0
0

Hi

I am setting up a looping PCM buffer for the PC platform using:

buffer=malloc( 20*1024 );

memset(Sound,0);

Sound.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
Sound.length = 20*1024;
Sound.format = FMOD_SOUND_FORMAT_PCM16;
Sound.defaultfrequency = 48000;
Sound.numchannels = 1;

Mode=FMOD_OPENRAW|
FMOD_OPENMEMORY_POINT|
FMOD_SOFTWARE|
FMOD_LOOP_NORMAL;

sys->createSound( buffer , Mode , Sound , Voice );

sys->playSound( ….

This all works except for it’s not looping correctly. It seems that the voice will play samples 0 to 10240 (i.e. one extra sample) and not samples 0 to 10239 as expected.

I can fix my problem by setting Sound.length = (20*1024) – 2; but this seems wrong.

Any ideas?

Thanks

Andrew

  • You must to post comments
0
0

This is a most timely post, I was just composing a warning to my fellow developers on the same topic.

[b:1rrz4hyl]WARNING!![/b:1rrz4hyl] If you allocate your own looping PCM buffer, passing to createSound the magic combination of the following four mode flags:

[quote="AndrewHutchings":1rrz4hyl]Mode=FMOD_OPENRAW|
FMOD_OPENMEMORY_POINT|
FMOD_SOFTWARE|
FMOD_LOOP_NORMAL;

sys->createSound( buffer , Mode , Sound , Voice );
[/quote:1rrz4hyl]

then you [b:1rrz4hyl]MUST[/b:1rrz4hyl] allocate extra padding at the end of your buffer! Empirical evidence suggests that 8 bytes per channel is sufficient.

FURTHERMORE, the looping flag is not properly handled by createSound. You must also call [b:1rrz4hyl]setMode (FMOD_LOOP_NORMAL)[/b:1rrz4hyl] for it to work without clicking artifacts.

The reason is that FMOD copies the first sample of your buffer to the memory just after your last sample, to aid in rapid sample-rate interpolation. This copying takes place during the setMode call, and apparently not during createSound.

[size=75:1rrz4hyl](observed on 4.08.05 for Win32)[/size:1rrz4hyl]

  • You must to post comments
0
0

Hi

Surely even with the padding (which mine happened to have anyway), the fact is that a sample outside the bounds of the buffer is being played.

I only noticed this because my buffers have a sentinel number at either end that would cause a click when looping silence.

For now I am sticking with the workaround:

Sound.length = (201024) – (2Sound.numchannels);

And I can only assume Sound.lenght is in fact Sound.last_sample_is!

Thanks

Andrew

  • You must to post comments
0
0

I’m adding documentation to this effect now.

FMOD does read past the end of the sample, thats because it uses interpolation. ie. out[pos] = (in[pos] * (1-f)) + (in[pos+1] * f)

If not ‘pointing’ then fmod allocates extra bytes for this, and copies the start of the sound to that empty space, so it has something to interpolate with. This is is more efficient than writing some hack to interrupt the inner mixing loop with inefficient checks.

We’re just recommending padding the data before and after the sound with 16 bytes of memory for now.

  • You must to post comments
0
0

Hi Brett

Thanks for clarifying that, this makes sense now.

So for a perfect PCM loop I need to do something like:

S16* Buffer=Malloc( (SampleCount + 1) * 2 );

Sound.lenght = SampleCount * 2;

And then copy Buffer[0] into Buffer[SampleCount]?

Also the PCM buffers we are creating are having their sample data dynamically modified by external processes using Channel->getPosition to control the data flow. Are there any other problems this might cause or should the above workaround suffice.

Thanks

Andrew

  • You must to post comments
0
0

if you modify data that is on loop point boundaries and fmod doesnt know about it, you will get clicks. That is what Sound::lock/Sound::unlock is for using a normal sample so that it can fix the data up after you’ve modified it.

  • You must to post comments
Showing 5 results
Your Answer

Please first to submit.