tested audio stuff on tinylink

This commit is contained in:
RandyGaul 2022-11-19 14:09:08 -08:00
parent 4cc0f8b608
commit b57011905b
5 changed files with 89 additions and 58 deletions

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "blah_app.h" #include "blah_app.h"
#include "blah_aseprite.h" #include "blah_aseprite.h"
#include "blah_audio.h"
#include "blah_batch.h" #include "blah_batch.h"
#include "blah_calc.h" #include "blah_calc.h"
#include "blah_color.h" #include "blah_color.h"

View File

@ -21,7 +21,7 @@ Platform* App::Internal::platform = nullptr;
Renderer* App::Internal::renderer = nullptr; Renderer* App::Internal::renderer = nullptr;
// Internal Audio bool // Internal Audio bool
bool Audio::Internal::is_init = false; bool Internal::audio_is_init = false;
namespace namespace
{ {
@ -117,12 +117,12 @@ bool App::run(const Config* c)
// initialize audio // initialize audio
{ {
if (!Audio::Internal::is_init) { if (!Blah::Internal::audio_is_init) {
int more_on_emscripten = 1; int more_on_emscripten = 1;
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
more_on_emscripten = 4; more_on_emscripten = 4;
#endif #endif
Audio::Internal::is_init = Audio::Internal::init(NULL, c->audio_frequency_in_Hz, 1024 * more_on_emscripten); Blah::Internal::audio_is_init = Blah::Internal::audio_init(NULL, c->audio_frequency_in_Hz, 1024 * more_on_emscripten);
} }
} }
@ -280,6 +280,9 @@ void App::Internal::iterate()
renderer->after_render(); renderer->after_render();
platform->present(); platform->present();
} }
// Update audio
Blah::Internal::audio_update();
} }
void App::Internal::shutdown() void App::Internal::shutdown()
@ -300,8 +303,8 @@ void App::Internal::shutdown()
delete platform; delete platform;
platform = nullptr; platform = nullptr;
Audio::Internal::shutdown(); Blah::Internal::audio_shutdown();
Audio::Internal::is_init = false; Blah::Internal::audio_is_init = false;
// clear static App state // clear static App state
app_config = Config(); app_config = Config();

View File

@ -1,4 +1,5 @@
#include "blah_audio.h" #include "blah_audio.h"
#include "blah_time.h"
#define STB_VORBIS_HEADER_ONLY #define STB_VORBIS_HEADER_ONLY
#include "third_party/stb_vorbis.c" #include "third_party/stb_vorbis.c"
@ -11,7 +12,7 @@ namespace Blah
{ {
namespace Internal namespace Internal
{ {
bool init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_samples) bool audio_init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_samples)
{ {
cs_error_t err = cs_init(os_handle, play_frequency_in_Hz, buffered_samples, NULL); cs_error_t err = cs_init(os_handle, play_frequency_in_Hz, buffered_samples, NULL);
if (err != CUTE_SOUND_ERROR_NONE) { if (err != CUTE_SOUND_ERROR_NONE) {
@ -20,12 +21,18 @@ namespace Blah
} else { } else {
return true; return true;
} }
cs_spawn_mix_thread();
} }
void shutdown() void audio_shutdown()
{ {
cs_shutdown(); cs_shutdown();
} }
void audio_update()
{
cs_update(Time::delta);
}
} }
Audio::Audio(void* audio) Audio::Audio(void* audio)
@ -74,7 +81,7 @@ namespace Blah
// load wav file from memory using cute_sound.h // load wav file from memory using cute_sound.h
cs_error_t err; cs_error_t err;
void* audio = cs_read_mem_wav((void*)buffer.data(), (size_t)buffer.size(), &err); void* audio = cs_read_mem_wav((void*)buffer.data(), stream.length(), &err);
if (!audio) { if (!audio) {
Log::error(cs_error_as_string(err)); Log::error(cs_error_as_string(err));
return AudioRef(); return AudioRef();
@ -98,7 +105,7 @@ namespace Blah
// load ogg file from memory using cute_sound.h // load ogg file from memory using cute_sound.h
cs_error_t err; cs_error_t err;
void* audio = cs_read_mem_ogg((void*)buffer.data(), (size_t)buffer.size(), &err); void* audio = cs_read_mem_ogg((void*)buffer.data(), stream.length(), &err);
if (!audio) { if (!audio) {
Log::error(cs_error_as_string(err)); Log::error(cs_error_as_string(err));
return AudioRef(); return AudioRef();

View File

@ -37,17 +37,15 @@ namespace Blah
} }
} }
namespace Audio
{
namespace Internal namespace Internal
{ {
extern bool is_init; extern bool audio_is_init;
// Pass in NULL for `os_handle`, except for the DirectSound backend this should be hwnd. // Pass in NULL for `os_handle`, except for the DirectSound backend this should be hwnd.
// play_frequency_in_Hz depends on your audio file, 44100 seems to be fine. // play_frequency_in_Hz depends on your audio file, 44100 seems to be fine.
// buffered_samples is clamped to be at least 1024. // buffered_samples is clamped to be at least 1024.
bool init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_samples); bool audio_init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_samples);
void shutdown(); void audio_shutdown();
} void audio_update();
} }
} }

View File

@ -1339,7 +1339,6 @@ typedef struct cs_context_t
cs_inst_page_t* pages /* = NULL */; cs_inst_page_t* pages /* = NULL */;
cs_list_t playing_sounds; cs_list_t playing_sounds;
cs_list_t free_sounds; cs_list_t free_sounds;
void* mem_ctx /* = NULL */;
unsigned latency_samples; unsigned latency_samples;
int Hz; int Hz;
@ -1393,6 +1392,7 @@ typedef struct cs_context_t
#endif #endif
} cs_context_t; } cs_context_t;
void* s_mem_ctx;
cs_context_t* s_ctx = NULL; cs_context_t* s_ctx = NULL;
void cs_sleep(int milliseconds) void cs_sleep(int milliseconds)
@ -1708,21 +1708,21 @@ cs_error_t cs_init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_
s_ctx->music_next = NULL; s_ctx->music_next = NULL;
s_ctx->audio_sources_to_free_capacity = 32; s_ctx->audio_sources_to_free_capacity = 32;
s_ctx->audio_sources_to_free_size = 0; s_ctx->audio_sources_to_free_size = 0;
s_ctx->audio_sources_to_free = (cs_audio_source_t**)CUTE_SOUND_ALLOC(sizeof(cs_audio_source_t*) * s_ctx->audio_sources_to_free_capacity, s_ctx->mem_ctx); s_ctx->audio_sources_to_free = (cs_audio_source_t**)CUTE_SOUND_ALLOC(sizeof(cs_audio_source_t*) * s_ctx->audio_sources_to_free_capacity, s_mem_ctx);
s_ctx->instance_id_gen = 1; s_ctx->instance_id_gen = 1;
hashtable_init(&s_ctx->instance_map, sizeof(cs_audio_source_t*), 1024, user_allocator_context); hashtable_init(&s_ctx->instance_map, sizeof(cs_audio_source_t*), 1024, user_allocator_context);
s_ctx->pages = NULL; s_ctx->pages = NULL;
cs_list_init(&s_ctx->playing_sounds); cs_list_init(&s_ctx->playing_sounds);
cs_list_init(&s_ctx->free_sounds); cs_list_init(&s_ctx->free_sounds);
s_add_page(); s_add_page();
s_ctx->mem_ctx = user_allocator_context; s_mem_ctx = user_allocator_context;
s_ctx->latency_samples = buffered_samples; s_ctx->latency_samples = buffered_samples;
s_ctx->Hz = play_frequency_in_Hz; s_ctx->Hz = play_frequency_in_Hz;
s_ctx->bps = bps; s_ctx->bps = bps;
s_ctx->wide_count = wide_count; s_ctx->wide_count = wide_count;
s_ctx->floatA = (cs__m128*)cs_malloc16(sizeof(cs__m128) * wide_count, s_ctx->mem_ctx); s_ctx->floatA = (cs__m128*)cs_malloc16(sizeof(cs__m128) * wide_count, s_mem_ctx);
s_ctx->floatB = (cs__m128*)cs_malloc16(sizeof(cs__m128) * wide_count, s_ctx->mem_ctx); s_ctx->floatB = (cs__m128*)cs_malloc16(sizeof(cs__m128) * wide_count, s_mem_ctx);
s_ctx->samples = (cs__m128i*)cs_malloc16(sizeof(cs__m128i) * wide_count, s_ctx->mem_ctx); s_ctx->samples = (cs__m128i*)cs_malloc16(sizeof(cs__m128i) * wide_count, s_mem_ctx);
s_ctx->running = true; s_ctx->running = true;
s_ctx->separate_thread = false; s_ctx->separate_thread = false;
s_ctx->sleep_milliseconds = 0; s_ctx->sleep_milliseconds = 0;
@ -1802,25 +1802,37 @@ void cs_shutdown()
#endif #endif
if (!cs_list_empty(&s_ctx->playing_sounds)) {
cs_list_node_t* playing_node = cs_list_begin(&s_ctx->playing_sounds);
cs_list_node_t* end_node = cs_list_end(&s_ctx->playing_sounds);
do {
cs_list_node_t* next_node = playing_node->next;
cs_sound_inst_t* playing = CUTE_SOUND_LIST_HOST(cs_sound_inst_t, node, playing_node);
cs_audio_source_t* audio = playing->audio;
if (audio) audio->playing_count = 0;
playing_node = next_node;
} while (playing_node != end_node);
}
cs_inst_page_t* page = s_ctx->pages; cs_inst_page_t* page = s_ctx->pages;
while (page) { while (page) {
cs_inst_page_t* next = page->next; cs_inst_page_t* next = page->next;
CUTE_SOUND_FREE(page, s_ctx->mem_ctx); CUTE_SOUND_FREE(page, s_mem_ctx);
page = next; page = next;
} }
for (int i = 0; i < s_ctx->audio_sources_to_free_size; ++i) { for (int i = 0; i < s_ctx->audio_sources_to_free_size; ++i) {
cs_audio_source_t* audio = s_ctx->audio_sources_to_free[i]; cs_audio_source_t* audio = s_ctx->audio_sources_to_free[i];
cs_free16(audio->channels[0], s_ctx->mem_ctx); cs_free16(audio->channels[0], s_mem_ctx);
CUTE_SOUND_FREE(audio, s_ctx->mem_ctx); CUTE_SOUND_FREE(audio, s_mem_ctx);
} }
CUTE_SOUND_FREE(s_ctx->audio_sources_to_free, s_ctx->mem_ctx); CUTE_SOUND_FREE(s_ctx->audio_sources_to_free, s_mem_ctx);
cs_free16(s_ctx->floatA, s_ctx->mem_ctx); cs_free16(s_ctx->floatA, s_mem_ctx);
cs_free16(s_ctx->floatB, s_ctx->mem_ctx); cs_free16(s_ctx->floatB, s_mem_ctx);
cs_free16(s_ctx->samples, s_ctx->mem_ctx); cs_free16(s_ctx->samples, s_mem_ctx);
hashtable_term(&s_ctx->instance_map); hashtable_term(&s_ctx->instance_map);
void* mem_ctx = s_ctx->mem_ctx; void* mem_ctx = s_mem_ctx;
(void)mem_ctx; (void)mem_ctx;
CUTE_SOUND_FREE(s_ctx, mem_ctx); CUTE_SOUND_FREE(s_ctx, mem_ctx);
s_ctx = NULL; s_ctx = NULL;
@ -2227,7 +2239,11 @@ void cs_mix()
playing->active = false; playing->active = false;
if (playing->audio) { if (playing->audio) {
if (s_ctx->running) {
playing->audio->playing_count -= 1; playing->audio->playing_count -= 1;
} else {
playing->audio->playing_count = 0;
}
CUTE_SOUND_ASSERT(playing->audio->playing_count >= 0); CUTE_SOUND_ASSERT(playing->audio->playing_count >= 0);
} }
@ -2276,8 +2292,8 @@ void cs_mix()
for (int i = 0; i < s_ctx->audio_sources_to_free_size;) { for (int i = 0; i < s_ctx->audio_sources_to_free_size;) {
cs_audio_source_t* audio = s_ctx->audio_sources_to_free[i]; cs_audio_source_t* audio = s_ctx->audio_sources_to_free[i];
if (audio->playing_count == 0) { if (audio->playing_count == 0) {
cs_free16(audio->channels[0], s_ctx->mem_ctx); cs_free16(audio->channels[0], s_mem_ctx);
CUTE_SOUND_FREE(audio, s_ctx->mem_ctx); CUTE_SOUND_FREE(audio, s_mem_ctx);
s_ctx->audio_sources_to_free[i] = s_ctx->audio_sources_to_free[--s_ctx->audio_sources_to_free_size]; s_ctx->audio_sources_to_free[i] = s_ctx->audio_sources_to_free[--s_ctx->audio_sources_to_free_size];
} else { } else {
++i; ++i;
@ -2376,10 +2392,10 @@ static void cs_last_element(cs__m128* a, int i, int j, int16_t* samples, int off
cs_audio_source_t* cs_load_wav(const char* path, cs_error_t* err /* = NULL */) cs_audio_source_t* cs_load_wav(const char* path, cs_error_t* err /* = NULL */)
{ {
int size; int size;
void* wav = cs_read_file_to_memory(path, &size, s_ctx->mem_ctx); void* wav = cs_read_file_to_memory(path, &size, s_mem_ctx);
if (!wav) return NULL; if (!wav) return NULL;
cs_audio_source_t* audio = cs_read_mem_wav(wav, size, err); cs_audio_source_t* audio = cs_read_mem_wav(wav, size, err);
CUTE_SOUND_FREE(wav, s_ctx->mem_ctx); CUTE_SOUND_FREE(wav, s_mem_ctx);
return audio; return audio;
} }
@ -2431,7 +2447,7 @@ cs_audio_source_t* cs_read_mem_wav(const void* memory, size_t size, cs_error_t*
data = cs_next(data); data = cs_next(data);
} }
audio = (cs_audio_source_t*)CUTE_SOUND_ALLOC(sizeof(cs_audio_source_t), s_ctx->mem_ctx); audio = (cs_audio_source_t*)CUTE_SOUND_ALLOC(sizeof(cs_audio_source_t), s_mem_ctx);
CUTE_SOUND_MEMSET(audio, 0, sizeof(*audio)); CUTE_SOUND_MEMSET(audio, 0, sizeof(*audio));
audio->sample_rate = (int)fmt.nSamplesPerSec; audio->sample_rate = (int)fmt.nSamplesPerSec;
@ -2505,22 +2521,28 @@ cs_audio_source_t* cs_read_mem_wav(const void* memory, size_t size, cs_error_t*
void cs_free_audio_source(cs_audio_source_t* audio) void cs_free_audio_source(cs_audio_source_t* audio)
{ {
if (s_ctx) {
cs_lock(); cs_lock();
if (audio->playing_count == 0) { if (audio->playing_count == 0) {
cs_free16(audio->channels[0], s_ctx->mem_ctx); cs_free16(audio->channels[0], s_mem_ctx);
CUTE_SOUND_FREE(audio, s_ctx->mem_ctx); CUTE_SOUND_FREE(audio, s_mem_ctx);
} else { } else {
if (s_ctx->audio_sources_to_free_size == s_ctx->audio_sources_to_free_capacity) { if (s_ctx->audio_sources_to_free_size == s_ctx->audio_sources_to_free_capacity) {
int new_capacity = s_ctx->audio_sources_to_free_capacity * 2; int new_capacity = s_ctx->audio_sources_to_free_capacity * 2;
cs_audio_source_t** new_sources = (cs_audio_source_t**)CUTE_SOUND_ALLOC(new_capacity, s_ctx->mem_ctx); cs_audio_source_t** new_sources = (cs_audio_source_t**)CUTE_SOUND_ALLOC(new_capacity, s_mem_ctx);
CUTE_SOUND_MEMCPY(new_sources, s_ctx->audio_sources_to_free, sizeof(cs_audio_source_t*) * s_ctx->audio_sources_to_free_size); CUTE_SOUND_MEMCPY(new_sources, s_ctx->audio_sources_to_free, sizeof(cs_audio_source_t*) * s_ctx->audio_sources_to_free_size);
CUTE_SOUND_FREE(s_ctx->audio_sources_to_free, s_ctx->mem_ctx); CUTE_SOUND_FREE(s_ctx->audio_sources_to_free, s_mem_ctx);
s_ctx->audio_sources_to_free = new_sources; s_ctx->audio_sources_to_free = new_sources;
s_ctx->audio_sources_to_free_capacity = new_capacity; s_ctx->audio_sources_to_free_capacity = new_capacity;
} }
s_ctx->audio_sources_to_free[s_ctx->audio_sources_to_free_size++] = audio; s_ctx->audio_sources_to_free[s_ctx->audio_sources_to_free_size++] = audio;
} }
cs_unlock(); cs_unlock();
} else {
CUTE_SOUND_ASSERT(audio->playing_count == 0);
cs_free16(audio->channels[0], NULL);
CUTE_SOUND_FREE(audio, s_mem_ctx);
}
} }
#if CUTE_SOUND_PLATFORM == CUTE_SOUND_SDL && defined(SDL_rwops_h_) && defined(CUTE_SOUND_SDL_RWOPS) #if CUTE_SOUND_PLATFORM == CUTE_SOUND_SDL && defined(SDL_rwops_h_) && defined(CUTE_SOUND_SDL_RWOPS)
@ -2556,10 +2578,10 @@ void cs_free_audio_source(cs_audio_source_t* audio)
cs_audio_source_t* cs_load_wav_rw(SDL_RWops* context, cs_error_t* err) cs_audio_source_t* cs_load_wav_rw(SDL_RWops* context, cs_error_t* err)
{ {
int size; int size;
char* wav = (char*)cs_read_rw_to_memory(context, &size, s_ctx->mem_ctx); char* wav = (char*)cs_read_rw_to_memory(context, &size, s_mem_ctx);
if (!memory) return NULL; if (!memory) return NULL;
cs_audio_source_t* audio = cs_read_mem_wav(wav, length, err); cs_audio_source_t* audio = cs_read_mem_wav(wav, length, err);
CUTE_SOUND_FREE(wav, s_ctx->mem_ctx); CUTE_SOUND_FREE(wav, s_mem_ctx);
return audio; return audio;
} }
@ -2577,7 +2599,7 @@ cs_audio_source_t* cs_read_mem_ogg(const void* memory, size_t length, cs_error_t
int sample_rate; int sample_rate;
int sample_count = stb_vorbis_decode_memory((const unsigned char*)memory, (int)length, &channel_count, &sample_rate, &samples); int sample_count = stb_vorbis_decode_memory((const unsigned char*)memory, (int)length, &channel_count, &sample_rate, &samples);
if (sample_count <= 0) { if (err) *err = CUTE_SOUND_ERROR_STB_VORBIS_DECODE_FAILED; return NULL; } if (sample_count <= 0) { if (err) *err = CUTE_SOUND_ERROR_STB_VORBIS_DECODE_FAILED; return NULL; }
audio = (cs_audio_source_t*)CUTE_SOUND_ALLOC(sizeof(cs_audio_source_t), s_ctx->mem_ctx); audio = (cs_audio_source_t*)CUTE_SOUND_ALLOC(sizeof(cs_audio_source_t), s_mem_ctx);
CUTE_SOUND_MEMSET(audio, 0, sizeof(*audio)); CUTE_SOUND_MEMSET(audio, 0, sizeof(*audio));
{ {
@ -2663,10 +2685,10 @@ cs_audio_source_t* cs_load_ogg(const char* path, cs_error_t* err)
cs_audio_source_t* cs_load_ogg_rw(SDL_RWops* rw, cs_error_t* err) cs_audio_source_t* cs_load_ogg_rw(SDL_RWops* rw, cs_error_t* err)
{ {
int length; int length;
void* memory = cs_read_rw_to_memory(rw, &length, s_ctx->mem_ctx); void* memory = cs_read_rw_to_memory(rw, &length, s_mem_ctx);
if (!memory) return NULL; if (!memory) return NULL;
cs_audio_source_t* audio = cs_read_ogg_wav(memory, length, err); cs_audio_source_t* audio = cs_read_ogg_wav(memory, length, err);
CUTE_SOUND_FREE(memory, s_ctx->mem_ctx); CUTE_SOUND_FREE(memory, s_mem_ctx);
return audio; return audio;
} }