refactor: jail_audio RAII polish — JA_Music_t amb vector<Uint8>/string + elimina overload i camp morts

This commit is contained in:
2026-04-16 10:02:55 +02:00
parent b3ff620c81
commit f9346add79

View File

@@ -7,6 +7,9 @@
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#define STB_VORBIS_HEADER_ONLY
#include "external/stb_vorbis.h"
@@ -48,13 +51,15 @@ struct JA_Channel_t {
struct JA_Music_t {
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
// OGG comprimit en memòria. Propietat nostra; es copia des del fitxer una
// sola vegada en JA_LoadMusic i es descomprimix en chunks per streaming.
Uint8* ogg_data{nullptr};
Uint32 ogg_length{0};
// OGG comprimit en memòria. Propietat nostra; es copia des del buffer
// d'entrada una sola vegada en JA_LoadMusic i es descomprimix en chunks
// per streaming. Com que stb_vorbis guarda un punter persistent al
// `.data()` d'aquest vector, no el podem resize'jar un cop establert
// (una reallocation invalidaria el punter que el decoder conserva).
std::vector<Uint8> ogg_data;
stb_vorbis* vorbis{nullptr}; // handle del decoder, viu tot el cicle del JA_Music_t
char* filename{nullptr};
std::string filename;
int times{0}; // loops restants (-1 = infinit, 0 = un sol play)
SDL_AudioStream* stream{nullptr};
@@ -200,26 +205,23 @@ inline void JA_Quit() {
inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
if (!buffer || length == 0) return nullptr;
// Còpia del OGG comprimit: stb_vorbis llig de forma persistent aquesta
// memòria mentre el handle estiga viu, així que hem de posseir-la nosaltres.
Uint8* ogg_copy = static_cast<Uint8*>(SDL_malloc(length));
if (!ogg_copy) return nullptr;
SDL_memcpy(ogg_copy, buffer, length);
// Allocem el JA_Music_t primer per aprofitar el seu `std::vector<Uint8>`
// com a propietari del OGG comprimit. stb_vorbis guarda un punter
// persistent al buffer; com que ací no el resize'jem, el .data() és
// estable durant tot el cicle de vida del music.
auto* music = new JA_Music_t();
music->ogg_data.assign(buffer, buffer + length);
int error = 0;
stb_vorbis* vorbis = stb_vorbis_open_memory(ogg_copy, static_cast<int>(length), &error, nullptr);
if (!vorbis) {
SDL_free(ogg_copy);
music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(),
static_cast<int>(length), &error, nullptr);
if (!music->vorbis) {
SDL_Log("JA_LoadMusic: stb_vorbis_open_memory failed (error %d)", error);
delete music;
return nullptr;
}
auto* music = new JA_Music_t();
music->ogg_data = ogg_copy;
music->ogg_length = length;
music->vorbis = vorbis;
const stb_vorbis_info info = stb_vorbis_get_info(vorbis);
const stb_vorbis_info info = stb_vorbis_get_info(music->vorbis);
music->spec.channels = info.channels;
music->spec.freq = static_cast<int>(info.sample_rate);
music->spec.format = SDL_AUDIO_S16;
@@ -228,38 +230,11 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
return music;
}
// Overload de compatibilitat: accepta filename per a no trencar els call
// sites existents que passaven el nom del fitxer junt amb el buffer.
// Overload amb filename — els callers l'usen per poder comparar la música
// en curs amb JA_GetMusicFilename() i no rearrancar-la si ja és la mateixa.
inline JA_Music_t* JA_LoadMusic(Uint8* buffer, Uint32 length, const char* filename) {
JA_Music_t* music = JA_LoadMusic(static_cast<const Uint8*>(buffer), length);
if (music && filename) {
music->filename = static_cast<char*>(malloc(strlen(filename) + 1));
if (music->filename) strcpy(music->filename, filename);
}
return music;
}
inline JA_Music_t* JA_LoadMusic(const char* filename) {
FILE* f = fopen(filename, "rb");
if (!f) return nullptr;
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
auto* buffer = static_cast<Uint8*>(malloc(fsize + 1));
if (!buffer) {
fclose(f);
return nullptr;
}
if (fread(buffer, fsize, 1, f) != 1) {
fclose(f);
free(buffer);
return nullptr;
}
fclose(f);
JA_Music_t* music = JA_LoadMusic(buffer, static_cast<Uint32>(fsize), filename);
free(buffer);
if (music && filename) music->filename = filename;
return music;
}
@@ -290,10 +265,10 @@ inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) {
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n");
}
inline char* JA_GetMusicFilename(JA_Music_t* music = nullptr) {
inline const char* JA_GetMusicFilename(JA_Music_t* music = nullptr) {
if (!music) music = current_music;
if (!music) return nullptr;
return music->filename;
if (!music || music->filename.empty()) return nullptr;
return music->filename.c_str();
}
inline void JA_PauseMusic() {
@@ -352,8 +327,8 @@ inline void JA_DeleteMusic(JA_Music_t* music) {
}
if (music->stream) SDL_DestroyAudioStream(music->stream);
if (music->vorbis) stb_vorbis_close(music->vorbis);
SDL_free(music->ogg_data);
free(music->filename);
// ogg_data (std::vector) i filename (std::string) s'alliberen sols
// al destructor de JA_Music_t.
delete music;
}