FilePlayer::fadeVolume take a length in seconds rather than sample frames

,

Hi all,

I'm working on a game that plays music via the FilePlayer and either I have missed something or noticed what is hopefully a pretty simple quirk to resolve with the fadeVolume method. The issue is the following:

  • There is no way to retrieve the sampling rate in Hz of the underlying audio file for a FilePlayer (setRate/getRate are for a rate scalar).
  • fadeVolume requires a length in samples, but such a length is going to typically be computed as samplingRateHz * lengthSecs.
  • Since there is no way to find samplingRateHz it must be hard-coded.

fadeVolume seems like an outlier in that other methods like setOffset/getOffset take a float value in seconds. Assuming I'm not missing something, there are two relatively simple ways to make this interface nicer:

  1. Add a method like getSamplingRate for retrieving the sampling rate in Hertz so users can perform the length calculation needed.
  2. Add a variant of fadeVolume that takes a float length in seconds so users don't have to worry about this at all.
4 Likes

What a coincidence, I was just about to create this request!

Since it is not immediately clear from you post, please the tag C (or was it c-api?) to specify you want this in C.

Note: if people want this in lua; it is available in playdate.sound.fileplayer:setVolume(left, [right, [fadeSeconds, [fadeCallback, [arg]]]])

For consistency with the C api, one approach might be to implement the equivalent of AudioSample::getData, but for FilePlayer

void playdate->sound->sample->getData(AudioSample* sample, uint8_t** data, SoundFormat* format, uint32_t* sampleRate, uint32_t* bytelength)
1 Like

I agree this would be nice! every other function here takes seconds, offset, loopRange, etc.

Currently I have a utility :

int32_t seconds_to_samples(float seconds)
{
    return floorf(44100 * seconds);
}
fplayer->fadeVolume(musicSound, 0, 0, seconds_to_samples(1.5f), NULL, NULL);

But it's based only in the fact that currently the samplerate is locked at 44100 according to the lua docs...
GetSampleRate()

Returns the sample rate of the audio system (44100). The sample rate is determined by the hardware, and is not currently mutable.

2 Likes

Thanks for that utility function. Does it also work when your audio files are encoded using 22khz?

In other words: does the fadeVolume function expect to receive the number of samples in the audio file or the number of samples according to the sound system?

1 Like

Does that work on playdate? or does pdc duplicate the samples when compiling?
Or is it possible to compensate and set the playback rate to 0.5?

(I would expect it's according to the sound system as it has its own timing system)

Just tested with 22050 and it still works.

(looking at the compiled audio inside the pdx, it looks like the compiler is duplicating every sample up to 44100)
so storing your audio at 22050 doesn't actually save you any space in the build...

I'm not entirely sure what happened here. My guess is that I originally had everything using sample offsets and then decided it was okay (and friendlier) to use seconds instead, and missed this function when I made the change. sampleplayer->setPlayRange() is also still using samples, though I wonder if accuracy is critical there? No, it wouldn't be--we don't have enough memory for samples where that would be a problem, first precision error is at 16M.

I've filed an issue on that. I'll probably make separate replacement functions instead of changing the behavior of the existing function. Don't love the idea of having it change on people unawares.

As far as computing the length with 44100*seconds, yes that will work regardless of the file's sample rate. It's doing the fading on the render side after the sample rate conversion.

3 Likes

Is it possible you're looking at a stereo file with identical samples in left and right? For 8 and 16 bit data, the compiler doesn't even touch the sample data, just plonks a new header on the file. For 24 bit it chops it down to 16, but still doesn't change the sample rate. I just double-checked with a mono 11kHz file and see the same sample data in the pda as in the wav.

1 Like

Hmm, I'll take another look. I was using a Mono wav of my menu music. I must have missed something. Thanks for the response!

Yeah, changing the existing function would be very much breaking, since you will be using float instead of int, and C doesn't have overloading

1 Like