(Time) Length of SDL_mixer chunks?

Hey,

is it possible to get the time length of a loaded chunk in SDL_mixer? In
seconds, ticks, or the like?

Thanks in advance,

martin–
Get my public GPG key from pgp.mit.edu or wwwkeys.pgp.net
Key ID: 0x44085D12

Homepage: http://mroot.net/
Powered by Gentoo Linux (http://gentoo.org/)
-------------- next part --------------
A non-text attachment was scrubbed…
Name: signature.asc
Type: application/pgp-signature
Size: 894 bytes
Desc: OpenPGP digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20051222/cfcbd8fc/attachment.pgp

is it possible to get the time length of a loaded chunk in SDL_mixer? In
seconds, ticks, or the like?

/* untested code follows… */
Uint32 getChunkTimeMilliseconds(Mix_Chunk chunk)
{
Uint32 points = 0;
Uint32 frames = 0;
int freq = 0;
Uint16 fmt = 0;
int chans = 0;
/
Chunks are converted to audio device format… /
if (!Mix_QuerySpec(&freq, &fmt, &chans))
return 0; /
never called Mix_OpenAudio()?! */

 /* bytes / samplesize == sample points */
 points = (chunk->alen / ((fmt & 0xFF) / 8));

 /* sample points / channels == sample frames */
 frames = (points / chans);

 /* (sample frames * 1000) / frequency == play length in ms */
 return (frames * 1000) / freq);

}

–ryan.

Hello.

Some days ago, Ryan answered my question on calculating the length of a
SDL_mixer chunk.

I’ve now tested the proposed code and I have strange results: Sometimes the
calculated length is correct, sometimes it differs from the length I found with
audacity.

CSoundEngine::loadSample : Loading sample ‘intro-thunder’ … (Length: 3345 ms,
calculated length: 2430 ms) done
CSoundEngine::loadSample : Loading sample ‘intro-grenade-0’ … (Length: 2253
ms, calculated length: 2253 ms) done
CSoundEngine::loadSample : Loading sample ‘intro-machine_gun-0’ … (Length: 888
ms, calculated length: 888 ms) done
CSoundEngine::loadSample : Loading sample ‘intro-machine_gun-1’ … (Length: 691
ms, calculated length: 501 ms) done

The samples have the format:

$ file intro-*.wav
intro-grenade-0.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8
bit, mono 11025 Hz
intro-machine_gun-0.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM,
16 bit, mono 11025 Hz
intro-machine_gun-1.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8
bit, mono 8000 Hz
intro-thunder.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8
bit, mono 8012 Hz

It seems as if there is a relation to the frequency of the files: Those with
11025 Hz work the other ones not.

You can download the files if probably you need them to help me here:

http://files.mgeek.de/intro-grenade-0.wav
http://files.mgeek.de/intro-machine_gun-0.wav
http://files.mgeek.de/intro-machine_gun-1.wav
http://files.mgeek.de/intro-thunder.wav

Thanks in advance for any help …

  • martin

I’ve now tested the proposed code and I have strange results: Sometimes the
calculated length is correct, sometimes it differs from the length I found with
audacity.

SDL_mixer (or spacifically, SDL_mixer’s call to SDL_ConvertAudio()
inside Mix_LoadWAV()) can’t resample audio well…it can only convert
audio frequencies that are powers of two in relation to the audio
device…so if your audio device is playing at 44100 Hz, it can resample
.wav files from 22050 or 11025 Hz but not 8000 Hz.

I think this is why you see a discrepancy. Do these sounds all playback
correctly? I’d imagine some sound funny, depending on how the mixer was
initialized.

It’s also possible that I screwed up the math in my original answer, but
it looks okay from here.

Ultimately, we should really find a way to fix SDL_ConvertAudio()
instead (apparently, the power of two restriction was intentional for
some reason).

–ryan.

Ultimately, we should really find a way to fix SDL_ConvertAudio()
instead (apparently, the power of two restriction was intentional for
some reason).

There are two reasons for it.
First, efficiency - when the code was written, floating point was too slow. :slight_smile:
Second, many hardware drivers only allow power of two buffers for audio DMA,
so the final output rate would change the size of the input buffer, instead
of it being possible to calculate as a function of the input format.

e.g. an app might request 44.1KHz stereo data with a buffer size of 1024
samples, and reasonably expect a buffer size of 4096 bytes, but if the output
rate is 48KHz, then we’d need to use a buffer size of 4096 bytes at 48KHz,
and we would need to call the audio callback at a slightly different rate
than the hardware update rate, and there isn’t an integer number of samples
at 44.1KHz that maps to 4096 bytes at 48KHz.

Did that make sense?

-Sam Lantinga, Senior Software Engineer, Blizzard Entertainment

Second, many hardware drivers only allow power of two buffers for audio DMA,
so the final output rate would change the size of the input buffer, instead
of it being possible to calculate as a function of the input format.

But, if SDL_mixer is as good an example as any: SDL_ConvertAudio() has
uses outside of the audio callback. Perhaps we should remove the
limitation generally and have SDL_OpenAudio() fail if the sample rate
isn’t a power of two? Maybe have SDL buffer data that would overflow the
hardware fragment size and give the audio callback a variable-sized
buffer when it has to make up the difference?

It seems that we should probably make this work cleanly behind the
scenes or at least give an error. Right now, people just get strange
results without any explanation as to why.

–ryan.

But, if SDL_mixer is as good an example as any: SDL_ConvertAudio() has
uses outside of the audio callback. Perhaps we should remove the
limitation generally and have SDL_OpenAudio() fail if the sample rate
isn’t a power of two? Maybe have SDL buffer data that would overflow the
hardware fragment size and give the audio callback a variable-sized
buffer when it has to make up the difference?

So let’s take the example in my previous e-mail… (keep in mind I’m
not a DSP expert, so let me know if I’m missing something obvious)

The audio driver gave you a DMA buffer of 4096 bytes of 16-bit stereo
audio at 48KHz, and you’re trying to fill it with 16-bit stereo audio
at 44.1KHz… How many samples should you request in the callback?

-Sam Lantinga, Senior Software Engineer, Blizzard Entertainment

44100 / 48000 * 4096 ==> alternating between 3763 atd 3764. (SDL
should report the maximum value, for application side buffer
allocation.)

For interpolation, you’ll also need to buffer a few samples
internally, for overlap.

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Friday 20 January 2006 02:52, Sam Lantinga wrote:

But, if SDL_mixer is as good an example as any: SDL_ConvertAudio()
has
uses outside of the audio callback. Perhaps we should remove the
limitation generally and have SDL_OpenAudio() fail if the sample
rate
isn’t a power of two? Maybe have SDL buffer data that would
overflow the
hardware fragment size and give the audio callback a
variable-sized
buffer when it has to make up the difference?

So let’s take the example in my previous e-mail… (keep in mind I’m
not a DSP expert, so let me know if I’m missing something obvious)

The audio driver gave you a DMA buffer of 4096 bytes of 16-bit
stereo
audio at 48KHz, and you’re trying to fill it with 16-bit stereo
audio
at 44.1KHz… How many samples should you request in the callback?

44100 / 48000 * 4096 ==> alternating between 3763 atd 3764. (SDL
should report the maximum value, for application side buffer
allocation.)

For interpolation, you’ll also need to buffer a few samples
internally, for overlap.

Okay, let’s do this. I’ve set up a bug so we can discuss and track this:
https://bugzilla.libsdl.org/show_bug.cgi?id=58

-Sam Lantinga, Senior Software Engineer, Blizzard Entertainment

Hello.

Don’t blame me because I have not that knowledge of playing sounds and
that stuff, but in my opinion, there must be a way to convort audio
files of any frequency to the freq or power of two of the device.
Filling with “empty” data or something. But maybe this is just
unawareness of the format specs …

And another thought: I have found no way to examine the frequency of an
audio file with SDL_mixer, is that right? In that case, it would do it
in my opinion to provide a function to get it, so the application can
decide how to handle non-conpliant frequencies.

Regards, martin

David Olofson wrote:> […]


Get my public GPG key from pgp.mit.edu or wwwkeys.pgp.net
Key ID: 0x44085D12

Homepage: http://mroot.net/
Powered by Gentoo Linux (http://gentoo.org/)

-------------- next part --------------
A non-text attachment was scrubbed…
Name: signature.asc
Type: application/pgp-signature
Size: 890 bytes
Desc: OpenPGP digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060120/9edb05e3/attachment.pgp

Don’t blame me because I have not that knowledge of playing sounds and
that stuff, but in my opinion, there must be a way to convort audio
files of any frequency to the freq or power of two of the device.
Filling with “empty” data or something. But maybe this is just
unawareness of the format specs …

We’re tracking this as an SDL issue now:
https://bugzilla.libsdl.org/show_bug.cgi?id=58

–ryan.

Any news on this? ie. Whether there is any conceivable way under SDL_Mixer to get the length of music or sounds?
Apologies for zombie-rising an old thread.

Any way to get the length? Lol