neteja tidy a source/core/system i audio amb fixes d'arrel
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
// Implementación de stb_vorbis (debe estar ANTES de incluir jail_audio.hpp).
|
||||
// clang-format off
|
||||
#undef STB_VORBIS_HEADER_ONLY
|
||||
#include "external/stb_vorbis.c"
|
||||
#include "external/stb_vorbis.h"
|
||||
// stb_vorbis.c filtra les macros L, C i R (i PLAYBACK_*) al TU. Les netegem
|
||||
// perquè xocarien amb noms de paràmetres de plantilla en altres headers.
|
||||
#undef L
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath> // Para lround
|
||||
#include <cstdint> // Para int8_t, uint8_t
|
||||
#include <string> // Para string
|
||||
#include <utility> // Para move
|
||||
@@ -59,8 +60,8 @@ class Audio {
|
||||
|
||||
// --- Helpers de conversió per a la capa de presentació ---
|
||||
// UI (menús, notificacions) manega enters 0..100; internament viu float 0..1.
|
||||
static constexpr auto toPercent(float volume) -> int {
|
||||
return static_cast<int>((volume * 100.0F) + 0.5F);
|
||||
static auto toPercent(float volume) -> int {
|
||||
return static_cast<int>(std::lround(volume * 100.0F));
|
||||
}
|
||||
static constexpr auto fromPercent(int percent) -> float {
|
||||
return static_cast<float>(percent) / 100.0F;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <vector> // Para std::vector
|
||||
|
||||
#define STB_VORBIS_HEADER_ONLY
|
||||
#include "external/stb_vorbis.c" // Para stb_vorbis_open_memory i streaming
|
||||
#include "external/stb_vorbis.h" // Para stb_vorbis_open_memory i streaming
|
||||
|
||||
// Deleter stateless per a buffers reservats amb `SDL_malloc` / `SDL_LoadWAV*`.
|
||||
// Compatible amb `std::unique_ptr<Uint8[], SDLFreeDeleter>` — zero size
|
||||
@@ -26,14 +26,14 @@ struct SDLFreeDeleter {
|
||||
};
|
||||
|
||||
// --- Public Enums ---
|
||||
enum JA_Channel_state {
|
||||
enum JA_Channel_state : std::uint8_t {
|
||||
JA_CHANNEL_INVALID,
|
||||
JA_CHANNEL_FREE,
|
||||
JA_CHANNEL_PLAYING,
|
||||
JA_CHANNEL_PAUSED,
|
||||
JA_SOUND_DISABLED,
|
||||
};
|
||||
enum JA_Music_state {
|
||||
enum JA_Music_state : std::uint8_t {
|
||||
JA_MUSIC_INVALID,
|
||||
JA_MUSIC_PLAYING,
|
||||
JA_MUSIC_PAUSED,
|
||||
@@ -42,7 +42,7 @@ enum JA_Music_state {
|
||||
};
|
||||
|
||||
// --- Struct Definitions ---
|
||||
enum {
|
||||
enum : std::uint8_t {
|
||||
JA_MAX_SIMULTANEOUS_CHANNELS = 20,
|
||||
JA_MAX_GROUPS = 2
|
||||
};
|
||||
@@ -57,10 +57,10 @@ struct JA_Sound_t {
|
||||
|
||||
struct JA_Channel_t {
|
||||
JA_Sound_t* sound{nullptr};
|
||||
SDL_AudioStream* stream{nullptr};
|
||||
int pos{0};
|
||||
int times{0};
|
||||
int group{0};
|
||||
SDL_AudioStream* stream{nullptr};
|
||||
JA_Channel_state state{JA_CHANNEL_FREE};
|
||||
};
|
||||
|
||||
@@ -199,63 +199,86 @@ inline void JA_PreFillOutgoing(JA_Music_t* music, int duration_ms) {
|
||||
|
||||
// --- Core Functions ---
|
||||
|
||||
// Fade-out de la música sortint (crossfade o fade-out a silenci). En acabar
|
||||
// destrueix l'AudioStream sortint.
|
||||
inline void JA_UpdateOutgoingFade() {
|
||||
if ((outgoing_music.stream == nullptr) || !outgoing_music.fade.active) {
|
||||
return;
|
||||
}
|
||||
const Uint64 elapsed = SDL_GetTicks() - outgoing_music.fade.start_time;
|
||||
if (elapsed >= static_cast<Uint64>(outgoing_music.fade.duration_ms)) {
|
||||
SDL_DestroyAudioStream(outgoing_music.stream);
|
||||
outgoing_music.stream = nullptr;
|
||||
outgoing_music.fade.active = false;
|
||||
return;
|
||||
}
|
||||
const float percent = static_cast<float>(elapsed) / static_cast<float>(outgoing_music.fade.duration_ms);
|
||||
SDL_SetAudioStreamGain(outgoing_music.stream, outgoing_music.fade.initial_volume * (1.0F - percent));
|
||||
}
|
||||
|
||||
// Fade-in de la música entrant (segona meitat d'un crossfade).
|
||||
inline void JA_UpdateIncomingFade() {
|
||||
if (!incoming_fade.active) {
|
||||
return;
|
||||
}
|
||||
const Uint64 elapsed = SDL_GetTicks() - incoming_fade.start_time;
|
||||
if (elapsed >= static_cast<Uint64>(incoming_fade.duration_ms)) {
|
||||
incoming_fade.active = false;
|
||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
|
||||
return;
|
||||
}
|
||||
const float percent = static_cast<float>(elapsed) / static_cast<float>(incoming_fade.duration_ms);
|
||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume * percent);
|
||||
}
|
||||
|
||||
// Manté l'stream de la música activa alimentat i para la reproducció si
|
||||
// el vorbis s'ha esgotat i no queden loops.
|
||||
inline void JA_UpdateCurrentMusic() {
|
||||
if (!JA_musicEnabled || current_music == nullptr || current_music->state != JA_MUSIC_PLAYING) {
|
||||
return;
|
||||
}
|
||||
JA_UpdateIncomingFade();
|
||||
JA_PumpMusic(current_music);
|
||||
if (current_music->times == 0 && SDL_GetAudioStreamAvailable(current_music->stream) == 0) {
|
||||
JA_StopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
// Avança l'estat d'un sol canal de so: alimenta més samples mentre quedin
|
||||
// loops; si ja no queden i l'stream s'ha buidat, atura el canal.
|
||||
inline void JA_UpdateSoundChannel(int channel_index) {
|
||||
JA_Channel_t& ch = channels[channel_index];
|
||||
if (ch.state != JA_CHANNEL_PLAYING) {
|
||||
return;
|
||||
}
|
||||
if (ch.times == 0) {
|
||||
if (SDL_GetAudioStreamAvailable(ch.stream) == 0) {
|
||||
JA_StopChannel(channel_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (static_cast<Uint32>(SDL_GetAudioStreamAvailable(ch.stream)) < (ch.sound->length / 2)) {
|
||||
SDL_PutAudioStreamData(ch.stream, ch.sound->buffer.get(), ch.sound->length);
|
||||
if (ch.times > 0) {
|
||||
ch.times--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Avança tots els canals de so actius.
|
||||
inline void JA_UpdateSoundChannels() {
|
||||
if (!JA_soundEnabled) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i) {
|
||||
JA_UpdateSoundChannel(i);
|
||||
}
|
||||
}
|
||||
|
||||
inline void JA_Update() {
|
||||
// --- Outgoing music fade-out (crossfade o fade-out a silencio) ---
|
||||
if ((outgoing_music.stream != nullptr) && outgoing_music.fade.active) {
|
||||
Uint64 now = SDL_GetTicks();
|
||||
Uint64 elapsed = now - outgoing_music.fade.start_time;
|
||||
if (elapsed >= (Uint64)outgoing_music.fade.duration_ms) {
|
||||
SDL_DestroyAudioStream(outgoing_music.stream);
|
||||
outgoing_music.stream = nullptr;
|
||||
outgoing_music.fade.active = false;
|
||||
} else {
|
||||
float percent = (float)elapsed / (float)outgoing_music.fade.duration_ms;
|
||||
SDL_SetAudioStreamGain(outgoing_music.stream, outgoing_music.fade.initial_volume * (1.0F - percent));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Current music ---
|
||||
if (JA_musicEnabled && (current_music != nullptr) && current_music->state == JA_MUSIC_PLAYING) {
|
||||
// Fade-in (parte de un crossfade)
|
||||
if (incoming_fade.active) {
|
||||
Uint64 now = SDL_GetTicks();
|
||||
Uint64 elapsed = now - incoming_fade.start_time;
|
||||
if (elapsed >= (Uint64)incoming_fade.duration_ms) {
|
||||
incoming_fade.active = false;
|
||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
|
||||
} else {
|
||||
float percent = (float)elapsed / (float)incoming_fade.duration_ms;
|
||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume * percent);
|
||||
}
|
||||
}
|
||||
|
||||
// Streaming: rellenem l'stream fins al low-water-mark i parem si el
|
||||
// vorbis s'ha esgotat i no queden loops.
|
||||
JA_PumpMusic(current_music);
|
||||
if (current_music->times == 0 && SDL_GetAudioStreamAvailable(current_music->stream) == 0) {
|
||||
JA_StopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
// --- Sound channels ---
|
||||
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 ((Uint32)SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length / 2)) {
|
||||
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer.get(), channels[i].sound->length);
|
||||
if (channels[i].times > 0) {
|
||||
channels[i].times--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) {
|
||||
JA_StopChannel(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
JA_UpdateOutgoingFade();
|
||||
JA_UpdateCurrentMusic();
|
||||
JA_UpdateSoundChannels();
|
||||
}
|
||||
|
||||
inline void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels) {
|
||||
@@ -586,7 +609,7 @@ inline void JA_EnableMusic(const bool value) {
|
||||
inline auto JA_LoadSound(uint8_t* buffer, uint32_t size) -> JA_Sound_t* {
|
||||
auto sound = std::make_unique<JA_Sound_t>();
|
||||
Uint8* raw = nullptr;
|
||||
if (!SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), 1, &sound->spec, &raw, &sound->length)) {
|
||||
if (!SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), true, &sound->spec, &raw, &sound->length)) {
|
||||
std::cout << "Failed to load WAV from memory: " << SDL_GetError() << '\n';
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user