If fmod can play the audio in a video file?

We use webm video format in our game,which the audio part of it is ogg.
I separatede the video and audio data by using libwebm.
Can I use fmod to play the audio data?
libwebm parse the file piece by piece. So I can’t get the whole audio data at the beginnning.
Is there any examples if fmod support this?

Oh,There do have a race condition. It’s my fault.
I have fixed this error and play both sounds and pictures.
Thanks for your help.

This is off-topic, but there is a race condition in the code sample you posted. You should be calling ResetEvent inside the first critical section block e.g. if ( bAudioFrameQueueEmpty ) ResetEvent(…);

For the second question, createStream() is the correct function to be calling.

1 Like

Thanks for your reply.
I have played the sound in this way.
But I met another problem when I try to play both pictures and sounds.
Don’t consider synching picture with sound.Main thread decode the image and display it.
When meeting a audio frame,it put the audio frame into a queue.
PCMCALLBACK pick data from the queue.It will wait if there is not enough data in the queue.

			
//put the audio frame in a std::deque  (main thread)
else if(pTrack->GetType() == mkvparser::Track::kAudio)
{
				const mkvparser::Block::Frame& Frame = block_ptr->GetFrame(m_frame_state.m_frame_idx);
				const mkvparser::Block::Frame* pFrame = &Frame;
				
				EnterCriticalSection(&g_AudioC_S);
				m_AudioFrameDeque.push_back(pFrame);

				std::deque<const mkvparser::Block::Frame*>::size_type size = m_AudioFrameDeque.size();

				if (size > 20)
				{
					SetEvent(g_hAudioDequeEvent);
				}

				LeaveCriticalSection(&g_AudioC_S);
}//kAudio
// pick data from deque  (PCMCALLBACK)
	while ( datalen > 0 )
	{
		EnterCriticalSection(&g_AudioC_S);

		bAudioFrameQueueEmpty = m_AudioFrameDeque.empty();

		LeaveCriticalSection(&g_AudioC_S);
		
		if ( bAudioFrameQueueEmpty )
		{
			WaitForSingleObject(g_hAudioDequeEvent, INFINITE);

			ResetEvent(g_hAudioDequeEvent);

			if (g_bQuit)
			{
				return -1;
			}
		}

		EnterCriticalSection(&g_AudioC_S);

		std::deque<const mkvparser::Block::Frame*>::size_type size = m_AudioFrameDeque.size();
		if ( size <= 0 )
		{
		}

		const mkvparser::Block::Frame* pFrame = m_AudioFrameDeque.front();
		m_AudioFrameDeque.pop_front();

		LeaveCriticalSection(&g_AudioC_S);
             
               ...

         }

But sometimes WaitForSingleObject can’t block the thread when g_hAudioDequeEvent is non-signaled, even through the return value is WAIT_OBJECT_0. Then lead to an error.
This is only two place used the deque and g_hAudioDequeEvent EVENT.

Another question is

Here is how I create the Sound

	FMOD_CREATESOUNDEXINFO infopcm;
	memset(&infopcm, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	infopcm.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
	infopcm.numchannels = 2;
	infopcm.defaultfrequency = 44100;
	infopcm.decodebuffersize = 0;
	infopcm.length = infopcm.defaultfrequency * infopcm.numchannels * 4 * kvm_r.GetAudioDurationInSecond();
	infopcm.format = FMOD_SOUND_FORMAT_PCMFLOAT;
	infopcm.pcmreadcallback = pcmreadcallback;
	infopcm.pcmsetposcallback = pcmsetposcallback;

	result = g_pFmodSystem->createStream(0, 
		FMOD_OPENUSER | FMOD_LOOP_OFF | FMOD_2D | FMOD_OPENONLY, &infopcm, &sound);
	if ( result != FMOD_OK )
	{
		printf("FMOD::System::createStream failed");
	}
	result = g_pFmodSystem->playSound(sound, 0, false, &channel);
	if ( result != FMOD_OK )
	{
		printf("FMOD::System::playSound failed");
	}

After turn result = g_pFmodSystem->createStream(…) to
result = g_pFmodSystem->createSound(…)

PCMCALLBACK is not invoked anymore.

And The audio data parsed by libwebm is still ogg data,not decoded.
thanks in advance

I have a look at user_created_sound example. Looks like FMOD_SOUND_PCMREADCALLBACK can achieve what I want.
But I have two questions here.
I read a ogg file into memory and want to use PCMREADCALLBACK to play it.I do this just want to learn how to use PCMREADCALLBACK.
It can be played in FMOD_OPENMEMORY mode with nothing wrong.
But there is only noise in FMOD_OPENUSER mode.

//read the file into memory
BYTE* bufferpcm = 0;
unsigned int havereadpcm = 0;
	FILE* filepcm = NULL;
	fopen_s( &filepcm, "20_cairo.ogg", "rb" );
	fseek( filepcm, 0, SEEK_END );
	long lenpcm = ftell( filepcm );
	fseek( filepcm, 0, SEEK_SET );
	bufferpcm = (BYTE*)malloc( lenpcm );
	fread( bufferpcm, 1, lenpcm, filepcm );
	fclose( filepcm );

	FMOD_CREATESOUNDEXINFO infopcm;
	memset(&infopcm, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	infopcm.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
	infopcm.numchannels = 2;
	infopcm.defaultfrequency = 44100;
	infopcm.decodebuffersize = 44100;
	infopcm.length = (unsigned int)lenpcm;
	infopcm.format = FMOD_SOUND_FORMAT_PCM16;
	infopcm.pcmreadcallback = pcmreadcallback;
	infopcm.pcmsetposcallback = pcmsetposcallback;
	infopcm.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS;

	FMOD::Sound* pPCMSound = NULL;
	FMOD::Channel* pPCMChannel = NULL;
	FMOD_RESULT result;
	result = m_pFmodSystem->createSound(0, FMOD_OPENUSER|FMOD_CREATESTREAM, &infopcm, &pPCMSound);
	if ( FMOD_OK == result )
	{		
		result = m_pFmodSystem->playSound(pPCMSound, 0, false, &pPCMChannel);
		if (result != FMOD_OK)
		{
			return -1;
		}
	}

//PCMREADCALLBACK
FMOD_RESULT F_CALLBACK pcmreadcallback(FMOD_SOUND* sound, void* data, unsigned int datalen)
{
	memcpy(data, (bufferpcm + havereadpcm), datalen);
	havereadpcm += datalen;
	return FMOD_OK;
}

FMOD_RESULT F_CALLBACK pcmsetposcallback(FMOD_SOUND* sound, int subsound, unsigned int position, FMOD_TIMEUNIT posttype)
{
	return FMOD_OK;
}

I don’t understand where’s wrong.

And the other qustion, I notice that the first param of createSound is 0 in FMOD_OPENUSER.
But sometimes it play more than one video at the same time in our game.
what should I do?

I have a look at manaualdecode example in fmodex sdk.(Just a suggestion, please supplement examples in fmod api sdk if you have time.Newbie like me which never use fmodex before don’t even know there are so many examples)
My understanding is I can’t pass encoded data to PCMREADCALLBACK, data come from Sound::readData have been decoded by fmod.So my previous code is wrong.
But libwebm parse the video file piece by piece so I can’t get the whole audio file at the beginning.
Because fmod can decode a ogg file and play it, I think I do not must use libvorbis to decode the data then pass it to PCMREADCALLBACK.
But how to do?
I believe that someone here must have this kind of experience.
Any advice is appreciated.

WebM does not contain ogg data, it contains vorbis data. Ogg is a container format, vorbis is an audio codec. FMOD cannot decode raw vorbis data, it can only decode it from within a container such as ogg or fsb (our own container format).

If you use libvorbis to decode vorbis to PCM you can feed it to FMOD piece-wise using the PCMREADCALLBACK.