feat(title): música title.ogg amb fade-out, SFX player_start al START i bombament continu del stream sortint per evitar talls quan SDL drena a 2x

This commit is contained in:
JailDesigner committed 2026-05-06 17:44:30 +02:00
1 parent 36fc496226
commit 921e10bbb3
10 files changed
+109 -1

No files matched your search

+44 -1
View File
@@ -127,11 +127,44 @@ namespace Ja {
void Engine::updateOutgoingFade() {
if (outgoing_music_.stream == nullptr || !outgoing_music_.fade.active) { return; }
// Mentre la fosa està activa, mantenim el stream amb una reserva
// de samples per davant del cursor (mateix patró que pumpMusic
// per al current_music_). Així el stream no es buida ni quan SDL
// drena més ràpid del previst en haver sounds bound a la mateixa
// device. Si l'OGG arriba a EOF, rebobina (la fosa pot ser més
// llarga que la pista).
if (outgoing_music_.music != nullptr && outgoing_music_.music->vorbis != nullptr) {
const Music& music = *outgoing_music_.music;
const int BYTES_PER_SECOND = music.spec.freq * music.spec.channels * MUSIC_BYTES_PER_SAMPLE;
const int LOW_WATER = static_cast<int>(MUSIC_LOW_WATER_SECONDS * static_cast<float>(BYTES_PER_SECOND));
while (SDL_GetAudioStreamAvailable(outgoing_music_.stream) < LOW_WATER) {
short chunk[MUSIC_CHUNK_SHORTS];
const int SAMPLES = stb_vorbis_get_samples_short_interleaved(
music.vorbis,
music.spec.channels,
static_cast<short*>(chunk),
MUSIC_CHUNK_SHORTS);
if (SAMPLES <= 0) {
stb_vorbis_seek_start(music.vorbis);
continue;
}
const int BYTES = SAMPLES * music.spec.channels * MUSIC_BYTES_PER_SAMPLE;
SDL_PutAudioStreamData(outgoing_music_.stream, static_cast<const void*>(chunk), BYTES);
}
}
const float PROGRESS = fadeProgress(outgoing_music_.fade);
if (PROGRESS >= 1.0F) {
SDL_DestroyAudioStream(outgoing_music_.stream);
outgoing_music_.stream = nullptr;
outgoing_music_.fade.active = false;
// Deixem el Vorbis del Music original en un estat conegut per
// a la pròxima reproducció. (playMusic també fa seek_start,
// però fer-ho ací evita estats intermedis si algú consulta.)
if (outgoing_music_.music != nullptr && outgoing_music_.music->vorbis != nullptr) {
stb_vorbis_seek_start(outgoing_music_.music->vorbis);
}
outgoing_music_.music = nullptr;
} else {
SDL_SetAudioStreamGain(outgoing_music_.stream, outgoing_music_.fade.initial_volume * (1.0F - PROGRESS));
}
@@ -191,7 +224,14 @@ namespace Ja {
}
preFillOutgoing(current_music_, duration_ms);
outgoing_music_.stream = current_music_->stream;
// Guardem la referència al Music perquè updateOutgoingFade puga
// seguir bombant Vorbis cap al stream durant tota la fosa. NO fem
// seek_start ací: la decompressió ha de continuar des d'on estava
// perquè el so siga continu. El seek_start es farà quan la fosa
// acabe (o quan playMusic la interrompi via stopMusic).
outgoing_music_.music = current_music_;
outgoing_music_.fade = {
.active = true,
.start_time = SDL_GetTicks(),
@@ -200,7 +240,6 @@ namespace Ja {
};
current_music_->stream = nullptr;
current_music_->state = MusicState::STOPPED;
if (current_music_->vorbis != nullptr) { stb_vorbis_seek_start(current_music_->vorbis); }
}
template <typename Fn>
@@ -265,6 +304,10 @@ namespace Ja {
SDL_DestroyAudioStream(outgoing_music_.stream);
outgoing_music_.stream = nullptr;
outgoing_music_.fade.active = false;
if (outgoing_music_.music != nullptr && outgoing_music_.music->vorbis != nullptr) {
stb_vorbis_seek_start(outgoing_music_.music->vorbis);
}
outgoing_music_.music = nullptr;
}
incoming_fade_.active = false;