18 Commits
v1.2 ... master

Author SHA1 Message Date
5158d95e3d - Prova amb update explicit 2025-07-24 18:06:48 +02:00
7d591bb028 - [NEW] Afegits grups de sons, per a fer el volum de cada grup independent. 2025-07-01 09:09:12 +02:00
45e14f3ff7 - [NEW] Afegit JA_GetMusicFilename() perque me fa falta pal AEE 2025-06-29 13:15:47 +02:00
1f4628122f - [FIX] copy paste de merda 2025-06-29 13:04:21 +02:00
4c46581ae1 - [FIX] Els sonsse tallaven en compte de usar un nou canal.
- [FIX] La repetició de sons no infinita no funcionava.
2025-06-25 08:11:17 +02:00
b03ff65c4c - [FIX] El fade out are te en compte el volumen inicial 2025-06-25 07:41:48 +02:00
d8eb90df1a - [FIX] Arreglada la pausa i continuació de música i só per a que siguen independents
- [FIX] Condicions de petada al stopar sons
2025-03-27 13:48:29 +01:00
38491f1bbe - [FIX] renamada funció del sistema de log a SDL3 2025-03-27 13:15:03 +01:00
d704614b23 - [FIX] Che, se m'havia colat un error 2025-03-27 13:13:12 +01:00
1d6d92a0b2 - [FIX] Al acabar un fadeoutmusic podria petar 2025-03-27 13:08:49 +01:00
861c227c54 - [FIX] Evitar que sonen varies musiques a l'hora
- [FIX] ResumeAudioStream al playar la musica
- [FIX] Parar un canal de audio abans de intentar usar-lo per a un nou só
- [FIX] No permetre canals negatius
- [FIX] Alliberar el stream al parar un canal
- [FIX] Arreglat el control de volum en l'aplicació de exemple
2025-03-27 12:54:14 +01:00
37776fce4a - Puto free del sdl no es igual en tots els SO. 2025-03-27 12:21:30 +01:00
c61f02faff - Ultims commits de la rama principal aplicats (no probat) 2025-03-27 12:04:43 +01:00
e994ab2678 - Exemple updatat a SDL3 2025-03-27 09:40:13 +01:00
d7d813718c - Pas complet a SDL3 2024-11-06 20:23:35 +01:00
f0687f9f4d - [NEW] JA_LoadMusic() i JA_LoadSound() ara també accepten un buffer de uint8_t* i un tamany, a l'hora de carregar.
- [FIX] JA_PlaySound() de vegades no tornava res
2024-10-06 15:06:11 +02:00
cd2f18212b - [NEW] JA_SetMusicVolume(int volume)
- [NEW] JA_EnableMusic(const bool value)
- [NEW]  JA_SetSoundVolume(int volume)
- [NEW] JA_EnableSound(const bool value)
2024-05-31 18:25:11 +02:00
c79150b24a - Types changed, SDL_Mixer version included 2022-12-01 19:42:20 +01:00
5 changed files with 422 additions and 172 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
.vscode .vscode
*.out *.out
main main
jail_audio

View File

@@ -1,95 +1,159 @@
#ifndef JA_USESDLMIXER
#include "jail_audio.h" #include "jail_audio.h"
#include "stb_vorbis.c" #include "stb_vorbis.c"
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
#include <stdio.h> #include <stdio.h>
#define JA_MAX_SIMULTANEOUS_CHANNELS 5 #define JA_MAX_SIMULTANEOUS_CHANNELS 5
#define JA_MAX_GROUPS 5
struct JA_Sound_t { struct JA_Sound_t
Uint32 length {0}; {
Uint8* buffer {NULL}; SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
Uint32 length { 0 };
Uint8 *buffer { NULL };
}; };
struct JA_Channel_t { struct JA_Channel_t
JA_Sound sound; {
int pos {0}; JA_Sound_t *sound { nullptr };
int times {0}; int pos { 0 };
int times { 0 };
int group { 0 };
SDL_AudioStream *stream { nullptr };
JA_Channel_state state { JA_CHANNEL_FREE }; JA_Channel_state state { JA_CHANNEL_FREE };
}; };
struct JA_Music_t { struct JA_Music_t
int samples {0}; {
int pos {0}; SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
int times {0}; Uint32 length { 0 };
short* output {NULL}; Uint8 *buffer { nullptr };
JA_Music_state state {JA_MUSIC_INVALID}; char *filename { nullptr };
int pos { 0 };
int times { 0 };
SDL_AudioStream *stream { nullptr };
JA_Music_state state { JA_MUSIC_INVALID };
}; };
JA_Music current_music{NULL}; JA_Music_t *current_music { nullptr };
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS]; JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000}; SDL_AudioSpec JA_audioSpec { SDL_AUDIO_S16, 2, 48000 };
SDL_AudioFormat JA_format {AUDIO_S16}; float JA_musicVolume { 1.0f };
Uint8 JA_channels {2}; float JA_soundVolume[JA_MAX_GROUPS];
int JA_musicvolume = 128; bool JA_musicEnabled { true };
int JA_soundvolume = 64; bool JA_soundEnabled { true };
SDL_AudioDeviceID sdlAudioDevice = 0; SDL_AudioDeviceID sdlAudioDevice { 0 };
//SDL_TimerID JA_timerID { 0 };
void audioCallback(void * userdata, uint8_t * stream, int len) { bool fading = false;
SDL_memset(stream, 0, len); int fade_start_time;
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) { int fade_duration;
const int size = SDL_min(len, current_music->samples*2-current_music->pos); int fade_initial_volume;
SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_musicvolume);
current_music->pos += size/2;
if (size < len) { void JA_Update()
if (current_music->times != 0) { {
SDL_MixAudioFormat(stream+size, (Uint8*)current_music->output, AUDIO_S16, len-size, JA_musicvolume); if (JA_musicEnabled && current_music && current_music->state == JA_MUSIC_PLAYING)
current_music->pos = (len-size)/2; {
if (current_music->times > 0) current_music->times--; if (fading) {
int time = SDL_GetTicks();
if (time > (fade_start_time+fade_duration)) {
fading = false;
JA_StopMusic();
return;
} else { } else {
current_music->pos = 0; const int time_passed = time - fade_start_time;
current_music->state = JA_MUSIC_STOPPED; const float percent = (float)time_passed / (float)fade_duration;
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume*(1.0 - percent));
} }
} }
if (current_music->times != 0)
{
if (SDL_GetAudioStreamAvailable(current_music->stream) < (current_music->length/2)) {
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
} }
// Mixar els channels mi amol if (current_music->times>0) current_music->times--;
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { }
if (channels[i].state == JA_CHANNEL_PLAYING) { else
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, JA_soundvolume); if (SDL_GetAudioStreamAvailable(current_music->stream) == 0) JA_StopMusic();
channels[i].pos += size;
if (size < len) {
if (channels[i].times != 0) {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, JA_soundvolume);
channels[i].pos = len-size;
if (channels[i].times > 0) channels[i].times--;
} else {
JA_StopChannel(i);
} }
} }
if (JA_soundEnabled)
{
for (int i=0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
if (channels[i].state == JA_CHANNEL_PLAYING)
{
if (channels[i].times != 0)
{
if (SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length/2)) {
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
if (channels[i].times>0) channels[i].times--;
} }
} }
else
{
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) JA_StopChannel(i);
}
}
}
return;
} }
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) { void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels)
JA_freq = freq; {
JA_format = format; #ifdef DEBUG
JA_channels = channels; SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL}; #endif
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); SDL_Log("Iniciant JailAudio...");
SDL_PauseAudioDevice(sdlAudioDevice, 0); JA_audioSpec = {format, num_channels, freq };
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &JA_audioSpec);
SDL_Log( (sdlAudioDevice==0) ? "Failed to initialize SDL audio!\n" : "OK!\n");
for (int i=0; i<JA_MAX_SIMULTANEOUS_CHANNELS; ++i) channels[i].state = JA_CHANNEL_FREE;
for (int i=0; i<JA_MAX_GROUPS; ++i) JA_soundVolume[i] = 0.5f;
//SDL_PauseAudioDevice(sdlAudioDevice);
//JA_timerID = SDL_AddTimer(30, JA_UpdateCallback, nullptr);
} }
void JA_Quit() { void JA_Quit()
SDL_PauseAudioDevice(sdlAudioDevice, 1); {
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice); //if (JA_timerID) SDL_RemoveTimer(JA_timerID);
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = 0; sdlAudioDevice = 0;
} }
JA_Music JA_LoadMusic(const char* filename) { JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length)
int chan, samplerate; {
JA_Music_t *music = new JA_Music_t();
int chan, samplerate;
short *output;
music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
music->spec.channels = chan;
music->spec.freq = samplerate;
music->spec.format = SDL_AUDIO_S16;
music->buffer = (Uint8*)SDL_malloc(music->length);
SDL_memcpy(music->buffer, output, music->length);
free(output);
music->pos = 0;
music->state = JA_MUSIC_STOPPED;
return music;
}
JA_Music_t *JA_LoadMusic(const char* filename)
{
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid. // [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
FILE *f = fopen(filename, "rb"); FILE *f = fopen(filename, "rb");
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
@@ -99,105 +163,196 @@ JA_Music JA_LoadMusic(const char* filename) {
if (fread(buffer, fsize, 1, f)!=1) return NULL; if (fread(buffer, fsize, 1, f)!=1) return NULL;
fclose(f); fclose(f);
JA_Music music = new JA_Music_t(); JA_Music_t *music = JA_LoadMusic(buffer, fsize);
music->filename = (char*)malloc(strlen(filename)+1);
strcpy(music->filename, filename);
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output);
free(buffer); free(buffer);
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
if (cvt.needed) {
cvt.len = music->samples * chan * 2;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt);
free(music->output);
music->output = (short*)cvt.buf;
}
music->pos = 0;
music->state = JA_MUSIC_STOPPED;
return music; return music;
} }
void JA_PlayMusic(JA_Music music, const int loop) { void JA_PlayMusic(JA_Music_t *music, const int loop)
if (current_music != NULL) { {
current_music->pos = 0; if (!JA_musicEnabled) return;
current_music->state = JA_MUSIC_STOPPED;
} JA_StopMusic();
current_music = music; current_music = music;
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop; current_music->times = loop;
current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec);
if (!SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length)) printf("[ERROR] SDL_PutAudioStreamData failed!\n");
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n");
//SDL_ResumeAudioStreamDevice(current_music->stream);
} }
void JA_PauseMusic() { char *JA_GetMusicFilename(JA_Music_t *music)
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; {
if (!music) music = current_music;
return music->filename;
}
void JA_PauseMusic()
{
if (!JA_musicEnabled) return;
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PAUSED; current_music->state = JA_MUSIC_PAUSED;
//SDL_PauseAudioStreamDevice(current_music->stream);
SDL_UnbindAudioStream(current_music->stream);
} }
void JA_ResumeMusic() { void JA_ResumeMusic()
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; {
if (!JA_musicEnabled) return;
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
//SDL_ResumeAudioStreamDevice(current_music->stream);
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
} }
void JA_StopMusic() { void JA_StopMusic()
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; {
if (!JA_musicEnabled) return;
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
//SDL_PauseAudioStreamDevice(current_music->stream);
SDL_DestroyAudioStream(current_music->stream);
current_music->stream = nullptr;
free(current_music->filename);
current_music->filename = nullptr;
} }
JA_Music_state JA_GetMusicState() { void JA_FadeOutMusic(const int milliseconds)
if (current_music == NULL) return JA_MUSIC_INVALID; {
if (!JA_musicEnabled) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
fading = true;
fade_start_time = SDL_GetTicks();
fade_duration = milliseconds;
fade_initial_volume = JA_musicVolume;
}
JA_Music_state JA_GetMusicState()
{
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
if (!current_music) return JA_MUSIC_INVALID;
return current_music->state; return current_music->state;
} }
void JA_DeleteMusic(JA_Music music) { void JA_DeleteMusic(JA_Music_t *music)
if (current_music == music) current_music = NULL; {
free(music->output); if (current_music == music) current_music = nullptr;
SDL_free(music->buffer);
if (music->stream) SDL_DestroyAudioStream(music->stream);
delete music; delete music;
} }
JA_Sound JA_NewSound(Uint8* buffer, Uint32 length) { float JA_SetMusicVolume(float volume)
JA_Sound sound = new JA_Sound_t(); {
JA_musicVolume = SDL_clamp( volume, 0.0f, 1.0f );
if (current_music) SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
return JA_musicVolume;
}
void JA_SetMusicPosition(float value)
{
if (!current_music) return;
current_music->pos = value * current_music->spec.freq;
}
float JA_GetMusicPosition()
{
if (!current_music) return 0;
return float(current_music->pos)/float(current_music->spec.freq);
}
void JA_EnableMusic(const bool value)
{
if ( !value && current_music && (current_music->state==JA_MUSIC_PLAYING) ) JA_StopMusic();
JA_musicEnabled = value;
}
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length)
{
JA_Sound_t *sound = new JA_Sound_t();
sound->buffer = buffer; sound->buffer = buffer;
sound->length = length; sound->length = length;
return sound; return sound;
} }
JA_Sound JA_LoadSound(const char* filename) { JA_Sound_t *JA_LoadSound(uint8_t* buffer, uint32_t size)
JA_Sound sound = new JA_Sound_t(); {
SDL_AudioSpec wavSpec; JA_Sound_t *sound = new JA_Sound_t();
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length); SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size),1, &sound->spec, &sound->buffer, &sound->length);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
sound->buffer = cvt.buf;
sound->length = cvt.len_cvt;
return sound; return sound;
} }
int JA_PlaySound(JA_Sound sound, const int loop) { JA_Sound_t *JA_LoadSound(const char* filename)
{
JA_Sound_t *sound = new JA_Sound_t();
SDL_LoadWAV(filename, &sound->spec, &sound->buffer, &sound->length);
return sound;
}
int JA_PlaySound(JA_Sound_t *sound, const int loop, const int group)
{
if (!JA_soundEnabled) return -1;
int channel = 0; int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; } while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0; if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
JA_StopChannel(channel);
channels[channel].sound = sound; channels[channel].sound = sound;
channels[channel].times = loop; channels[channel].times = loop;
channels[channel].pos = 0; channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING; channels[channel].state = JA_CHANNEL_PLAYING;
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
SDL_SetAudioStreamGain(channels[channel].stream, JA_soundVolume[group]);
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
return channel; return channel;
} }
void JA_DeleteSound(JA_Sound sound) { int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop, const int group)
{
if (!JA_soundEnabled) return -1;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return -1;
JA_StopChannel(channel);
channels[channel].sound = sound;
channels[channel].times = loop;
channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING;
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
SDL_SetAudioStreamGain(channels[channel].stream, JA_soundVolume[group]);
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
return channel;
}
void JA_DeleteSound(JA_Sound_t *sound)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i); if (channels[i].sound == sound) JA_StopChannel(i);
} }
@@ -205,57 +360,118 @@ void JA_DeleteSound(JA_Sound sound) {
delete sound; delete sound;
} }
void JA_PauseChannel(const int channel) { void JA_PauseChannel(const int channel)
if (channel == -1) { {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { if (!JA_soundEnabled) return;
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED;
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;
//SDL_PauseAudioStreamDevice(channels[i].stream);
SDL_UnbindAudioStream(channels[i].stream);
}
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PLAYING)
{
channels[channel].state = JA_CHANNEL_PAUSED;
//SDL_PauseAudioStreamDevice(channels[channel].stream);
SDL_UnbindAudioStream(channels[channel].stream);
} }
} 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) { void JA_ResumeChannel(const int channel)
if (channel == -1) { {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { if (!JA_soundEnabled) return;
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING;
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;
//SDL_ResumeAudioStreamDevice(channels[i].stream);
SDL_BindAudioStream(sdlAudioDevice, channels[i].stream);
}
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PAUSED)
{
channels[channel].state = JA_CHANNEL_PLAYING;
//SDL_ResumeAudioStreamDevice(channels[channel].stream);
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
} }
} 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) { void JA_StopChannel(const int channel)
if (channel == -1) { {
if (!JA_soundEnabled) return;
if (channel == -1)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[i].stream);
channels[i].stream = nullptr;
channels[i].state = JA_CHANNEL_FREE; channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0; channels[i].pos = 0;
channels[i].sound = NULL; channels[i].sound = NULL;
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { }
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[channel].stream);
channels[channel].stream = nullptr;
channels[channel].state = JA_CHANNEL_FREE; channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0; channels[channel].pos = 0;
channels[channel].sound = NULL; channels[channel].sound = NULL;
} }
} }
JA_Channel_state JA_GetChannelState(const int channel) { JA_Channel_state JA_GetChannelState(const int channel)
{
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID; if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state; return channels[channel].state;
} }
int JA_SetSoundVolume(int volume) { float JA_SetSoundVolume(float volume, const int group)
JA_soundvolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; {
return JA_soundvolume; const float v = SDL_clamp( volume, 0.0f, 1.0f );
for (int i = 0; i < JA_MAX_GROUPS; ++i) {
if (group==-1 || group==i) JA_soundVolume[i]=v;
}
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if ( ((channels[i].state == JA_CHANNEL_PLAYING) || (channels[i].state == JA_CHANNEL_PAUSED)) &&
((group==-1) || (channels[i].group==group)) )
SDL_SetAudioStreamGain(channels[i].stream, JA_soundVolume[i]);
return v;
} }
int JA_SetMusicVolume(int volume) { void JA_EnableSound(const bool value)
JA_musicvolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; {
return JA_musicvolume; for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PLAYING) JA_StopChannel(i);
}
JA_soundEnabled = value;
} }
int JA_SetVolume(int volume) { float JA_SetVolume(float volume)
JA_musicvolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; {
JA_soundvolume = JA_musicvolume/2; JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
return JA_musicvolume;
return JA_musicVolume;
} }
#endif

View File

@@ -1,33 +1,43 @@
#pragma once #pragma once
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED }; enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED };
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED }; enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED };
typedef struct JA_Sound_t *JA_Sound; struct JA_Sound_t;
typedef struct JA_Music_t *JA_Music; struct JA_Music_t;
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels); void JA_Update();
void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels);
void JA_Quit(); void JA_Quit();
JA_Music JA_LoadMusic(const char* filename); JA_Music_t *JA_LoadMusic(const char* filename);
void JA_PlayMusic(JA_Music music, const int loop = -1); JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length);
void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
char *JA_GetMusicFilename(JA_Music_t *music = nullptr);
void JA_PauseMusic(); void JA_PauseMusic();
void JA_ResumeMusic(); void JA_ResumeMusic();
void JA_StopMusic(); void JA_StopMusic();
int JA_SetVolume(int volume); void JA_FadeOutMusic(const int milliseconds);
int JA_SetMusicVolume(int volume);
JA_Music_state JA_GetMusicState(); JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music music); void JA_DeleteMusic(JA_Music_t *music);
float JA_SetMusicVolume(float volume);
JA_Sound JA_NewSound(Uint8* buffer, Uint32 length); void JA_SetMusicPosition(float value);
JA_Sound JA_LoadSound(const char* filename); float JA_GetMusicPosition();
int JA_PlaySound(JA_Sound sound, const int loop = 0); void JA_EnableMusic(const bool value);
void JA_DeleteSound(JA_Sound sound);
int JA_SetSoundVolume(int volume);
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(Uint8* buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(const char* filename);
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0, const int group=0);
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop = 0, const int group=0);
void JA_PauseChannel(const int channel); void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel); void JA_ResumeChannel(const int channel);
void JA_StopChannel(const int channel); void JA_StopChannel(const int channel);
JA_Channel_state JA_GetChannelState(const int channel); JA_Channel_state JA_GetChannelState(const int channel);
void JA_DeleteSound(JA_Sound_t *sound);
float JA_SetSoundVolume(float volume, const int group=0);
void JA_EnableSound(const bool value);
float JA_SetVolume(float volume);

View File

@@ -1,6 +1,6 @@
#include "jail_audio.h" #include "jail_audio.h"
#include <stdlib.h> #include <stdlib.h>
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
#include <stdio.h> #include <stdio.h>
SDL_Event event; SDL_Event event;
@@ -8,22 +8,22 @@ SDL_Window *sdlWindow;
int main(int argc, char **argv) { int main(int argc, char **argv) {
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_AUDIO|SDL_INIT_EVENTS);
sdlWindow = SDL_CreateWindow("JailAudio", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_SHOWN); sdlWindow = SDL_CreateWindow("JailAudio", 320, 240, 0);
JA_Init(48000, AUDIO_S16, 2); JA_Init(48000, SDL_AUDIO_S16, 2);
JA_Music music = JA_LoadMusic("intro2.ogg"); JA_Music_t *music = JA_LoadMusic("intro2.ogg");
JA_Sound peiv = JA_LoadSound("menu_select.wav"); JA_Sound_t *peiv = JA_LoadSound("menu_select.wav");
int channel = -1; int channel = -1;
JA_PlayMusic(music, true); JA_PlayMusic(music, -1);
int volume = 128; float volume = 1.0f;
bool should_exit = false; bool should_exit = false;
while(!should_exit) { while(!should_exit) {
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) { should_exit = true; break; } if (event.type == SDL_EVENT_QUIT) { should_exit = true; break; }
if (event.type == SDL_KEYDOWN) { if (event.type == SDL_EVENT_KEY_DOWN) {
switch (event.key.keysym.scancode) { switch (event.key.scancode) {
case SDL_SCANCODE_1: // Si pulsem la tecla '1' pausem o despausem la música case SDL_SCANCODE_1: // Si pulsem la tecla '1' pausem o despausem la música
if (JA_GetMusicState() == JA_MUSIC_PLAYING) { JA_PauseMusic(); } else { JA_ResumeMusic(); } if (JA_GetMusicState() == JA_MUSIC_PLAYING) { JA_PauseMusic(); } else { JA_ResumeMusic(); }
break; break;
@@ -31,10 +31,10 @@ int main(int argc, char **argv) {
JA_PlaySound(peiv); JA_PlaySound(peiv);
break; break;
case SDL_SCANCODE_3: // Si pulsem la tecla '3' sona el wav 3 vegades case SDL_SCANCODE_3: // Si pulsem la tecla '3' sona el wav 3 vegades
JA_PlaySound(peiv, 2); JA_PlaySound(peiv, 2, 1);
break; break;
case SDL_SCANCODE_4: // Si pulsem la tecla '4' sona el wav infinitament case SDL_SCANCODE_4: // Si pulsem la tecla '4' sona el wav infinitament
channel = JA_PlaySound(peiv, -1); channel = JA_PlaySound(peiv, -1, 2);
break; break;
case SDL_SCANCODE_5: // Si pulsem la tecla '5' pausem o despausem el wav que sonaba infinitament case SDL_SCANCODE_5: // Si pulsem la tecla '5' pausem o despausem el wav que sonaba infinitament
if (JA_GetChannelState(channel) == JA_CHANNEL_PLAYING) { JA_PauseChannel(channel); } else { JA_ResumeChannel(channel); } if (JA_GetChannelState(channel) == JA_CHANNEL_PLAYING) { JA_PauseChannel(channel); } else { JA_ResumeChannel(channel); }
@@ -42,11 +42,20 @@ int main(int argc, char **argv) {
case SDL_SCANCODE_6: // Si pulsem la tecla '6' stopem definitivament el wav infinit case SDL_SCANCODE_6: // Si pulsem la tecla '6' stopem definitivament el wav infinit
JA_StopChannel(channel); JA_StopChannel(channel);
break; break;
case SDL_SCANCODE_7:
JA_PlayMusic(music, 0); // Si pulsem la tecla '7' fa sonar la música UNA negada nomes.
break;
case SDL_SCANCODE_0: // Si pulsem la tecla '0' stopem la música amb un fade
JA_FadeOutMusic(1000);
break;
case SDL_SCANCODE_UP: case SDL_SCANCODE_UP:
volume = JA_SetVolume(volume+16); volume = JA_SetVolume(volume+0.1f);
break; break;
case SDL_SCANCODE_DOWN: case SDL_SCANCODE_DOWN:
volume = JA_SetVolume(volume-16); volume = JA_SetVolume(volume-0.1f);
break;
case SDL_SCANCODE_ESCAPE:
should_exit = true;
break; break;
default: default:
break; break;
@@ -54,9 +63,11 @@ int main(int argc, char **argv) {
} }
} }
JA_Update();
} }
JA_DeleteSound(peiv); JA_DeleteSound(peiv);
JA_DeleteMusic(music); JA_DeleteMusic(music);
JA_Quit();
SDL_DestroyWindow(sdlWindow); SDL_DestroyWindow(sdlWindow);
SDL_Quit(); SDL_Quit();
return 0; return 0;

12
valgrind-sup.txt Normal file
View File

@@ -0,0 +1,12 @@
{
ignore_unversioned_libs
Memcheck:Leak
...
obj:*/lib*/lib*.so
}
{
ignore_versioned_libs
Memcheck:Leak
...
obj:*/lib*/lib*.so.*
}