latency time when recording audio


(wenyu) #1

When I record audio to a wav file,first time, the wave is all right.But from the second time, the wave become wrong.There is about 0.4s empty audio in the head of the wave.the code is like below.

    FMOD_RESULT result;
unsigned int   datalength = 0, soundlength;
FILE      *fp;

uint length;

float volume;

bool mute;

m_result = system->init(32, FMOD_INIT_NORMAL, 0);

FMOD_CREATESOUNDEXINFO exinfo;
memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));

exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.numchannels = m_iChannels;
exinfo.format = FMOD_SOUND_FORMAT_PCM16;
exinfo.defaultfrequency = m_iSampleRate;
exinfo.length = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels;
result = system->createSound(0, FMOD_2D |FMOD_OUTPUTTYPE_WINMM| FMOD_OPENUSER, &exinfo, &sound);
result = system->recordStart(recorddriver, sound, true);
if (result != FMOD_OK)
{
	emit sigDriveErr();
	return;
}
	

fp = fopen(fileName.toStdString().c_str(), "wb");
if (!fp)
{
	printf("ERROR : could not open record.wav for writing.\n");
	return;
}

/*
Write out the wav header.  As we don't know the length yet it will be 0.
*/
WriteWavHeader(fp, sound, datalength);

result = sound->getLength(&soundlength, FMOD_TIMEUNIT_PCM);
ERRCHECK(result);
QVector<float> waveData;

do
{
	static unsigned int lastrecordpos = 0;
	static unsigned int index = 0;
	unsigned int recordpos = 0;
	system->getRecordPosition(recorddriver, &recordpos);
	ERRCHECK(result);

	if (recordpos != lastrecordpos)
	{
		void *ptr1, *ptr2;
		int blocklength;
		unsigned int len1, len2;

		blocklength = (int)recordpos - (int)lastrecordpos;
		if (blocklength < 0)
		{
			blocklength += soundlength;
		}

		/*
		Lock the sound to get access to the raw data.
		*/
		sound->lock(lastrecordpos * exinfo.numchannels * 2, blocklength * exinfo.numchannels * 2, &ptr1, &ptr2, &len1, &len2);   /* * exinfo.numchannels * 2 = stereo 16bit.  1 sample = 4 bytes. */																															 /*																															 Write it to disk.
																																 */
		if (ptr1 && len1)
		{
			datalength += fwrite(ptr1, 1, len1, fp);
			signed short *data = (signed short *)ptr1;
			
			/*for (int i = 0, n = 0; i < len1; i += step, n++) 
			{
			    waveData.append(data[n]);
			}
			index++;
			if (index % 5 == 0)
			{
				emit waveDataReceive(waveData);
				waveData.clear();
			}*/
		}
		if (ptr2 && len2)
		{
			datalength += fwrite(ptr2, 1, len2, fp);
			ushort *data = (ushort *)ptr2;
			//QVector<float> waveData;
			/*for (int i = 0, n = 0; i < len1; i += step, n++) 
			{
				waveData.append(data[n]);
			}
			index++;
			if (index % 5 == 0)
			{
				emit waveDataReceive(waveData);
				waveData.clear();
			}*/
		}

		/*
		Unlock the sound to allow FMOD to use it again.
		*/
		sound->unlock(ptr1, ptr2, len1, len2);
	}

	lastrecordpos = recordpos;


	system->update();

	Sleep(10);

} while (isStopWave != true);

WriteWavHeader(fp, sound, datalength);
fclose(fp);

(Brett Paterson) #2

its a pretty random thing to do to put FMOD_OUTPUTTYPE_WINMM in the middle of the mode bits that are supposed to only be from the FMOD_MODE list.

because FMOD_OUTPUTTYPE_WINMM = 7, the FMOD_MODE bits that it equivocates to are
#define FMOD_LOOP_OFF 0x00000001
#define FMOD_LOOP_NORMAL 0x00000002
#define FMOD_LOOP_BIDI 0x00000004
and FMOD_LOOP_OFF overides the other 2, so it would mean the sound would only play the start it it was played.

You said it has a delay, but from what I can see you haven’t posted the whole code.

Is recordStop called?


(wenyu) #3

When I delete FMOD_OUTPUTTYPE_WINMM choice,it is still wrong. I do not call recordStop function.Here is WriteWavHeader function code.

void WriteWavHeader(FILE *fp, FMOD::Sound *sound, int length)
{
int channels, bits;
float rate;

if (!sound)
{
	return;
}

fseek(fp, 0, SEEK_SET);

sound->getFormat(0, 0, &channels, &bits);
sound->getDefaults(&rate, 0);

{

#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' }, length } };

	struct
	{
		RiffChunk   chunk;
		signed char rifftype[4];
	} WavHeader = { { { 'R','I','F','F' }, sizeof(FmtChunk) + sizeof(RiffChunk) + length },{ 'W','A','V','E' } };

#if defined(WIN32) || defined(_WIN64) || defined(WATCOMC) || defined(_WIN32) || defined(WIN32)
#pragma pack()
#endif

	/*
	Write out the WAV header.
	*/
	fwrite(&WavHeader, sizeof(WavHeader), 1, fp);
	fwrite(&FmtChunk, sizeof(FmtChunk), 1, fp);
	fwrite(&DataChunk, sizeof(DataChunk), 1, fp);
}

}


(Brett Paterson) #4

the reason you have a delay is becase you are not stopping the record system and lock/write code at the same time. The 2nd time you are starting the file writing after it has already recorded something. You should stop/start each time.