From a66dec3fab601a1f2f14e9f8b7cb1773f23663d5 Mon Sep 17 00:00:00 2001 From: Holmes Futrell Date: Fri, 18 Jul 2008 20:51:59 +0000 Subject: [PATCH] Drum kit demo (SDL_mixer) --- XCodeiPhoneOS/Demos/src/mixer.c | 321 ++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 XCodeiPhoneOS/Demos/src/mixer.c diff --git a/XCodeiPhoneOS/Demos/src/mixer.c b/XCodeiPhoneOS/Demos/src/mixer.c new file mode 100644 index 000000000..d893814e4 --- /dev/null +++ b/XCodeiPhoneOS/Demos/src/mixer.c @@ -0,0 +1,321 @@ +/* + * mixer.c + * written by Holmes Futrell + * use however you want + */ + +#import "SDL.h" +#import "common.h" + +#define NUM_CHANNELS 8 /* max number of sounds we can play at once */ +#define NUM_DRUMS 4 /* number of drums in our set */ +#define MILLESECONDS_PER_FRAME 16 /* about 60 frames per second */ + +static struct { + SDL_Rect rect; /* where the button is drawn */ + SDL_Color upColor; /* color when button is not active */ + SDL_Color downColor; /* color when button is active */ + int isPressed; /* is the button being pressed ? */ + int touchIndex; /* what mouse (touch) index pressed the button ? */ +} buttons[NUM_DRUMS]; + +struct sound { + Uint8 *buffer; /* audio buffer for sound file */ + Uint32 length; /* length of the buffer (in bytes) */ +}; + +/* this array holds the audio for the drum noises */ +static struct sound drums[NUM_DRUMS]; + +/* function declarations */ +void handleMouseButtonDown(SDL_Event *event); +void handleMouseButtonUp(SDL_Event *event); +int playSound(struct sound *); +void render(void); +void initializeButtons(); +void audioCallback(void *userdata, Uint8 *stream, int len); +void loadSound(const char *file, struct sound *s); + +struct { + /* channel array holds information about currently playing sounds */ + struct { + Uint8 *position; /* what is the current position in the buffer of this sound ? */ + Uint32 remaining; /* how many bytes remaining before we're done playing the sound ? */ + Uint32 timestamp; /* when did this sound start playing ? */ + } channels[NUM_CHANNELS]; + SDL_AudioSpec outputSpec; /* what audio format are we using for output? */ + int numSoundsPlaying; /* how many sounds are currently playing */ +} mixer; + +/* sets up the buttons (color, position, state) */ +void initializeButtons() { + + int i; + int spacing = 10; /* gap between drum buttons */ + SDL_Rect buttonRect; /* keeps track of where to position drum */ + SDL_Color upColor = { 86, 86, 140, 255 }; /* color of drum when not pressed */ + SDL_Color downColor = { 191, 191, 221, 255 }; /* color of drum when pressed */ + + buttonRect.x = spacing; + buttonRect.y = spacing; + buttonRect.w = SCREEN_WIDTH - 2 * spacing; + buttonRect.h = ( SCREEN_HEIGHT - (NUM_DRUMS + 1) * spacing ) / NUM_DRUMS; + + /* setup each button */ + for (i=0; ibuffer, &s->length) == NULL) { + fatalError("could not load .wav"); + } + /* build the audio converter */ + result = SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, + mixer.outputSpec.format, mixer.outputSpec.channels, mixer.outputSpec.freq); + if (result == -1) { + fatalError("could not build audio CVT"); + } + else if (result != 0) { + /* + this happens when the .wav format differs from the output format. + we convert the .wav buffer here + */ + cvt.buf = (Uint8 *)SDL_malloc(s->length * cvt.len_mult); /* allocate conversion buffer */ + cvt.len = s->length; /* set conversion buffer length */ + SDL_memcpy(cvt.buf, s->buffer, s->length); /* copy sound to conversion buffer */ + if (SDL_ConvertAudio(&cvt) == -1) { /* convert the sound */ + fatalError("could not convert .wav"); + } + SDL_free(s->buffer); /* free the original (unconverted) buffer */ + s->buffer = cvt.buf; /* point sound buffer to converted buffer */ + s->length = cvt.len_cvt; /* set sound buffer's new length */ + } +} + +/* called from main event loop */ +void handleMouseButtonDown(SDL_Event *event) { + + int x, y, mouseIndex, i, drumIndex; + + mouseIndex = event->button.which; + drumIndex = -1; + + SDL_SelectMouse(mouseIndex); + SDL_GetMouseState(&x, &y); + /* check if we hit any of the drum buttons */ + for (i=0; i= buttons[i].rect.x && x < buttons[i].rect.x + buttons[i].rect.w \ + && y >= buttons[i].rect.y && y < buttons[i].rect.y + buttons[i].rect.h) { + drumIndex = i; + break; + } + } + if (drumIndex != -1) { + /* if we hit a button */ + buttons[drumIndex].touchIndex = mouseIndex; + buttons[drumIndex].isPressed = 1; + playSound(&drums[drumIndex]); + } + +} + +/* called from main event loop */ +void handleMouseButtonUp(SDL_Event *event) { + int i; + int mouseIndex = event->button.which; + /* check if this should cause any of the buttons to become unpressed */ + for (i=0; ibuffer; + mixer.channels[selected_channel].remaining = s->length; + mixer.channels[selected_channel].timestamp = SDL_GetTicks(); + + return selected_channel; +} + +/* + Called from SDL's audio system. Supplies sound input with data by mixing together all + currently playing sound effects. +*/ +void audioCallback(void *userdata, Uint8 *stream, int len) { + int i; + int copy_amt; + SDL_memset(stream, mixer.outputSpec.silence, len); /* initialize buffer to silence */ + /* for each channel, mix in whatever is playing on that channel */ + for (i=0; i MILLESECONDS_PER_FRAME) { + delay = MILLESECONDS_PER_FRAME; + } + SDL_Delay(delay); + } + + /* cleanup code, let's free up those sound buffers */ + int i; + for (i=0; i