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
{
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
Uint32 length { 0 };
Uint8 *buffer { nullptr };
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
SDL_AudioStream* stream { nullptr };
int pos { 0 };
int times { 0 };
SDL_AudioStream *stream { nullptr };
music::state state { music::state::invalid };
const uint8_t* ogg_data { nullptr };
uint32_t ogg_length { 0 };
stb_vorbis* vorbis { nullptr };
stb_vorbis_info info {};
int times { 0 };
music::state state { music::state::invalid };
};
static int current { -1 };
@@ -87,10 +90,12 @@ namespace jail
static void updateMusic()
{
if (!music::enabled) return;
if (music::current < 0 || music::current > static_cast<int>(music::musics.size())) return;
auto &m = music::musics[music::current];
if (music::current < 0) return;
auto& m = music::musics[music::current];
if (m.state != music::state::playing) return;
// Fade-out
if (music::fade::fading) {
int time = SDL_GetTicks();
if (time > (music::fade::start_time + music::fade::duration)) {
@@ -98,23 +103,37 @@ namespace jail
music::stop();
return;
} else {
const int time_passed = time - music::fade::start_time;
const float percent = (float)time_passed / (float)music::fade::duration;
SDL_SetAudioStreamGain(m.stream, 1.0 - percent);
float percent = float(time - music::fade::start_time) / float(music::fade::duration);
SDL_SetAudioStreamGain(m.stream, 1.0f - percent);
}
}
if (m.times != 0)
{
if (SDL_GetAudioStreamAvailable(m.stream) < static_cast<int>(m.length/2)) {
SDL_PutAudioStreamData(m.stream, m.buffer, m.length);
// ¿Hay suficiente audio en el stream?
if (SDL_GetAudioStreamAvailable(m.stream) > 48000) return; // 1 segundo
// 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()
@@ -194,26 +213,31 @@ namespace jail
{
int load(const uint8_t* buffer, uint32_t length)
{
int music = 0;
while (music < static_cast<int>(musics.size()) && musics[music].state != state::invalid) { music++; }
if (music == static_cast<int>(musics.size())) musics.emplace_back();
int idx = 0;
while (idx < (int)musics.size() && musics[idx].state != state::invalid) idx++;
if (idx == (int)musics.size()) musics.emplace_back();
auto &m = musics[music];
auto& m = musics[idx];
int chan, samplerate;
short *output;
m.length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
m.ogg_data = buffer;
m.ogg_length = length;
m.spec.channels = chan;
m.spec.freq = samplerate;
int error;
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.buffer = (uint8_t*)SDL_malloc(m.length);
SDL_memcpy(m.buffer, output, m.length);
free(output);
m.pos = 0;
m.state = state::stopped;
return music;
return idx;
}
int load(const char* filename)
@@ -236,23 +260,19 @@ namespace jail
void play(int mus, int loop)
{
if (!music::enabled) return;
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;
auto &m = musics[current];
m.pos = 0;
m.state = state::playing;
auto& m = musics[mus];
m.times = loop;
m.state = state::playing;
stb_vorbis_seek_start(m.vorbis);
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);
if (!SDL_BindAudioStream(sdlAudioDevice, m.stream)) log_msg(LOG_FAIL, "SDL_BindAudioStream failed!\n");
//SDL_ResumeAudioStreamDevice(current->stream);
SDL_BindAudioStream(sdlAudioDevice, m.stream);
}
void pause()
@@ -293,21 +313,13 @@ namespace jail
void stop()
{
if (!music::enabled || (current<0)) return;
if (current>static_cast<int>(musics.size())) {
log_msg(LOG_FAIL, "music::stop: Illegal music handle: %i\n", current);
return;
}
auto &m = musics[current];
if (m.state == state::invalid) {
log_msg(LOG_FAIL, "music::stop: Invalidated music handle: %i\n", current);
return;
}
if (current < 0) return;
auto& m = musics[current];
m.pos = 0;
m.state = state::stopped;
//SDL_PauseAudioStreamDevice(current->stream);
SDL_DestroyAudioStream(m.stream);
if (m.stream) SDL_DestroyAudioStream(m.stream);
m.stream = nullptr;
}
@@ -339,16 +351,16 @@ namespace jail
void destroy(int mus)
{
if (current == mus) current = -1;
if (mus<0 || mus>static_cast<int>(musics.size())) {
log_msg(LOG_FAIL, "music::destroy: Illegal music handle: %i\n", mus);
return;
}
auto &m = musics[mus];
SDL_free(m.buffer);
m.buffer = nullptr;
if (mus < 0 || mus >= (int)musics.size()) return;
auto& m = musics[mus];
if (m.stream) SDL_DestroyAudioStream(m.stream);
if (m.vorbis) stb_vorbis_close(m.vorbis);
m.stream = nullptr;
m.vorbis = nullptr;
m.state = state::invalid;
}
@@ -366,18 +378,13 @@ namespace jail
void setPosition(float value)
{
if (!music::enabled) return;
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;
}
auto& m = musics[current];
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()
@@ -392,8 +399,8 @@ namespace jail
log_msg(LOG_FAIL, "music::getPosition: Invalidated music handle: %i\n", current);
return 0;
}
return float(m.pos)/float(m.spec.freq);
int sample = stb_vorbis_get_sample_offset(m.vorbis);
return float(sample) / float(m.info.sample_rate);
}
void enable(bool value)
+1 -1
View File
@@ -1,3 +1,3 @@
#pragma once
#define MINI_VERSION "1.5.7"
#define MINI_VERSION "1.5.8"