VERSIÓ 1.5.8:
- [NEW] Implementat streaming de OGGs
This commit is contained in:
@@ -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,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define MINI_VERSION "1.5.7"
|
||||
#define MINI_VERSION "1.5.8"
|
||||
|
||||
Reference in New Issue
Block a user