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.
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.