mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-09-04 11:44:45 +03:00
397 lines
11 KiB
C++
397 lines
11 KiB
C++
/*===============================================================================================
|
|
Record example
|
|
Copyright (c), Firelight Technologies Pty, Ltd 2004-2016.
|
|
|
|
This example shows how to record a sound, then write it to a wav file.
|
|
It then shows how to play a sound while it is being recorded to. Because it is recording, the
|
|
sound playback has to be delayed a little bit so that the playback doesn't play part of the
|
|
buffer that is still being written to.
|
|
===============================================================================================*/
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <conio.h>
|
|
|
|
#include "../../api/inc/fmod.hpp"
|
|
#include "../../api/inc/fmod_errors.h"
|
|
|
|
void ERRCHECK(FMOD_RESULT result)
|
|
{
|
|
if (result != FMOD_OK)
|
|
{
|
|
printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
#if defined(WIN32) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
|
|
#define __PACKED /* dummy */
|
|
#else
|
|
#define __PACKED __attribute__((packed)) /* gcc packed */
|
|
#endif
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Writes out the contents of a record buffer to a file.
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
void
|
|
|
|
[REMARKS]
|
|
]
|
|
*/
|
|
void SaveToWav(FMOD::Sound *sound)
|
|
{
|
|
FILE *fp;
|
|
int channels, bits;
|
|
float rate;
|
|
void *ptr1, *ptr2;
|
|
unsigned int lenbytes, len1, len2;
|
|
|
|
if (!sound)
|
|
{
|
|
return;
|
|
}
|
|
|
|
sound->getFormat (0, 0, &channels, &bits);
|
|
sound->getDefaults(&rate, 0, 0, 0);
|
|
sound->getLength (&lenbytes, FMOD_TIMEUNIT_PCMBYTES);
|
|
|
|
{
|
|
#if defined(WIN32) || defined(_WIN64) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
|
|
#pragma pack(1)
|
|
#endif
|
|
|
|
/*
|
|
WAV Structures
|
|
*/
|
|
typedef struct
|
|
{
|
|
signed char id[4];
|
|
int size;
|
|
} RiffChunk;
|
|
|
|
struct
|
|
{
|
|
RiffChunk chunk __PACKED;
|
|
unsigned short wFormatTag __PACKED; /* format type */
|
|
unsigned short nChannels __PACKED; /* number of channels (i.e. mono, stereo...) */
|
|
unsigned int nSamplesPerSec __PACKED; /* sample rate */
|
|
unsigned int nAvgBytesPerSec __PACKED; /* for buffer estimation */
|
|
unsigned short nBlockAlign __PACKED; /* block size of data */
|
|
unsigned short wBitsPerSample __PACKED; /* number of bits per sample of mono data */
|
|
} FmtChunk = { {{'f','m','t',' '}, sizeof(FmtChunk) - sizeof(RiffChunk) }, 1, channels, (int)rate, (int)rate * channels * bits / 8, 1 * channels * bits / 8, bits } __PACKED;
|
|
|
|
struct
|
|
{
|
|
RiffChunk chunk;
|
|
} DataChunk = { {{'d','a','t','a'}, lenbytes } };
|
|
|
|
struct
|
|
{
|
|
RiffChunk chunk;
|
|
signed char rifftype[4];
|
|
} WavHeader = { {{'R','I','F','F'}, sizeof(FmtChunk) + sizeof(RiffChunk) + lenbytes }, {'W','A','V','E'} };
|
|
|
|
#if defined(WIN32) || defined(_WIN64) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
|
|
#pragma pack()
|
|
#endif
|
|
|
|
fp = fopen("record.wav", "wb");
|
|
|
|
/*
|
|
Write out the WAV header.
|
|
*/
|
|
fwrite(&WavHeader, sizeof(WavHeader), 1, fp);
|
|
fwrite(&FmtChunk, sizeof(FmtChunk), 1, fp);
|
|
fwrite(&DataChunk, sizeof(DataChunk), 1, fp);
|
|
|
|
/*
|
|
Lock the sound to get access to the raw data.
|
|
*/
|
|
sound->lock(0, lenbytes, &ptr1, &ptr2, &len1, &len2);
|
|
|
|
/*
|
|
Write it to disk.
|
|
*/
|
|
fwrite(ptr1, len1, 1, fp);
|
|
|
|
/*
|
|
Unlock the sound to allow FMOD to use it again.
|
|
*/
|
|
sound->unlock(ptr1, ptr2, len1, len2);
|
|
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
FMOD::System *system = 0;
|
|
FMOD::Sound *sound = 0;
|
|
FMOD::Channel *channel = 0;
|
|
FMOD_RESULT result;
|
|
FMOD_CREATESOUNDEXINFO exinfo;
|
|
int key, driver, recorddriver, numdrivers, count;
|
|
unsigned int version;
|
|
|
|
/*
|
|
Create a System object and initialize.
|
|
*/
|
|
result = FMOD::System_Create(&system);
|
|
ERRCHECK(result);
|
|
|
|
result = system->getVersion(&version);
|
|
ERRCHECK(result);
|
|
|
|
if (version < FMOD_VERSION)
|
|
{
|
|
printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
System initialization
|
|
*/
|
|
printf("---------------------------------------------------------\n");
|
|
printf("Select OUTPUT type\n");
|
|
printf("---------------------------------------------------------\n");
|
|
printf("1 : DirectSound\n");
|
|
printf("2 : Windows Multimedia WaveOut\n");
|
|
printf("3 : ASIO\n");
|
|
printf("4 : WASAPI (Vista only)\n");
|
|
printf("---------------------------------------------------------\n");
|
|
printf("Press a corresponding number or ESC to quit\n");
|
|
|
|
do
|
|
{
|
|
key = _getch();
|
|
} while (key != 27 && key < '1' && key > '5');
|
|
|
|
switch (key)
|
|
{
|
|
case '1' : result = system->setOutput(FMOD_OUTPUTTYPE_DSOUND);
|
|
break;
|
|
case '2' : result = system->setOutput(FMOD_OUTPUTTYPE_WINMM);
|
|
break;
|
|
case '3' : result = system->setOutput(FMOD_OUTPUTTYPE_ASIO);
|
|
break;
|
|
case '4' : result = system->setOutput(FMOD_OUTPUTTYPE_WASAPI);
|
|
break;
|
|
default : return 1;
|
|
}
|
|
ERRCHECK(result);
|
|
|
|
/*
|
|
Enumerate playback devices
|
|
*/
|
|
|
|
result = system->getNumDrivers(&numdrivers);
|
|
ERRCHECK(result);
|
|
|
|
printf("---------------------------------------------------------\n");
|
|
printf("Choose a PLAYBACK driver\n");
|
|
printf("---------------------------------------------------------\n");
|
|
for (count=0; count < numdrivers; count++)
|
|
{
|
|
char name[256];
|
|
|
|
result = system->getDriverInfo(count, name, 256, 0);
|
|
ERRCHECK(result);
|
|
|
|
printf("%d : %s\n", count + 1, name);
|
|
}
|
|
printf("---------------------------------------------------------\n");
|
|
printf("Press a corresponding number or ESC to quit\n");
|
|
|
|
do
|
|
{
|
|
key = _getch();
|
|
if (key == 27)
|
|
{
|
|
return 0;
|
|
}
|
|
driver = key - '1';
|
|
} while (driver < 0 || driver >= numdrivers);
|
|
|
|
result = system->setDriver(driver);
|
|
ERRCHECK(result);
|
|
|
|
/*
|
|
Enumerate record devices
|
|
*/
|
|
|
|
result = system->getRecordNumDrivers(&numdrivers);
|
|
ERRCHECK(result);
|
|
|
|
printf("---------------------------------------------------------\n");
|
|
printf("Choose a RECORD driver\n");
|
|
printf("---------------------------------------------------------\n");
|
|
for (count=0; count < numdrivers; count++)
|
|
{
|
|
char name[256];
|
|
|
|
result = system->getRecordDriverInfo(count, name, 256, 0);
|
|
ERRCHECK(result);
|
|
|
|
printf("%d : %s\n", count + 1, name);
|
|
}
|
|
printf("---------------------------------------------------------\n");
|
|
printf("Press a corresponding number or ESC to quit\n");
|
|
|
|
recorddriver = 0;
|
|
do
|
|
{
|
|
key = _getch();
|
|
if (key == 27)
|
|
{
|
|
return 0;
|
|
}
|
|
recorddriver = key - '1';
|
|
} while (recorddriver < 0 || driver >= numdrivers);
|
|
|
|
printf("\n");
|
|
|
|
result = system->init(32, FMOD_INIT_NORMAL, 0);
|
|
ERRCHECK(result);
|
|
|
|
memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
|
|
|
|
exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
|
|
exinfo.numchannels = 1;
|
|
exinfo.format = FMOD_SOUND_FORMAT_PCM16;
|
|
exinfo.defaultfrequency = 44100;
|
|
exinfo.length = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 5;
|
|
|
|
result = system->createSound(0, FMOD_2D | FMOD_SOFTWARE | FMOD_OPENUSER, &exinfo, &sound);
|
|
ERRCHECK(result);
|
|
|
|
printf("===================================================================\n");
|
|
printf("Recording example. Copyright (c) Firelight Technologies 2004-2016.\n");
|
|
printf("===================================================================\n");
|
|
printf("\n");
|
|
printf("Press 'r' to record a 5 second segment of audio and write it to a wav file.\n");
|
|
printf("Press 'p' to play the 5 second segment of audio.\n");
|
|
printf("Press 'l' to turn looping on/off.\n");
|
|
printf("Press 's' to stop recording and playback.\n");
|
|
printf("Press 'w' to save the 5 second segment to a wav file.\n");
|
|
printf("Press 'Esc' to quit\n");
|
|
printf("\n");
|
|
|
|
/*
|
|
Main loop.
|
|
*/
|
|
do
|
|
{
|
|
static FMOD::Channel *channel = 0;
|
|
static bool looping = false;
|
|
bool recording = false;
|
|
bool playing = false;
|
|
unsigned int recordpos = 0;
|
|
unsigned int playpos = 0;
|
|
unsigned int length;
|
|
|
|
if (_kbhit())
|
|
{
|
|
key = _getch();
|
|
|
|
switch (key)
|
|
{
|
|
case 'r' :
|
|
case 'R' :
|
|
{
|
|
result = system->recordStart(recorddriver, sound, looping);
|
|
ERRCHECK(result);
|
|
break;
|
|
}
|
|
case 'p' :
|
|
case 'P' :
|
|
{
|
|
if (looping)
|
|
{
|
|
sound->setMode(FMOD_LOOP_NORMAL);
|
|
}
|
|
else
|
|
{
|
|
sound->setMode(FMOD_LOOP_OFF);
|
|
}
|
|
ERRCHECK(result);
|
|
|
|
result = system->playSound(FMOD_CHANNEL_REUSE, sound, false, &channel);
|
|
ERRCHECK(result);
|
|
break;
|
|
}
|
|
case 'l' :
|
|
case 'L' :
|
|
{
|
|
looping = !looping;
|
|
break;
|
|
}
|
|
case 's' :
|
|
case 'S' :
|
|
{
|
|
result = system->recordStop(recorddriver);
|
|
if (channel)
|
|
{
|
|
channel->stop();
|
|
channel = 0;
|
|
}
|
|
break;
|
|
}
|
|
case 'w' :
|
|
case 'W' :
|
|
{
|
|
printf("Writing to record.wav ... \r");
|
|
|
|
SaveToWav(sound);
|
|
Sleep(500);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
sound->getLength(&length, FMOD_TIMEUNIT_PCM);
|
|
ERRCHECK(result);
|
|
|
|
system->isRecording(recorddriver, &recording);
|
|
ERRCHECK(result);
|
|
|
|
system->getRecordPosition(recorddriver, &recordpos);
|
|
ERRCHECK(result);
|
|
|
|
if (channel)
|
|
{
|
|
channel->isPlaying(&playing);
|
|
ERRCHECK(result);
|
|
|
|
channel->getPosition(&playpos, FMOD_TIMEUNIT_PCM);
|
|
ERRCHECK(result);
|
|
}
|
|
|
|
printf("State: %-19s. Record pos = %6d : Play pos = %6d : Loop %-3s\r", recording ? playing ? "Recording / playing" : "Recording" : playing ? "Playing" : "Idle", recordpos, playpos, looping ? "On" : "Off");
|
|
|
|
system->update();
|
|
|
|
Sleep(10);
|
|
|
|
} while (key != 27);
|
|
|
|
printf("\n");
|
|
|
|
/*
|
|
Shut down
|
|
*/
|
|
result = sound->release();
|
|
ERRCHECK(result);
|
|
|
|
result = system->release();
|
|
ERRCHECK(result);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|