sdl@lists.libsdl.org
[Top] [All Lists]

Re: [SDL] SDL_audio code..no need for function parameters?????? Help ple

Subject: Re: [SDL] SDL_audio code..no need for function parameters?????? Help please
From: Holmes Futrell
Date: Fri, 17 Oct 2008 11:34:10 -0700
Hello,

That line of code does not call the audio callback function. What the line of code DOES do is that it sets the audio callback function to the fillerup function. Later on when SDL (periodically) needs more audio data, SDL asks, hey what is my callback function, and finds that it has been set to fillerup. SDL then calls the fillerup function so obtain the needed audio data.

From your query it sounds like you might not be familiar with function pointers (wave.spec.callback is a function pointer), so here is a reference:
http://www.newty.de/fpt/index.html

- Holmes

On Oct 17, 2008, at 11:21 AM, Anonymous wrote:

----In the code below, I'm wondering why the function fillerup can be called
like this ONLY:

wave.spec.callback = fillerup;


----When the function itself takes the form:

void SDLCALL fillerup(void *unused, Uint8 *stream, int len)




Doesn't it need parameters or arguments???
-----------------------------------------------------------------------------


/* Program to load a wave file and loop playing it using SDL sound */

/* loopwaves.c is much more robust in handling WAVE files --
        This is only for simple WAVEs
*/
#include "SDL_config.h"

#include <stdio.h>
#include <stdlib.h>

#if HAVE_SIGNAL_H
#include <signal.h>
#endif

#include "SDL.h"
#include "SDL_audio.h"

static double volume = 1.0f;
struct {
        SDL_AudioSpec spec;
        Uint8   *sound;                 /* Pointer to wave data */
        Uint32   soundlen;              /* Length of wave data */
        int      soundpos;              /* Current play position */
} wave;


static int done = 0;
void poked(int sig)
{
        done = 1;
}

/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void quit(int rc)
{
        SDL_Quit();
        exit(rc);
}

/* Process the audio buffer, here only adjust the volume. */
void process_audio(Uint8 *audio_buf, int buf_size) {
        int i;
   switch (wave.spec.format) {
   case AUDIO_U8: {
       // unsigned 8-bit sample
       Uint8 *ptr = (Uint8 *)audio_buf;
       if (wave.spec.channels == 1) {
           // process mono audio
           for (i=0; i<buf_size; i += sizeof(Uint8)) {
               double tmp = (*ptr) * volume;
               tmp = tmp > 255.0 ? 255.0 : tmp;
               *ptr = (Uint8)tmp;
               ptr++;
           }
       } else if (wave.spec.channels == 2) {
           // process stero audio
           for (i=0; i<buf_size; i += sizeof(Uint8)*2) {
               // process left channel
               double tmp = (*ptr) * volume;
               tmp = tmp > 255.0 ? 255.0 : tmp;
               *ptr = (Uint8)tmp;
               ptr++;

               // process right channel
               tmp = (*ptr) * volume;
               tmp = tmp > 255.0 ? 255.0 : tmp;
               *ptr = (Uint8)tmp;
               ptr++;
           }
       } else {
           fprintf(stderr, "Doesn't support more than 2 channels!\n");
           exit(1);
       }
       break; }
   case AUDIO_S8: {
       // signed 8-bit sample
       Sint8 *ptr = (Sint8 *)audio_buf;
       if (wave.spec.channels == 1) {
           // process mono audio
           for (i=0; i<buf_size; i += sizeof(Sint8)) {
               double tmp = (*ptr) * volume;
               tmp = tmp > 127.0 ? 127.0 : tmp;
               tmp = tmp < -128.0 ? -128.0 : tmp;
               *ptr = (Sint8)tmp;
               ptr++; // note here ptr will move to 8 bits higher
           }
       } else if (wave.spec.channels == 2) {
           // process stero audio
           for (i=0; i<buf_size; i += sizeof(Uint8)*2) {
               // process left channel
               double tmp = (*ptr) * volume;
               tmp = tmp > 127.0 ? 127.0 : tmp;
               tmp = tmp < -128.0 ? -128.0 : tmp;
               *ptr = (Sint8)tmp;
               ptr++;

               // process right channel
               tmp = (*ptr) * volume;
               tmp = tmp > 127.0 ? 127.0 : tmp;
               tmp = tmp < -128.0 ? -128.0 : tmp;
               *ptr = (Sint8)tmp;
               ptr++;
           }
       } else {
           fprintf(stderr, "Doesn't support more than 2 channels!\n");
           exit(1);
       }
       break; }
   case AUDIO_U16LSB: {
       // unsigned 16-bit sample, little-endian
       Uint16 *ptr = (Uint16 *)audio_buf;
       if (wave.spec.channels == 1) {
           // process mono audio
           for (i=0; i<buf_size; i += sizeof(Uint16)) {
#if (SDL_BYTE_ORDER == SDL_BIG_ENDIAN)
               Uint16 swap = SDL_Swap16(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               swap = (Uint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++; // note here ptr will move to 16 bits higher
#else
               double tmp = (*ptr) * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               *ptr = (Uint16)tmp;
               ptr++;
#endif
           }
       } else if (wave.spec.channels == 2) {
           // process stero audio
           for (i=0; i<buf_size; i += sizeof(Uint16)*2) {
#if (SDL_BYTE_ORDER == SDL_BIG_ENDIAN)
               // process left channel
               Uint16 swap = SDL_Swap16(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               swap = (Uint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;

               // process right channel
               swap = SDL_Swap16(*ptr);
               tmp = swap * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               swap = (Uint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;
#else
               // process left channel
               double tmp = (*ptr) * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               *ptr = (Uint16)tmp;
               ptr++;

               // process right channel
               tmp = (*ptr) * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               *ptr = (Uint16)tmp;
               ptr++;
#endif
           }
       } else {
           fprintf(stderr, "Doesn't support more than 2 channels!\n");
           exit(1);
       }
       break; }
   case AUDIO_S16LSB: {
       // signed 16-bit sample, little-endian
       Sint16 *ptr = (Sint16 *)audio_buf;
       if (wave.spec.channels == 1) {
           // process mono audio
           for (i=0; i<buf_size; i += sizeof(Sint16)) {
#if (SDL_BYTE_ORDER == SDL_BIG_ENDIAN)
               Sint16 swap = SDL_Swap16(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               swap = (Sint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;
#else
               double tmp = (*ptr) * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               *ptr = (Sint16)tmp;
               ptr++;
#endif
           }
       } else if (wave.spec.channels == 2) {
           // process stero audio
           for (i=0; i<buf_size; i += sizeof(Sint16)*2) {
#if (SDL_BYTE_ORDER == SDL_BIG_ENDIAN)
               // process left channel
               Sint16 swap = SDL_Swap(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               swap = (Sint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;

               // process right channel
               swap = SDL_Swap(*ptr);
               tmp = swap * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               swap = (Sint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;
#else
               // process left channel
               double tmp = (*ptr) * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               *ptr = (Sint16)tmp;
               ptr++;

               // process right channel
               tmp = (*ptr) * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               *ptr = (Sint16)tmp;
               ptr++;
#endif
           }
       } else {
           fprintf(stderr, "Doesn't support more than 2 channels!\n");
           exit(1);
       }
       break; }
   case AUDIO_U16MSB: {
       // unsigned 16-bit sample, big-endian
       Uint16 *ptr = (Uint16 *)audio_buf;
       if (wave.spec.channels == 1) {
           // process mono audio
           for (i=0; i<buf_size; i += sizeof(Uint16)) {
#if (SDL_BYTE_ORDER == SDL_LIL_ENDIAN)
               Uint16 swap = SDL_Swap16(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               swap = (Uint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++; // note here ptr will move to 16 bits higher
#else
               double tmp = (*ptr) * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               *ptr = (Uint16)tmp;
               ptr++;
#endif
           }
       } else if (wave.spec.channels == 2) {
           // process stero audio
           for (i=0; i<buf_size; i += sizeof(Uint16)*2) {
#if (SDL_BYTE_ORDER == SDL_LIL_ENDIAN)
               // process left channel
               Uint16 swap = SDL_Swap16(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               swap = (Uint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;

               // process right channel
               swap = SDL_Swap16(*ptr);
               tmp = swap * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               swap = (Uint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;
#else
               // process left channel
               double tmp = (*ptr) * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               *ptr = (Uint16)tmp;
               ptr++;

               // process right channel
               tmp = (*ptr) * volume;
               tmp = tmp > 65535.0 ? 65535.0 : tmp;
               *ptr = (Uint16)tmp;
               ptr++;
#endif
           }
       } else {
           fprintf(stderr, "Doesn't support more than 2 channels!\n");
           exit(1);
       }
       break; }
   case AUDIO_S16MSB: {
       // signed 16-bit sample, big-endian
       Sint16 *ptr = (Sint16 *)audio_buf;
       if (wave.spec.channels == 1) {
           // process mono audio
           for (i=0; i<buf_size; i += sizeof(Sint16)) {
#if (SDL_BYTE_ORDER == SDL_LIL_ENDIAN)
               Sint16 swap = SDL_Swap16(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               swap = (Sint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;
#else
               double tmp = (*ptr) * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               *ptr = (Sint16)tmp;
               ptr++;
#endif
           }
       } else if (wave.spec.channels == 2) {
           // process stero audio
           for (i=0; i<buf_size; i += sizeof(Sint16)*2) {
#if (SDL_BYTE_ORDER == SDL_LIL_ENDIAN)
               // process left channel
               Sint16 swap = SDL_Swap(*ptr);
               double tmp = swap * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               swap = (Sint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;

               // process right channel
               swap = SDL_Swap(*ptr);
               tmp = swap * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               swap = (Sint16)tmp;
               *ptr = SDL_Swap16(swap);
               ptr++;
#else
               // process left channel
               double tmp = (*ptr) * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               *ptr = (Sint16)tmp;
               ptr++;

               // process right channel
               tmp = (*ptr) * volume;
               tmp = tmp > 32767.0 ? 32767.0 : tmp;
               tmp = tmp < -32768.0 ? -32768.0 : tmp;
               *ptr = (Sint16)tmp;
               ptr++;
#endif
           }
       } else {
           fprintf(stderr, "Doesn't support more than 2 channels!\n");
           exit(1);
       }
       break; }
   }
}

void SDLCALL fillerup(void *unused, Uint8 *stream, int len)
{
        Uint8 *waveptr;
        int    waveleft;

        /* Set up the pointers */
        waveptr = wave.sound + wave.soundpos;
        waveleft = wave.soundlen - wave.soundpos;

        /* Go! */
        while ( waveleft <= len ) {
                /* Process samples */
                Uint8 process_buf[waveleft];
                SDL_memcpy(process_buf, waveptr, waveleft);
                process_audio(process_buf, waveleft);
        
                // play the end of the audio
                SDL_memcpy(stream, process_buf, waveleft);
                stream += waveleft;
                len -= waveleft;

                // ready to repeat play the audio
                waveptr = wave.sound;
                waveleft = wave.soundlen;
                wave.soundpos = 0;
        }
        
        /* Process samples */
        Uint8 process_buf[len];
        SDL_memcpy(process_buf, waveptr, len);
        process_audio(process_buf, len);
        
        // play the processed samples
        SDL_memcpy(stream, process_buf, len);
        wave.soundpos += len;
}

static const int SCR_WIDTH = 240;
static const int SCR_HEIGHT = 180;
int main(int argc, char *argv[])
{
        char            name[32];
   SDL_Event   event;
   Uint8       *keys;
   SDL_Surface *screen;

        /* Load the SDL library */
        if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 ) {
                fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
                return(1);
        }
        if ( argv[1] == NULL ) {
                argv[1] = "sample.wav";
        }
        
   // Make a screen to put our video
#ifndef __DARWIN__
   screen = SDL_SetVideoMode(SCR_WIDTH, SCR_HEIGHT, 0, 0);
#else
   screen = SDL_SetVideoMode(SCR_WIDTH, SCR_HEIGHT, 24, 0);
#endif

   if (!screen) {
       fprintf(stderr, "SDL: could not set video mode - exiting\n");
       quit(1);
   }
        
        /* Load the wave file into memory */
        if ( SDL_LoadWAV(argv[1],
                        &wave.spec, &wave.sound, &wave.soundlen) == NULL ) {
                fprintf(stderr, "Couldn't load %s: %s\n",
                                                argv[1], SDL_GetError());
                quit(1);
        }

        wave.spec.callback = fillerup;
        
#if HAVE_SIGNAL_H
        /* Set the signals */
#ifdef SIGHUP
        signal(SIGHUP, poked);
#endif
        signal(SIGINT, poked);
#ifdef SIGQUIT
        signal(SIGQUIT, poked);
#endif
        signal(SIGTERM, poked);
#endif /* HAVE_SIGNAL_H */

        /* Initialize fillerup() variables */
        if ( SDL_OpenAudio(&wave.spec, NULL) < 0 ) {
                fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
                SDL_FreeWAV(wave.sound);
                quit(2);
        }
        // start playing
        SDL_PauseAudio(0);

        /* Let the audio run */
        printf("Using audio driver: %s\n", SDL_AudioDriverName(name, 32));
        while ( ! done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) ) {
       // Poll input queue, run keyboard loop
       while ( SDL_PollEvent(&event) ) {
           if ( event.type == SDL_QUIT )
               done = 1;
       }
       keys = SDL_GetKeyState(NULL);
       if (keys[SDLK_q]) {
           done = 1;
       } else if (keys[SDLK_MINUS]) {
                        volume /= 2.0f;
                } else if (keys[SDLK_EQUALS]) {
                        volume *= 2.0f;
                }
                
                
                SDL_Delay(100);
        }

        /* Clean up on signal */
        SDL_CloseAudio();
        SDL_FreeWAV(wave.sound);
        SDL_Quit();
        return(0);
}


_______________________________________________
SDL mailing list
SDL@xxxxxxxxxxxxxxxx
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list
SDL@xxxxxxxxxxxxxxxx
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

<Prev in Thread] Current Thread [Next in Thread>