Santi Onta??n wrote:
Hi,
I want to play a stereo OGG, WAV… files using SDL_sound + SDL_mixer. I
use SDL_sound to decode the OGG file and SDL_mixer to mix it with other
samples.
I’ve redefined the “musicplayer” playback in this way (assumes 16bit sound):
bool playing_music=true;
Sound_Sample *music_sample;
…
void myMusicPlayer(void *udata, Uint8 *stream, int len)
{
int i,act=0;
Sint16 *ptr2;
if (stream!=0) {
ptr2=(Sint16 )stream;
if (playing_music) {
while(act<len) {
if (music_sample!=0) {
/ Play a music file: /
if (music_sample->flags&SOUND_SAMPLEFLAG_EOF)) {
/ End of file: /
Sound_Rewind(music_sample);
} else {
/ In the middle of the file: */
int decoded=0;
Sint16 *ptr;
Sound_SetBufferSize(music_sample, len-act);
decoded=Sound_Decode(music_sample);
ptr=(Sint16 *)music_sample->buffer;
for(i=0;i<decoded;i+=2,ptr++,ptr2++)
*ptr2=((Sint32(*ptr)*Sint32(music_volume))/127);
act+=decoded;
} /* if */
} else {
/* No music file loaded: */
for(i=act;i<len;i++) stream[i]=0;
act=len;
} /* if */
} /* while */
} else {
/* No music to play: */
for(i=0;i<len;i++) stream[i]=0;
} /* if */
} else {
fprintf(stderr,“ERROR in myMusicPlayer(): null music stream!!\n”);
} /* if /
} / myMusicPlayer */
But now, I want to extend it to be able to play stereo files, and I
don’t know how to do it, since the “Uint8 stream” is a single stream!
How do I have to fill it with the right and left channel data?
SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl
Code looks decent, but can likely be simplified… s’not a good idea to resize
the buffer every time you decode, for example…
In any case, there’s no need for worry - SDL_sound produces sound data in any
format requested without you having to worry about converting it in your own
code. As for how stereo works, it’s quite simple - they’re interleaved. Stored
as “right-left, right-left, right-left, …” Which, uncoincidentally, is
precisely how SDL wants it. Your decoder doesn’t even need to worry about what
format the music’s in, as long as it’s in an identical format to that of the
mixer… the pointers are Uint8 *'s simply out of convenience; the actual data
is in the format you requested. Lemme try rewriting this a bit…
#include <string.h>
#include “SDL_sound.h”
int playing_music=1; //plain C doesn’t have bool, used int instead
Sound_Sample *music_sample;
void myMusicPlayer(void *udata, Uint8 *stream, int len)
{
int size;
static int soundAvailable=0;
static int soundUsed=0;
//If we’re not playing, or there’s no sample loaded
if((!playing_music)||(music_sample==NULL))
{ //Fill stream with silence
memset(stream,0,len);
return;
}
while(len>0)
{ /* Play a music file: /
if (music_sample->flags&SOUND_SAMPLEFLAG_EOF))
{ / End of file: */
Sound_Rewind(music_sample);
}
//If we've used up the previously decoded sound:
if(soundAvailable==soundUsed)
{
soundUsed=0;
soundAvailable=Sound_Decode(music_sample);
if(soundAvailable==0)
{ //Go back to the top of the while look to catch EOF
continue;
}
else if(soundAvailable<0) //An error occured?
{ //Stop playing of music
playing_music=0;
soundAvailable=0;
soundUsed=0;
//Fill the remainder of the stream with silence
memset(stream,0,len);
return;
}
}
size=soundAvailable-soundUsed;
if(size>len) size=len; //Don't copy more than stream can hold
//Copy data into stream
memcpy(stream,((Uint8 *)(music_sample->buffer))+soundUsed,size);
//Decrement length
len-=size;
//Increment amount used, stream
soundUsed+=size;
stream+=size;
}
} /* myMusicPlayer */
That’s nearly verbatim the routine I’m using for my experiments with SDL_sound
streaming in SDL_mixer… it ought to work for any format, as long as the
format you specified in Sound_NewSample matches the mixer format.