36 Commits

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
bf1925bb3a Update 'readme.md' 2022-11-24 16:12:43 +01:00
861bb5e7f9 Merge branch 'master' of https://gitea.sustancia.synology.me/JailDoctor/JailAudio 2022-11-24 16:10:36 +01:00
debd80f6af - Removed volume per channel
- [NEW] JA_SetSoundVolume sets volume for all sound effects
- [NEW] JA_SetMusicVolume sets volume for the music
- JA_SetVolume works as always: sets volume for both, with sounds volume halved.
2022-11-24 16:10:33 +01:00
3ef6742c5d Add 'readme.md' 2022-11-24 15:51:49 +01:00
42986dd46a - Reorganització de la capçalera 2022-11-24 15:50:31 +01:00
cc7ef78d59 - [NEW] int JA_SetChannelVolume(const int channel, int volume) 2022-11-24 15:40:02 +01:00
6d8921b160 - Pa que se calle el compilaoooor en Linux 2022-11-09 13:56:32 +01:00
761119acf2 [FIX] JA_DeleteMusic() crashes, wrong free method 2022-10-07 17:44:23 +02:00
edf7484738 [FIX] SDL_AudioDeviceID is an Uint32, not a pointer 2022-10-07 17:33:43 +02:00
cb1154cb20 - JA_Init() now prevents bad multi-init
- [NEW] JA_Quit()
2022-10-07 17:28:20 +02:00
975fcfd81a Debug info removed 2022-08-28 09:08:26 +02:00
52df28a4f0 New stb_vorbis version added. OGG loading time optimized. 2022-08-28 09:07:37 +02:00
1ba349f6c3 Afegit "int JA_SetVolume(int volume);" 2022-08-28 08:16:30 +02:00
1623654564 Added function to create new sound from raw buffer 2021-03-26 15:36:11 +01:00
637c5c4677 Hopefully solved memory issues on deallocation 2021-02-17 14:24:43 +01:00
852710d15d JA_GetMusicState & JA_GetChannelState replace paused ones 2021-02-07 22:06:21 +01:00
f94d9294eb #3 Un par de warnings tontos.. 2021-02-05 13:37:56 +01:00
a3527dcad3 Solved some crashes when no music loaded 2021-02-05 13:36:08 +01:00
7 changed files with 599 additions and 197 deletions

1
.gitignore vendored
View File

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

View File

@@ -1,217 +1,477 @@
#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>
#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 };
}; };
enum JA_Channel_state { JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED }; struct JA_Channel_t
{
struct JA_Channel_t { JA_Sound_t *sound { nullptr };
JA_Sound sound; int pos { 0 };
int pos {0}; int times { 0 };
int times {0}; int group { 0 };
JA_Channel_state state { JA_CHANNEL_FREE }; SDL_AudioStream *stream { nullptr };
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
{
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
Uint32 length { 0 };
Uint8 *buffer { nullptr };
char *filename { nullptr };
struct JA_Music_t { int pos { 0 };
int samples {0}; int times { 0 };
int pos {0}; SDL_AudioStream *stream { nullptr };
int times {0}; JA_Music_state state { JA_MUSIC_INVALID };
short* output {NULL};
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];
bool JA_musicEnabled { true };
bool JA_soundEnabled { true };
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_memcpy(stream, current_music->output+current_music->pos, size);
current_music->pos += size/2;
if (size < len) { void JA_Update()
if (current_music->times != 0) { {
SDL_memcpy(stream+size, current_music->output, len-size); 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);
}
if (current_music->times>0) current_music->times--;
}
else
{
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0) JA_StopMusic();
}
} }
// Mixar els channels mi amol
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { if (JA_soundEnabled)
if (channels[i].state == JA_CHANNEL_PLAYING) { {
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos); for (int i=0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, 64); if (channels[i].state == JA_CHANNEL_PLAYING)
channels[i].pos += size; {
if (size < len) { if (channels[i].times != 0)
if (channels[i].times != 0) { {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, 64); if (SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length/2)) {
channels[i].pos = len-size; SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
if (channels[i].times > 0) channels[i].times--; if (channels[i].times>0) channels[i].times--;
} else { }
JA_StopChannel(i); }
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
SDL_AudioDeviceID sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
SDL_PauseAudioDevice(sdlAudioDevice, 0); SDL_Log("Iniciant JailAudio...");
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);
} }
JA_Music JA_LoadMusic(const char* filename) { void JA_Quit()
{
//if (JA_timerID) SDL_RemoveTimer(JA_timerID);
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = 0;
}
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length)
{
JA_Music_t *music = new JA_Music_t();
int chan, samplerate; int chan, samplerate;
JA_Music music = (JA_Music)SDL_malloc(sizeof(JA_Music_t)); short *output;
music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output); music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
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->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->pos = 0;
music->state = JA_MUSIC_STOPPED; music->state = JA_MUSIC_STOPPED;
return music; return music;
} }
void JA_PlayMusic(JA_Music music, const int loop) { JA_Music_t *JA_LoadMusic(const char* filename)
int chan, samplerate; {
if (current_music != NULL) { // [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
current_music->pos = 0; FILE *f = fopen(filename, "rb");
current_music->state = JA_MUSIC_STOPPED; fseek(f, 0, SEEK_END);
} long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8*)malloc(fsize + 1);
if (fread(buffer, fsize, 1, f)!=1) return NULL;
fclose(f);
JA_Music_t *music = JA_LoadMusic(buffer, fsize);
music->filename = (char*)malloc(strlen(filename)+1);
strcpy(music->filename, filename);
free(buffer);
return music;
}
void JA_PlayMusic(JA_Music_t *music, const int loop)
{
if (!JA_musicEnabled) return;
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->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->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->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;
} }
bool JA_IsMusicPlaying() { void JA_FadeOutMusic(const int milliseconds)
return current_music->state == JA_MUSIC_PLAYING; {
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;
} }
void JA_DeleteMusic(JA_Music music) { JA_Music_state JA_GetMusicState()
if (current_music == music) current_music = NULL; {
free(music->output); if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
free(music); if (!current_music) return JA_MUSIC_INVALID;
return current_music->state;
} }
JA_Sound JA_LoadSound(const char* filename) { void JA_DeleteMusic(JA_Music_t *music)
JA_Sound sound = new JA_Sound_t(); {
SDL_AudioSpec wavSpec; if (current_music == music) current_music = nullptr;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length); SDL_free(music->buffer);
if (music->stream) SDL_DestroyAudioStream(music->stream);
delete music;
}
SDL_AudioCVT cvt; float JA_SetMusicVolume(float volume)
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq); {
cvt.len = sound->length; JA_musicVolume = SDL_clamp( volume, 0.0f, 1.0f );
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult); if (current_music) SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
SDL_memcpy(cvt.buf, sound->buffer, sound->length); return JA_musicVolume;
SDL_ConvertAudio(&cvt); }
free(sound->buffer);
sound->buffer = cvt.buf; void JA_SetMusicPosition(float value)
sound->length = cvt.len_cvt; {
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->length = length;
return sound;
}
JA_Sound_t *JA_LoadSound(uint8_t* buffer, uint32_t size)
{
JA_Sound_t *sound = new JA_Sound_t();
SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size),1, &sound->spec, &sound->buffer, &sound->length);
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);
} }
SDL_FreeWAV(sound->buffer); SDL_free(sound->buffer);
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;
} }
} }
bool JA_IsChannelPlaying(const int channel) { JA_Channel_state JA_GetChannelState(const int channel)
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return false; {
return channels[channel].state == JA_CHANNEL_PLAYING; if (!JA_soundEnabled) return JA_SOUND_DISABLED;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state;
} }
float JA_SetSoundVolume(float volume, const int group)
{
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;
}
void JA_EnableSound(const bool value)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PLAYING) JA_StopChannel(i);
}
JA_soundEnabled = value;
}
float JA_SetVolume(float volume)
{
JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
return JA_musicVolume;
}
#endif

View File

@@ -1,23 +1,43 @@
#pragma once #pragma once
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
typedef struct JA_Sound_t *JA_Sound; enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED };
typedef struct JA_Music_t *JA_Music; enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED };
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels); struct JA_Sound_t;
struct JA_Music_t;
JA_Music JA_LoadMusic(const char* filename); void JA_Update();
void JA_PlayMusic(JA_Music music, const int loop = -1);
void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels);
void JA_Quit();
JA_Music_t *JA_LoadMusic(const char* filename);
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();
bool JA_IsMusicPlaying(); void JA_FadeOutMusic(const int milliseconds);
void JA_DeleteMusic(JA_Music music); JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music_t *music);
float JA_SetMusicVolume(float volume);
void JA_SetMusicPosition(float value);
float JA_GetMusicPosition();
void JA_EnableMusic(const bool value);
JA_Sound JA_LoadSound(const char* filename); JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
int JA_PlaySound(JA_Sound sound, const int loop = 0); 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);
bool JA_IsChannelPlaying(const int channel); JA_Channel_state JA_GetChannelState(const int channel);
void JA_DeleteSound(JA_Sound sound); 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,53 +1,73 @@
#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>
SDL_Event event; SDL_Event event;
SDL_Window *sdlWindow; 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);
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_IsMusicPlaying()) { JA_PauseMusic(); } else { JA_ResumeMusic(); } if (JA_GetMusicState() == JA_MUSIC_PLAYING) { JA_PauseMusic(); } else { JA_ResumeMusic(); }
break; break;
case SDL_SCANCODE_2: // Si pulsem la tecla '2' sona el wav 1 vegada case SDL_SCANCODE_2: // Si pulsem la tecla '2' sona el wav 1 vegada
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_IsChannelPlaying(channel)) { JA_PauseChannel(channel); } else { JA_ResumeChannel(channel); } if (JA_GetChannelState(channel) == JA_CHANNEL_PLAYING) { JA_PauseChannel(channel); } else { JA_ResumeChannel(channel); }
break; break;
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:
volume = JA_SetVolume(volume+0.1f);
break;
case SDL_SCANCODE_DOWN:
volume = JA_SetVolume(volume-0.1f);
break;
case SDL_SCANCODE_ESCAPE:
should_exit = true;
break;
default:
break;
} }
} }
} }
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;

70
readme.md Normal file
View File

@@ -0,0 +1,70 @@
# JailAudio v1.2
JailAudio es una xicoteta api per a reemplaçar lo basic de *SDL_mixer*. Amb ella es poden carregar cançons en format **OGG** o sons en format **WAV**. Per a usar-la nomes tindreu que incloure els arxius `jail_audio.cpp`, `jail_audio.h` i `stb_vorbis.c` al vostre projecte. El seu us es molt senzill i es pot vore un example a l'arxiu `main.cpp`.
## Inicialització
### `void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);`
Inicialitza el subsistema de audio. Es pot especificar la _frequència_, _format_ i _canals_, de la mateixa forma que abans creaveu el `SDL_AudioDevice`.
### `void JA_Quit();`
Tanquem la paraeta.
### `int JA_SetVolume(int volume);`
Canvia el volum general. Es un valor entre 0 i 128. Per defecte està a 128. La música al 100%, el só al 50%.
## Música
### `JA_Music JA_LoadMusic(const char* filename);`
Carrega un arxiu **OGG** en memoria i el guarda a una variable de tipus `JA_Music`. Es un punter opac, així que nomes val pa usar-lo com a referència a l'hora de fer-lo sonar.
### `void JA_PlayMusic(JA_Music music, const int loop);`
Comença a tocar un **OGG**. Se li pot dir que faça loop (`-1` fa loop, `0` no fa loop (sona 1 vegada), `1` repeteix el so (sona 2 vegades), etc...). Si estava sonant altra musica, pos la para i a prendre per cul.
### `void JA_PauseMusic();`
Pausa la música.
### `void JA_ResumeMusic();`
Continúa la música per on shavia pausat.
### `void JA_StopMusic();`
Pos això...
### `int JA_SetMusicVolume(int volume);`
Canvia el volum de la música. Es un valor entre 0 i 128. Per defecte està a 128.
### `JA_Music_state JA_GetMusicState();`
Torna el estat de la música, que pot ser `JA_MUSIC_INVALID`, `JA_MUSIC_PLAYING`, `JA_MUSIC_PAUSED`o `JA_MUSIC_STOPPED`.
### `void JA_DeleteMusic(JA_Music music);`
Esborra de la memòria una cançò prèviament carregada. Si está sonant pos para de sonar, ningún problema.
## Efectes de só
### `JA_Sound JA_NewSound(Uint8* buffer, Uint32 length);`
Crea un nou só a partir d'un buffer en memòria.
### `JA_Sound JA_LoadSound(const char* filename);`
Carrega un àudio des d'un arxiu **WAV** i el guarda a una variable de tipus `JA_Sound`. Es un punter opac, així que nomes val pa usar-lo com a referència a l'hora de fer-lo sonar.
### `int JA_PlaySound(JA_Sound sound, const int loop);`
Fa sonar un só prèviament carregat. Se li pot dir que faça loop (`-1` fa loop, `0` no fa loop (sona 1 vegada), `1` repeteix el so (sona 2 vegades), etc...). Torna el número del canal en el que està sonant.
### `void JA_DeleteSound(JA_Sound sound);`
Esborra de la memòria un só prèviament carregat. Si el só estava sonant en eixe moment, pos el para, ningún problema.
### `int JA_SetSoundVolume(int volume);`
Especifica el volum dels efecte de só. Es un valor entre 0 i 128. Per defecte està a 64.
## Canals de só
### `void JA_PauseChannel(const int channel);`
Pausa el só que estiga sonant en el canal especificat. Si s'especifica `-1`, pausa tots els canals que estigueren sonant en eixe moment.
### `void JA_ResumeChannel(const int channel);`
Continua sonant el canal especificat, si es que estava pausat. Si s'especifica `-1`, fa que tots els canals que estigueren pausats es despausen i continuen.
### `void JA_StopChannel(const int channel);`
Para un canal i el deixa lliure. Si s'especifica `-1`, para tots els canals que estigueren sonant en eixe moment.
### `JA_Channel_state JA_GetChannelState(const int channel);`
Torna el estat del canal especificat, que pot ser `JA_CHANNEL_INVALID`, `JA_CHANNEL_FREE`,`JA_CHANNEL_PLAYING` o `JA_CHANNEL_PAUSED`.

View File

@@ -1,4 +1,4 @@
// Ogg Vorbis audio decoder - v1.20 - public domain // Ogg Vorbis audio decoder - v1.22 - public domain
// http://nothings.org/stb_vorbis/ // http://nothings.org/stb_vorbis/
// //
// Original version written by Sean Barrett in 2007. // Original version written by Sean Barrett in 2007.
@@ -29,12 +29,15 @@
// Bernhard Wodo Evan Balster github:alxprd // Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart // Phillip Bennefall Rohit Thiago Goulart
// github:manxorist saga musix github:infatum // github:manxorist Saga Musix github:infatum
// Timur Gagiev Maxwell Koo Peter Waller // Timur Gagiev Maxwell Koo Peter Waller
// github:audinowho Dougall Johnson David Reid // github:audinowho Dougall Johnson David Reid
// github:Clownacy Pedro J. Estebanez Remi Verschelde // github:Clownacy Pedro J. Estebanez Remi Verschelde
// AnthoFoxo github:morlat Gabriel Ravier
// //
// Partial history: // Partial history:
// 1.22 - 2021-07-11 - various small fixes
// 1.21 - 2021-07-02 - fix bug for files with no comments
// 1.20 - 2020-07-11 - several small fixes // 1.20 - 2020-07-11 - several small fixes
// 1.19 - 2020-02-05 - warnings // 1.19 - 2020-02-05 - warnings
// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc. // 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
@@ -220,6 +223,12 @@ extern int stb_vorbis_decode_frame_pushdata(
// channel. In other words, (*output)[0][0] contains the first sample from // channel. In other words, (*output)[0][0] contains the first sample from
// the first channel, and (*output)[1][0] contains the first sample from // the first channel, and (*output)[1][0] contains the first sample from
// the second channel. // the second channel.
//
// *output points into stb_vorbis's internal output buffer storage; these
// buffers are owned by stb_vorbis and application code should not free
// them or modify their contents. They are transient and will be overwritten
// once you ask for more data to get decoded, so be sure to grab any data
// you need before then.
extern void stb_vorbis_flush_pushdata(stb_vorbis *f); extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
// inform stb_vorbis that your next datablock will not be contiguous with // inform stb_vorbis that your next datablock will not be contiguous with
@@ -579,7 +588,7 @@ enum STBVorbisError
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h> #include <malloc.h>
#endif #endif
#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__) #if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__)
#include <alloca.h> #include <alloca.h>
#endif #endif
#else // STB_VORBIS_NO_CRT #else // STB_VORBIS_NO_CRT
@@ -646,6 +655,12 @@ typedef signed int int32;
typedef float codetype; typedef float codetype;
#ifdef _MSC_VER
#define STBV_NOTUSED(v) (void)(v)
#else
#define STBV_NOTUSED(v) (void)sizeof(v)
#endif
// @NOTE // @NOTE
// //
// Some arrays below are tagged "//varies", which means it's actually // Some arrays below are tagged "//varies", which means it's actually
@@ -1046,7 +1061,7 @@ static float float32_unpack(uint32 x)
uint32 sign = x & 0x80000000; uint32 sign = x & 0x80000000;
uint32 exp = (x & 0x7fe00000) >> 21; uint32 exp = (x & 0x7fe00000) >> 21;
double res = sign ? -(double)mantissa : (double)mantissa; double res = sign ? -(double)mantissa : (double)mantissa;
return (float) ldexp((float)res, exp-788); return (float) ldexp((float)res, (int)exp-788);
} }
@@ -1077,6 +1092,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
// find the first entry // find the first entry
for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
if (k == n) { assert(c->sorted_entries == 0); return TRUE; } if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
assert(len[k] < 32); // no error return required, code reading lens checks this
// add to the list // add to the list
add_entry(c, 0, k, m++, len[k], values); add_entry(c, 0, k, m++, len[k], values);
// add all available leaves // add all available leaves
@@ -1090,6 +1106,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
uint32 res; uint32 res;
int z = len[i], y; int z = len[i], y;
if (z == NO_CODE) continue; if (z == NO_CODE) continue;
assert(z < 32); // no error return required, code reading lens checks this
// find lowest available leaf (should always be earliest, // find lowest available leaf (should always be earliest,
// which is what the specification calls for) // which is what the specification calls for)
// note that this property, and the fact we can never have // note that this property, and the fact we can never have
@@ -1099,12 +1116,10 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
while (z > 0 && !available[z]) --z; while (z > 0 && !available[z]) --z;
if (z == 0) { return FALSE; } if (z == 0) { return FALSE; }
res = available[z]; res = available[z];
assert(z >= 0 && z < 32);
available[z] = 0; available[z] = 0;
add_entry(c, bit_reverse(res), i, m++, len[i], values); add_entry(c, bit_reverse(res), i, m++, len[i], values);
// propagate availability up the tree // propagate availability up the tree
if (z != len[i]) { if (z != len[i]) {
assert(len[i] >= 0 && len[i] < 32);
for (y=len[i]; y > z; --y) { for (y=len[i]; y > z; --y) {
assert(available[y] == 0); assert(available[y] == 0);
available[y] = res + (1 << (32-y)); available[y] = res + (1 << (32-y));
@@ -2577,34 +2592,33 @@ static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A,
while (z > base) { while (z > base) {
float k00,k11; float k00,k11;
float l00,l11;
k00 = z[-0] - z[-8]; k00 = z[-0] - z[ -8];
k11 = z[-1] - z[-9]; k11 = z[-1] - z[ -9];
z[-0] = z[-0] + z[-8]; l00 = z[-2] - z[-10];
z[-1] = z[-1] + z[-9]; l11 = z[-3] - z[-11];
z[-8] = k00; z[ -0] = z[-0] + z[ -8];
z[-9] = k11 ; z[ -1] = z[-1] + z[ -9];
z[ -2] = z[-2] + z[-10];
z[ -3] = z[-3] + z[-11];
z[ -8] = k00;
z[ -9] = k11;
z[-10] = (l00+l11) * A2;
z[-11] = (l11-l00) * A2;
k00 = z[ -2] - z[-10]; k00 = z[ -4] - z[-12];
k11 = z[ -3] - z[-11];
z[ -2] = z[ -2] + z[-10];
z[ -3] = z[ -3] + z[-11];
z[-10] = (k00+k11) * A2;
z[-11] = (k11-k00) * A2;
k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation
k11 = z[ -5] - z[-13]; k11 = z[ -5] - z[-13];
l00 = z[ -6] - z[-14];
l11 = z[ -7] - z[-15];
z[ -4] = z[ -4] + z[-12]; z[ -4] = z[ -4] + z[-12];
z[ -5] = z[ -5] + z[-13]; z[ -5] = z[ -5] + z[-13];
z[-12] = k11;
z[-13] = k00;
k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation
k11 = z[ -7] - z[-15];
z[ -6] = z[ -6] + z[-14]; z[ -6] = z[ -6] + z[-14];
z[ -7] = z[ -7] + z[-15]; z[ -7] = z[ -7] + z[-15];
z[-14] = (k00+k11) * A2; z[-12] = k11;
z[-15] = (k00-k11) * A2; z[-13] = -k00;
z[-14] = (l11-l00) * A2;
z[-15] = (l00+l11) * -A2;
iter_54(z); iter_54(z);
iter_54(z-8); iter_54(z-8);
@@ -3069,6 +3083,7 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f
for (q=1; q < g->values; ++q) { for (q=1; q < g->values; ++q) {
j = g->sorted_order[q]; j = g->sorted_order[q];
#ifndef STB_VORBIS_NO_DEFER_FLOOR #ifndef STB_VORBIS_NO_DEFER_FLOOR
STBV_NOTUSED(step2_flag);
if (finalY[j] >= 0) if (finalY[j] >= 0)
#else #else
if (step2_flag[j]) if (step2_flag[j])
@@ -3171,6 +3186,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
// WINDOWING // WINDOWING
STBV_NOTUSED(left_end);
n = f->blocksize[m->blockflag]; n = f->blocksize[m->blockflag];
map = &f->mapping[m->mapping]; map = &f->mapping[m->mapping];
@@ -3368,7 +3384,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
// this isn't to spec, but spec would require us to read ahead // this isn't to spec, but spec would require us to read ahead
// and decode the size of all current frames--could be done, // and decode the size of all current frames--could be done,
// but presumably it's not a commonly used feature // but presumably it's not a commonly used feature
f->current_loc = -n2; // start of first frame is positioned for discard f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around)
// we might have to discard samples "from" the next frame too, // we might have to discard samples "from" the next frame too,
// if we're lapping a large block then a small at the start? // if we're lapping a large block then a small at the start?
f->discard_samples_deferred = n - right_end; f->discard_samples_deferred = n - right_end;
@@ -3642,9 +3658,11 @@ static int start_decoder(vorb *f)
f->vendor[len] = (char)'\0'; f->vendor[len] = (char)'\0';
//user comments //user comments
f->comment_list_length = get32_packet(f); f->comment_list_length = get32_packet(f);
if (f->comment_list_length > 0) { f->comment_list = NULL;
f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length)); if (f->comment_list_length > 0)
if (f->comment_list == NULL) return error(f, VORBIS_outofmem); {
f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length));
if (f->comment_list == NULL) return error(f, VORBIS_outofmem);
} }
for(i=0; i < f->comment_list_length; ++i) { for(i=0; i < f->comment_list_length; ++i) {
@@ -3867,8 +3885,7 @@ static int start_decoder(vorb *f)
unsigned int div=1; unsigned int div=1;
for (k=0; k < c->dimensions; ++k) { for (k=0; k < c->dimensions; ++k) {
int off = (z / div) % c->lookup_values; int off = (z / div) % c->lookup_values;
float val = mults[off]; float val = mults[off]*c->delta_value + c->minimum_value + last;
val = mults[off]*c->delta_value + c->minimum_value + last;
c->multiplicands[j*c->dimensions + k] = val; c->multiplicands[j*c->dimensions + k] = val;
if (c->sequence_p) if (c->sequence_p)
last = val; last = val;
@@ -3951,7 +3968,7 @@ static int start_decoder(vorb *f)
if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
} }
for (k=0; k < 1 << g->class_subclasses[j]; ++k) { for (k=0; k < 1 << g->class_subclasses[j]; ++k) {
g->subclass_books[j][k] = get_bits(f,8)-1; g->subclass_books[j][k] = (int16)get_bits(f,8)-1;
if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
} }
} }
@@ -4509,6 +4526,7 @@ stb_vorbis *stb_vorbis_open_pushdata(
*error = VORBIS_need_more_data; *error = VORBIS_need_more_data;
else else
*error = p.error; *error = p.error;
vorbis_deinit(&p);
return NULL; return NULL;
} }
f = vorbis_alloc(&p); f = vorbis_alloc(&p);
@@ -4566,7 +4584,7 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)
header[i] = get8(f); header[i] = get8(f);
if (f->eof) return 0; if (f->eof) return 0;
if (header[4] != 0) goto invalid; if (header[4] != 0) goto invalid;
goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24); goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24);
for (i=22; i < 26; ++i) for (i=22; i < 26; ++i)
header[i] = 0; header[i] = 0;
crc = 0; crc = 0;
@@ -4970,7 +4988,7 @@ unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
// set. whoops! // set. whoops!
break; break;
} }
previous_safe = last_page_loc+1; //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging
last_page_loc = stb_vorbis_get_file_offset(f); last_page_loc = stb_vorbis_get_file_offset(f);
} }
@@ -5081,7 +5099,10 @@ stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const st
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
{ {
stb_vorbis *f, p; stb_vorbis *f, p;
if (data == NULL) return NULL; if (!data) {
if (error) *error = VORBIS_unexpected_eof;
return NULL;
}
vorbis_init(&p, alloc); vorbis_init(&p, alloc);
p.stream = (uint8 *) data; p.stream = (uint8 *) data;
p.stream_end = (uint8 *) data + len; p.stream_end = (uint8 *) data + len;
@@ -5156,11 +5177,11 @@ static void copy_samples(short *dest, float *src, int len)
static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
{ {
#define BUFFER_SIZE 32 #define STB_BUFFER_SIZE 32
float buffer[BUFFER_SIZE]; float buffer[STB_BUFFER_SIZE];
int i,j,o,n = BUFFER_SIZE; int i,j,o,n = STB_BUFFER_SIZE;
check_endianness(); check_endianness();
for (o = 0; o < len; o += BUFFER_SIZE) { for (o = 0; o < len; o += STB_BUFFER_SIZE) {
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
if (o + n > len) n = len - o; if (o + n > len) n = len - o;
for (j=0; j < num_c; ++j) { for (j=0; j < num_c; ++j) {
@@ -5177,16 +5198,17 @@ static void compute_samples(int mask, short *output, int num_c, float **data, in
output[o+i] = v; output[o+i] = v;
} }
} }
#undef STB_BUFFER_SIZE
} }
static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
{ {
#define BUFFER_SIZE 32 #define STB_BUFFER_SIZE 32
float buffer[BUFFER_SIZE]; float buffer[STB_BUFFER_SIZE];
int i,j,o,n = BUFFER_SIZE >> 1; int i,j,o,n = STB_BUFFER_SIZE >> 1;
// o is the offset in the source data // o is the offset in the source data
check_endianness(); check_endianness();
for (o = 0; o < len; o += BUFFER_SIZE >> 1) { for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) {
// o2 is the offset in the output data // o2 is the offset in the output data
int o2 = o << 1; int o2 = o << 1;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
@@ -5216,6 +5238,7 @@ static void compute_stereo_samples(short *output, int num_c, float **data, int d
output[o2+i] = v; output[o2+i] = v;
} }
} }
#undef STB_BUFFER_SIZE
} }
static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
@@ -5288,8 +5311,6 @@ int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short
float **outputs; float **outputs;
int len = num_shorts / channels; int len = num_shorts / channels;
int n=0; int n=0;
int z = f->channels;
if (z > channels) z = channels;
while (n < len) { while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start; int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n; if (n+k >= len) k = len - n;
@@ -5308,8 +5329,6 @@ int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, in
{ {
float **outputs; float **outputs;
int n=0; int n=0;
int z = f->channels;
if (z > channels) z = channels;
while (n < len) { while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start; int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n; if (n+k >= len) k = len - n;

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.*
}