[SDL] Stereo files with SDL_mixer + SDL_sound

Corona688 tsm at accesscomm.ca
Tue Jan 14 10:07:02 PST 2003


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.





More information about the SDL mailing list