0
0

Hi,

We’ve got a video player that gives us PCM samples via a callback that we’d like to push into FMOD to play. We’re attempting to use the lock/unlock method (described as the solution for Bink video).

The problem I’m having is filling the FMOD sound buffer while the video player’s samples come in. Is there a better way to add to the buffer than unlocking the entire buffer and copying into it? There doesn’t seem to be a way to know how much of the buffer has been played, so that I can write into that point (or before it for a looping sound). Additionally, is looping the right way to stream this? I can’t see another way to continuously play a sound while I feed into the buffer.

Any general advice is welcome!

Thanks,
Christopher Redden
doublesix games

  • You must to post comments
0
0

Well I’ve had a little success with the lock/unlock and writing into the buffer doing this:

[code:20vzki9p]insertData( float** data, int nSamples )
{
typedef S16 sample; //16-bit
U32 liSoundLength = 0;
mpSound->getLength( &liSoundLength, FMOD_TIMEUNIT_PCMBYTES );

U32 liInsertLengthBytes = nSamples * mNumChannels * miSampleSize;

// Lock
U32 liLen1 = 0;
U32 liLen2 = 0;
void* lpPtr1 = 0;
void* lpPtr2 = 0;
mpSound->lock( miPrevPlayPos, liInsertLengthBytes, &lpPtr1, &lpPtr2, &liLen1, &liLen2 );

sample* lpSampleTarget1 = (sample*)lpPtr1;
sample* lpSampleTarget2 = (sample*)lpPtr2;
for( int i = 0; i < nSamples; i += 2 )
{
    if( i * miSampleSize < liLen1 )
    {
        lpSampleTarget1[ i ] = float2short( data[0][i] );
        lpSampleTarget1[ i + 1 ] = float2short( data[1][i] );
    }
    else if( i * miSampleSize < liLen2 )
    {
        lpSampleTarget2[ i ] = float2short( data[0][i] );
        lpSampleTarget2[ i + 1 ] = float2short( data[1][i] );
    }
}

// Unlock and update play point
mpSound->unlock( lpPtr1, lpPtr2, liLen1, liLen2 );
miPrevPlayPos += liInsertLengthBytes;
miPrevPlayPos = ( miPrevPlayPos > liSoundLength ? 0 : miPrevPlayPos );

}[/code:20vzki9p]

I’m probably making a lot of incorrect assumptions, but it appears to be working timing wise, however the audio is really high pitch and I can’t determine why. If I save up the audio buffer and copy it all at once, it’s fine, but copying like this and it appears to be chipmunk voices. It sounds like it’s playing too fast, but it’s correct to the video just sounds fast.

  • You must to post comments
0
0

did you call setDefaults on the sound to make sure the sound plays at the right rate ? (also specified in FMOD_CREATESOUNDEXINFO).

  • You must to post comments
0
0

The frequency is being set in the FMOD_CREATESOUNDEXINFO, this hasn’t changed.

As I said: if I just store the whole audio stream into a buffer and copy in the same way (but at once) it plays back at normal speed. Why would changing the way I copy into the buffer affect the resulting sound speed/pitch?

  • You must to post comments
0
0

I thought i better resurect this thread instead of creating new one.
I have a little bit different problem. On my end, there is just no sound at all after i lock the buffer, fill it and unlock again. Just silence and no errors.
The initialization code is taken from here: viewtopic.php?f=18&t=14604
Loading and playing sounds from files works perfectly. But now i need to "stream" my sound data, taken from a third party video player (the same as the author used: Theora).

The setup looks like this:
[code:f1n5lvr8] FMOD_CREATESOUNDEXINFO info;
MemoryMgr::MemorySet(&info, 0, sizeof(FMOD_CREATESOUNDEXINFO));

info.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
info.numchannels = channelsCount;
info.defaultfrequency = frequencyValue;
info.format = FMOD_SOUND_FORMAT_PCMFLOAT;
info.length = channelsCount * sizeof(float) * frequencyValue * 5;

if (!CheckFMODError(SoundMgr::GetFMODSystem()->createSound(nullptr, FMOD_2D | FMOD_OPENUSER | FMOD_SOFTWARE, &info, &fmodSound), "Failed creating user stream"))
return;[/code:f1n5lvr8]
Then, in the "right moment" (when the third party player asks for it) i just lock the buffer, fill it and unlock:
[code:f1n5lvr8]const bool SoundStream::Lock(const unsigned long samples)
{
const unsigned long size = channelsCount * sizeof(float) * samples;
return(CheckFMODError(fmodSound->lock(0, size, &lockedMemory1, &lockedMemory2, &lockedSize1, &lockedSize2), "Failed locking sound buffer"));
}[/code:f1n5lvr8]
[code:f1n5lvr8] if (!soundStream.Lock(nSamples))
return;
MemoryMgr::MemoryCopy(data, soundStream.GetLockedMemory(), soundStream.GetLockedSize());
soundStream.Unlock();[/code:f1n5lvr8]
The SoundStream::GetLockedMemory() and SoundStream::GetLockedSize() return the first pointer and first size from the Sound::lock() function (e.g. lockedMemory1 and lockedSize1) correspondingly.
The code executes almost fine – no errors and no sounds.
I can’t use callbacks, because they might happen at wrong time points, that’s why i try to use lock/unlock method.

Is there anything i forgot to do? Or just it simly works the other way? Samples (that comes with FMOD) show only the reading part of lock/unlock functions. Not writing. And for custom sounds they use callbacks only.

P.S.
The data comes as floats in the range [-1; 1] with a 44100 frequency and 2 channels.

  • You must to post comments
0
0

Anyone?

  • You must to post comments
0
0

Please? I can’t believe that nobody tried this way…

  • You must to post comments
0
0

Aaaand i’m bumping up again!

  • You must to post comments
0
0

I ca$per,
Have you find a solution? I have the same problems.

Cheers

Stefano

  • You must to post comments
0
0

Nope. And it’s very strange that no one from FMOD team have commented anything.

  • You must to post comments
Showing 9 results
Your Answer

Please first to submit.