VERSIÓ 1.5.8:

- [NEW] Implementat streaming de OGGs
This commit is contained in:
2026-05-14 09:26:34 +02:00
parent 7ada99f766
commit 669090238a
2 changed files with 88 additions and 81 deletions
+87 -80
View File
@@ -23,14 +23,17 @@ namespace jail
{ {
struct music_t struct music_t
{ {
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 }; SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
Uint32 length { 0 }; SDL_AudioStream* stream { nullptr };
Uint8 *buffer { nullptr };
int pos { 0 }; const uint8_t* ogg_data { nullptr };
int times { 0 }; uint32_t ogg_length { 0 };
SDL_AudioStream *stream { nullptr };
music::state state { music::state::invalid }; stb_vorbis* vorbis { nullptr };
stb_vorbis_info info {};
int times { 0 };
music::state state { music::state::invalid };
}; };
static int current { -1 }; static int current { -1 };
@@ -87,10 +90,12 @@ namespace jail
static void updateMusic() static void updateMusic()
{ {
if (!music::enabled) return; if (!music::enabled) return;
if (music::current < 0 || music::current > static_cast<int>(music::musics.size())) return; if (music::current < 0) return;
auto &m = music::musics[music::current];
auto& m = music::musics[music::current];
if (m.state != music::state::playing) return; if (m.state != music::state::playing) return;
// Fade-out
if (music::fade::fading) { if (music::fade::fading) {
int time = SDL_GetTicks(); int time = SDL_GetTicks();
if (time > (music::fade::start_time + music::fade::duration)) { if (time > (music::fade::start_time + music::fade::duration)) {
@@ -98,23 +103,37 @@ namespace jail
music::stop(); music::stop();
return; return;
} else { } else {
const int time_passed = time - music::fade::start_time; float percent = float(time - music::fade::start_time) / float(music::fade::duration);
const float percent = (float)time_passed / (float)music::fade::duration; SDL_SetAudioStreamGain(m.stream, 1.0f - percent);
SDL_SetAudioStreamGain(m.stream, 1.0 - percent);
} }
} }
if (m.times != 0) // ¿Hay suficiente audio en el stream?
{ if (SDL_GetAudioStreamAvailable(m.stream) > 48000) return; // 1 segundo
if (SDL_GetAudioStreamAvailable(m.stream) < static_cast<int>(m.length/2)) {
SDL_PutAudioStreamData(m.stream, m.buffer, m.length); // Decodificar un bloque
const int SAMPLES = 4096;
static int16_t temp[SAMPLES * 2];
int n = stb_vorbis_get_samples_short_interleaved(
m.vorbis,
m.info.channels,
temp,
SAMPLES
);
if (n == 0) {
if (m.times != 0) {
stb_vorbis_seek_start(m.vorbis);
if (m.times > 0) m.times--;
return;
} else {
music::stop();
return;
} }
if (m.times>0) m.times--;
}
else
{
if (SDL_GetAudioStreamAvailable(m.stream) == 0) music::stop();
} }
SDL_PutAudioStreamData(m.stream, temp, n * m.info.channels * sizeof(int16_t));
} }
static void updateSound() static void updateSound()
@@ -194,26 +213,31 @@ namespace jail
{ {
int load(const uint8_t* buffer, uint32_t length) int load(const uint8_t* buffer, uint32_t length)
{ {
int music = 0; int idx = 0;
while (music < static_cast<int>(musics.size()) && musics[music].state != state::invalid) { music++; } while (idx < (int)musics.size() && musics[idx].state != state::invalid) idx++;
if (music == static_cast<int>(musics.size())) musics.emplace_back(); if (idx == (int)musics.size()) musics.emplace_back();
auto &m = musics[music]; auto& m = musics[idx];
int chan, samplerate; m.ogg_data = buffer;
short *output; m.ogg_length = length;
m.length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
m.spec.channels = chan; int error;
m.spec.freq = samplerate; m.vorbis = stb_vorbis_open_memory(buffer, length, &error, nullptr);
if (!m.vorbis) {
log_msg(LOG_FAIL, "stb_vorbis_open_memory failed: %d\n", error);
return -1;
}
m.info = stb_vorbis_get_info(m.vorbis);
m.spec.channels = m.info.channels;
m.spec.freq = m.info.sample_rate;
m.spec.format = SDL_AUDIO_S16; m.spec.format = SDL_AUDIO_S16;
m.buffer = (uint8_t*)SDL_malloc(m.length);
SDL_memcpy(m.buffer, output, m.length);
free(output);
m.pos = 0;
m.state = state::stopped; m.state = state::stopped;
return music; return idx;
} }
int load(const char* filename) int load(const char* filename)
@@ -236,23 +260,19 @@ namespace jail
void play(int mus, int loop) void play(int mus, int loop)
{ {
if (!music::enabled) return;
stop(); stop();
if (mus < 0 || mus >= static_cast<int>(musics.size())) {
log_msg(LOG_FAIL, "music::play: Illegal music handle: %i\n", mus);
return;
}
current = mus; current = mus;
auto &m = musics[current]; auto& m = musics[mus];
m.pos = 0;
m.state = state::playing;
m.times = loop; m.times = loop;
m.state = state::playing;
stb_vorbis_seek_start(m.vorbis);
m.stream = SDL_CreateAudioStream(&m.spec, &audioSpec); m.stream = SDL_CreateAudioStream(&m.spec, &audioSpec);
if (!SDL_PutAudioStreamData(m.stream, m.buffer, m.length)) log_msg(LOG_FAIL, "SDL_PutAudioStreamData failed!\n");
SDL_SetAudioStreamGain(m.stream, volume); SDL_SetAudioStreamGain(m.stream, volume);
if (!SDL_BindAudioStream(sdlAudioDevice, m.stream)) log_msg(LOG_FAIL, "SDL_BindAudioStream failed!\n"); SDL_BindAudioStream(sdlAudioDevice, m.stream);
//SDL_ResumeAudioStreamDevice(current->stream);
} }
void pause() void pause()
@@ -293,21 +313,13 @@ namespace jail
void stop() void stop()
{ {
if (!music::enabled || (current<0)) return; if (current < 0) return;
if (current>static_cast<int>(musics.size())) {
log_msg(LOG_FAIL, "music::stop: Illegal music handle: %i\n", current); auto& m = musics[current];
return;
}
auto &m = musics[current];
if (m.state == state::invalid) {
log_msg(LOG_FAIL, "music::stop: Invalidated music handle: %i\n", current);
return;
}
m.pos = 0;
m.state = state::stopped; m.state = state::stopped;
//SDL_PauseAudioStreamDevice(current->stream);
SDL_DestroyAudioStream(m.stream); if (m.stream) SDL_DestroyAudioStream(m.stream);
m.stream = nullptr; m.stream = nullptr;
} }
@@ -339,16 +351,16 @@ namespace jail
void destroy(int mus) void destroy(int mus)
{ {
if (current == mus) current = -1; if (mus < 0 || mus >= (int)musics.size()) return;
if (mus<0 || mus>static_cast<int>(musics.size())) {
log_msg(LOG_FAIL, "music::destroy: Illegal music handle: %i\n", mus); auto& m = musics[mus];
return;
}
auto &m = musics[mus];
SDL_free(m.buffer);
m.buffer = nullptr;
if (m.stream) SDL_DestroyAudioStream(m.stream); if (m.stream) SDL_DestroyAudioStream(m.stream);
if (m.vorbis) stb_vorbis_close(m.vorbis);
m.stream = nullptr; m.stream = nullptr;
m.vorbis = nullptr;
m.state = state::invalid; m.state = state::invalid;
} }
@@ -366,18 +378,13 @@ namespace jail
void setPosition(float value) void setPosition(float value)
{ {
if (!music::enabled) return; auto& m = musics[current];
if (current<0 || current>static_cast<int>(musics.size())) {
log_msg(LOG_FAIL, "music::setPosition: Illegal music handle: %i\n", current);
return;
}
auto &m = musics[current];
if (m.state == state::invalid) {
log_msg(LOG_FAIL, "music::setPosition: Invalidated music handle: %i\n", current);
return;
}
m.pos = value * m.spec.freq; int sample = int(value * m.info.sample_rate);
if (stb_vorbis_seek(m.vorbis, sample)) {
SDL_ClearAudioStream(m.stream); // importante
}
} }
float getPosition() float getPosition()
@@ -392,8 +399,8 @@ namespace jail
log_msg(LOG_FAIL, "music::getPosition: Invalidated music handle: %i\n", current); log_msg(LOG_FAIL, "music::getPosition: Invalidated music handle: %i\n", current);
return 0; return 0;
} }
int sample = stb_vorbis_get_sample_offset(m.vorbis);
return float(m.pos)/float(m.spec.freq); return float(sample) / float(m.info.sample_rate);
} }
void enable(bool value) void enable(bool value)
+1 -1
View File
@@ -1,3 +1,3 @@
#pragma once #pragma once
#define MINI_VERSION "1.5.7" #define MINI_VERSION "1.5.8"