diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-04 07:06:45 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-04 07:06:45 -0400 |
| commit | 34863f5b702c0dbb00d8db5c00efd43d895fcd4c (patch) | |
| tree | 09e0249e16e937c22ec0c04cfa1bc4b0e4de337e /src/audio.cpp | |
| parent | 1c87a0e431d30aaf19195f8a45c7607add21018a (diff) | |
pke: audio: first-pass actually play an asset
Diffstat (limited to 'src/audio.cpp')
| -rw-r--r-- | src/audio.cpp | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/src/audio.cpp b/src/audio.cpp index c3f152e..194c01c 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -1,13 +1,19 @@ #define PKE_AUDIO_IMPL_PIPEWIRE -#include "audio.hpp" - +#include "asset-manager.hpp" #include "audio-impl-pw.hpp" +#include "audio.hpp" +#include "pk.h" struct pke_audio_master pke_audio_mstr{}; void pke_audio_init() { + pke_audio_mstr.master_volume = 1.f; pke_audio_mstr.channel_count = 2; + pke_audio_mstr.bkt_transient = pk_mem_bucket_create("pke_audio", PK_MEM_DEFAULT_BUCKET_SIZE, PK_MEMBUCKET_FLAG_TRANSIENT); + for (uint8_t i = 0; i < pke_audio_mstr.channel_count; ++i) { + pke_audio_mstr.source_volumes[i] = 1.f; + } #ifdef PKE_AUDIO_IMPL_PIPEWIRE pke_audio_pw_init(); #endif @@ -16,12 +22,13 @@ void pke_audio_teardown() { #ifdef PKE_AUDIO_IMPL_PIPEWIRE pke_audio_pw_teardown(); #endif + pk_mem_bucket_destroy(pke_audio_mstr.bkt_transient); } void pke_audio_tick(double delta) { (void)delta; #ifdef PKE_AUDIO_IMPL_PIPEWIRE if (pke_audio_pw.is_needing_output_remapped == true) { - pke_audio_pw.is_needing_output_remapped = !pke_audio_pw_remap_outputs(); + pke_audio_pw_remap_outputs(); } #endif } @@ -34,5 +41,44 @@ void pke_audio_set_volume(pke_audio_source source, float volume) { pke_audio_mstr.source_volumes[static_cast<pke_audio_source_T>(source)] = volume; } -void pke_audio_play(AssetHandle handle, pke_audio_source audio_source, pke_audio_flags flags); -void pke_audio_stop_all(); +bool pke_audio_playing_objects_find_first_by_key(void *user_data, void *arr_data) { + std::tuple<AssetHandle, pke_audio_source> &tup = *reinterpret_cast<std::tuple<AssetHandle, pke_audio_source>*>(user_data); + pke_audio_obj &audio_obj = *reinterpret_cast<pke_audio_obj*>(arr_data); + return std::get<0>(tup) == audio_obj.handle && std::get<1>(tup) == audio_obj.source; +} +void pke_audio_play(AssetHandle handle, pke_audio_source audio_source, glm::vec3 position_source, pke_audio_flags flags) { + // TODO validation: audio length (does it fit in uint32_t), etc + // TODO rethink threading: first-pass only mutex + std::tuple<AssetHandle, pke_audio_source> tup {handle, audio_source}; + pke_audio_mstr.mtx_buffer.lock(); + uint32_t idx = pk_arr_find_first_index(&pke_audio_mstr.playing_objects, &tup, pke_audio_playing_objects_find_first_by_key); + pke_audio_obj *aobj = NULL; + if (idx == uint32_t(-1)) { + AM_Get(handle); // keep the asset in memory, freed when play_count hits 0 + pk_arr_append_t(&pke_audio_mstr.playing_objects, {}); + aobj = &pke_audio_mstr.playing_objects[pke_audio_mstr.playing_objects.next-1]; + memset(aobj, 0, sizeof(pke_audio_obj)); + aobj->handle = handle; + aobj->source = audio_source; + aobj->play_count = 1; + idx = 0; + } else { + aobj = &pke_audio_mstr.playing_objects[idx]; + idx = aobj->play_count; + aobj->play_count += 1; + } + aobj->position_source[idx] = position_source; + aobj->flags[idx] = flags; + aobj->play_heads[idx] = 0; + pke_audio_mstr.mtx_buffer.unlock(); +} +void pke_audio_stop_all() { + // TODO fade-out instead of hard-cut? Maybe that should be a separate function. + uint32_t i; + pke_audio_mstr.mtx_buffer.lock(); + for (i = 0; i < pke_audio_mstr.playing_objects.next; ++i) { + AM_Release(pke_audio_mstr.playing_objects[i].handle); + } + pk_arr_clear(&pke_audio_mstr.playing_objects); + pke_audio_mstr.mtx_buffer.unlock(); +} |
