From 0b9b2eb5119d363874ed8d56e20dd1e5ab189c63 Mon Sep 17 00:00:00 2001 From: JailDoctor Date: Thu, 4 Feb 2021 17:01:00 +0100 Subject: [PATCH] Channels can be paused, resumed, stopped... --- jail_audio.cpp | 157 ++++++++++++++++++++++++++----------------------- jail_audio.h | 6 +- main.cpp | 26 ++++++-- 3 files changed, 109 insertions(+), 80 deletions(-) diff --git a/jail_audio.cpp b/jail_audio.cpp index 5f27601..49db2ac 100644 --- a/jail_audio.cpp +++ b/jail_audio.cpp @@ -2,41 +2,38 @@ #include "stb_vorbis.c" #include -#define JA_MAX_SIMULTANEOUS_SOUNDS 5 +#define JA_MAX_SIMULTANEOUS_CHANNELS 5 struct JA_Sound_t { - Uint32 length {0}; - Uint8 *buffer {NULL}; + Uint32 length {0}; + Uint8* buffer {NULL}; }; -struct JA_Sound_Playing_t { - Uint32 length {0}; - int pos {0}; - int times {0}; - Uint8 *buffer {NULL}; - JA_Sound_Playing_t* prev {NULL}; - JA_Sound_Playing_t* next {NULL}; +enum JA_Channel_state { JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED }; + +struct JA_Channel_t { + JA_Sound sound; + int pos {0}; + int times {0}; + JA_Channel_state state { JA_CHANNEL_FREE }; }; enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED }; struct JA_Music_t { - int samples {0}; - int pos {0}; - short *output {NULL}; - JA_Music_state state {JA_MUSIC_INVALID}; - int times {0}; + int samples {0}; + int pos {0}; + int times {0}; + short* output {NULL}; + JA_Music_state state {JA_MUSIC_INVALID}; }; -JA_Music current_music{NULL}; -JA_Sound_Playing_t sounds[JA_MAX_SIMULTANEOUS_SOUNDS]; -JA_Sound_Playing_t *first_sound {NULL}; -JA_Sound_Playing_t *last_sound {NULL}; -JA_Sound_Playing_t *free_sounds_list {NULL}; +JA_Music current_music{NULL}; +JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS]; -int JA_freq {48000}; +int JA_freq {48000}; SDL_AudioFormat JA_format {AUDIO_S16}; -Uint8 JA_channels {2}; +Uint8 JA_channels {2}; void audioCallback(void * userdata, uint8_t * stream, int len) { SDL_memset(stream, 0, len); @@ -55,36 +52,21 @@ void audioCallback(void * userdata, uint8_t * stream, int len) { } } } - // Mixar els sounds mi amol - JA_Sound_Playing_t *sound = first_sound; - while (sound != NULL) { - const int size = SDL_min(len, sound->length-sound->pos); - SDL_MixAudioFormat(stream, sound->buffer+sound->pos, AUDIO_S16, size, 64); - sound->pos += size; - if (size < len) { - if (sound->times != 0) { - SDL_MixAudioFormat(stream+size, sound->buffer, AUDIO_S16, len-size, 64); - sound->pos = len-size; - if (sound->times > 0) sound->times--; - } else { - if (sound == last_sound) last_sound = sound->prev; - if (sound == first_sound) first_sound = sound->next; - if (sound->prev != NULL) sound->prev->next = sound->next; - if (sound->next != NULL) sound->next->prev = sound->prev; - if (free_sounds_list == NULL) { - free_sounds_list = sound; - sound = sound->next; - free_sounds_list->prev = free_sounds_list->next = NULL; + // Mixar els channels mi amol + for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { + if (channels[i].state == JA_CHANNEL_PLAYING) { + const int size = SDL_min(len, channels[i].sound->length - channels[i].pos); + SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, 64); + channels[i].pos += size; + if (size < len) { + if (channels[i].times != 0) { + SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, 64); + channels[i].pos = len-size; + if (channels[i].times > 0) channels[i].times--; } else { - free_sounds_list->prev = sound; - sound = sound->next; - free_sounds_list->prev->next = free_sounds_list; - free_sounds_list = free_sounds_list->prev; - free_sounds_list->prev = NULL; + JA_StopChannel(i); } } - } else { - sound = sound->next; } } } @@ -95,10 +77,6 @@ void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) { JA_channels = channels; SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL}; SDL_AudioDeviceID sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); - free_sounds_list = &sounds[0]; - for (int i = 0; i < JA_MAX_SIMULTANEOUS_SOUNDS-2;i++) { - sounds[i].next = &sounds[i+1]; sounds[i+1].prev = &sounds[i]; - } SDL_PauseAudioDevice(sdlAudioDevice, 0); } @@ -178,29 +156,62 @@ JA_Sound JA_LoadSound(const char* filename) { return sound; } -void JA_PlaySound(JA_Sound sound, const int loop) { - if (free_sounds_list == NULL) { - first_sound->prev = last_sound; - last_sound->next = first_sound; - last_sound = first_sound; - first_sound = last_sound->next; - first_sound->prev = last_sound->next = NULL; - } else { - if (last_sound != NULL) - last_sound->next = free_sounds_list; - last_sound = free_sounds_list; - if (free_sounds_list->next != NULL) free_sounds_list->next->prev = NULL; - free_sounds_list = last_sound->next; - last_sound->next = NULL; - if (first_sound == NULL) first_sound = last_sound; - } - last_sound->buffer = sound->buffer; - last_sound->length = sound->length; - last_sound->times = loop; - last_sound->pos = 0; +int JA_PlaySound(JA_Sound sound, const int loop) { + int channel = 0; + while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; } + if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0; + + channels[channel].sound = sound; + channels[channel].times = loop; + channels[channel].pos = 0; + channels[channel].state = JA_CHANNEL_PLAYING; + return channel; } void JA_DeleteSound(JA_Sound sound) { + for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { + if (channels[i].sound == sound) JA_StopChannel(i); + } SDL_FreeWAV(sound->buffer); delete sound; } + +void JA_PauseChannel(const int channel) { + if (channel == -1) { + for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { + if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED; + } + } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { + if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED; + } +} + +void JA_ResumeChannel(const int channel) { + if (channel == -1) { + for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { + if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING; + } + } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { + if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING; + } +} + +void JA_StopChannel(const int channel) { + if (channel == -1) { + for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { + channels[i].state = JA_CHANNEL_FREE; + channels[i].pos = 0; + channels[i].sound = NULL; + } + } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { + channels[channel].state = JA_CHANNEL_FREE; + channels[channel].pos = 0; + channels[channel].sound = NULL; + } +} + +bool JA_IsChannelPlaying(const int channel) { + if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return false; + return channels[channel].state == JA_CHANNEL_PLAYING; +} + diff --git a/jail_audio.h b/jail_audio.h index ba9b0b2..994b3fd 100644 --- a/jail_audio.h +++ b/jail_audio.h @@ -15,5 +15,9 @@ bool JA_IsMusicPlaying(); void JA_DeleteMusic(JA_Music music); JA_Sound JA_LoadSound(const char* filename); -void JA_PlaySound(JA_Sound sound, const int loop = 0); +int JA_PlaySound(JA_Sound sound, const int loop = 0); +void JA_PauseChannel(const int channel); +void JA_ResumeChannel(const int channel); +void JA_StopChannel(const int channel); +bool JA_IsChannelPlaying(const int channel); void JA_DeleteSound(JA_Sound sound); diff --git a/main.cpp b/main.cpp index a7be8f8..79154c3 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,7 @@ int main(int argc, char **argv) { JA_Music music = JA_LoadMusic("intro2.ogg"); JA_Sound peiv = JA_LoadSound("menu_select.wav"); + int channel = -1; JA_PlayMusic(music, true); @@ -21,12 +22,25 @@ int main(int argc, char **argv) { while(SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { should_exit = true; break; } if (event.type == SDL_KEYDOWN) { - JA_PlaySound(peiv, 2); - if (JA_IsMusicPlaying()) - JA_PauseMusic(); - else - { - JA_ResumeMusic(); + switch (event.key.keysym.scancode) { + case SDL_SCANCODE_1: // Si pulsem la tecla '1' pausem o despausem la música + if (JA_IsMusicPlaying()) { JA_PauseMusic(); } else { JA_ResumeMusic(); } + break; + case SDL_SCANCODE_2: // Si pulsem la tecla '2' sona el wav 1 vegada + JA_PlaySound(peiv); + break; + case SDL_SCANCODE_3: // Si pulsem la tecla '3' sona el wav 3 vegades + JA_PlaySound(peiv, 2); + break; + case SDL_SCANCODE_4: // Si pulsem la tecla '4' sona el wav infinitament + channel = JA_PlaySound(peiv, -1); + break; + case SDL_SCANCODE_5: // Si pulsem la tecla '5' pausem o despausem el wav que sonaba infinitament + if (JA_IsChannelPlaying(channel)) { JA_PauseChannel(channel); } else { JA_ResumeChannel(channel); } + break; + case SDL_SCANCODE_6: // Si pulsem la tecla '6' stopem definitivament el wav infinit + JA_StopChannel(channel); + break; } }