diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-11 11:41:21 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-11 11:41:21 -0400 |
| commit | f88ca0bc946bae086e02eacdc6c129f00e2e07e3 (patch) | |
| tree | eb8975ec505315e7f53a15ded32fb0cfd6b57731 /src/audio-impl-pw.cpp | |
| parent | 1fd2b900a5f97379e80adc411d3763f9ba811570 (diff) | |
pke: audio: fx boilerplate, low-pass spatial
Diffstat (limited to 'src/audio-impl-pw.cpp')
| -rw-r--r-- | src/audio-impl-pw.cpp | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/src/audio-impl-pw.cpp b/src/audio-impl-pw.cpp index 4f5f4cf..92acd8d 100644 --- a/src/audio-impl-pw.cpp +++ b/src/audio-impl-pw.cpp @@ -1,8 +1,10 @@ #include "audio-impl-pw.hpp" +#include "audio-impl-shared.hpp" #include "asset-manager.hpp" #include "audio-types.hpp" #include "game-settings.hpp" +#include "math-helpers.hpp" #include "pipewire/keys.h" #include "pipewire/thread-loop.h" #include "pk.h" @@ -276,13 +278,16 @@ void on_pipewire_process(void *user_data) { int stride; uint8_t pc, pc2; uint32_t i, ii, c; - uint64_t n_frames, i_frame; + int64_t n_frames, i_frame; float *dst; float val, vol, vol2; float *spatial_volumes = nullptr; glm::vec3 listener_origin; glm::vec3 audio_dir = glm::vec3(0); glm::vec3 *spatial_normals = nullptr; + pke_audio_fx_params_reverb *params_reverb; + pke_audio_fx_params_delay *params_delay; + pke_audio_fx_params_low_pass_filter *params_low_pass_filter; pk_mem_bucket_reset(pke_audio_mstr.bkt_transient); if ((b = pw_stream_dequeue_buffer(pke_audio_pw.stream)) == NULL) { @@ -296,14 +301,11 @@ void on_pipewire_process(void *user_data) { return; } - stride = sizeof(float) * pke_audio_mstr.channel_count; - n_frames = buf->datas[0].maxsize / stride; - if (b->requested) { - n_frames = PK_MIN(b->requested, n_frames); - } - - spatial_volumes = pk_new<float>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); - spatial_normals = pk_new<glm::vec3>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); + spatial_volumes = pk_new<float>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); + spatial_normals = pk_new<glm::vec3>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); + params_reverb = pk_new<pke_audio_fx_params_reverb>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); + params_delay = pk_new<pke_audio_fx_params_delay>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); + params_low_pass_filter = pk_new<pke_audio_fx_params_low_pass_filter>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt_transient); // calculate spatial_normals // TODO maybe don't use UBO @@ -314,11 +316,19 @@ void on_pipewire_process(void *user_data) { switch (c) { case 0: // left-speaker - spatial_normals[c] = glm::normalize(glm::vec3(-1.f, 0.f, 1.f)); + if (pke_audio_mstr.channel_count > 2) { + spatial_normals[c] = glm::normalize(glm::vec3(-1.f, 0.f, 1.f)); + } else { + spatial_normals[c] = glm::normalize(glm::vec3(-1.f, 0.f, 0.f)); + } break; case 1: // right - spatial_normals[c] = glm::normalize(glm::vec3( 1.f, 0.f, 1.f)); + if (pke_audio_mstr.channel_count > 2) { + spatial_normals[c] = glm::normalize(glm::vec3( 1.f, 0.f, 1.f)); + } else { + spatial_normals[c] = glm::normalize(glm::vec3( 1.f, 0.f, 0.f)); + } break; case 2: // center @@ -350,10 +360,23 @@ void on_pipewire_process(void *user_data) { } pke_audio_mstr.mtx_buffer.lock(); + + stride = sizeof(float) * pke_audio_mstr.channel_count; + + n_frames = buf->datas[0].maxsize / stride; + if (b->requested) { + n_frames = PK_MIN((int64_t)b->requested, n_frames); + } + // fprintf(stdout, "[pw] frame count: %li, requested: %lu\n", n_frames, b->requested); + buf->datas[0].chunk->offset = 0; buf->datas[0].chunk->stride = stride; buf->datas[0].chunk->size = n_frames * stride; + if (buf->datas[0].chunk->size == 0) { + goto audio_done; + } + for (i = 0; i < pke_audio_mstr.playing_objects.next; ++i) { pke_audio_obj *aobj = &pke_audio_mstr.playing_objects[i]; const Asset *a = AM_Get(aobj->handle); @@ -381,11 +404,19 @@ void on_pipewire_process(void *user_data) { break; } } - if (audio_dir != glm::vec3(0)) { - float dot_dir = glm::dot(spatial_normals[c], audio_dir); + float dot_dir = glm::dot(spatial_normals[c], audio_dir); + if (!glm::isnan(dot_dir) && dot_dir < 0.0) { // fprintf(stderr, "[pw] dot: %f\n", dot_dir); - spatial_volumes[c] = glm::clamp(dot_dir, 0.f, 1.f); + + // 20k max, 500 min + params_low_pass_filter[c].cutoff_freq = log_interp(500.f, 20000.f, abs(dot_dir)); + } else { + params_low_pass_filter[c].cutoff_freq = 0.f; } + params_reverb[c].reverb_strength = 0.f; // TODO + params_delay[c].delay_frames = 0; // TODO + // spatial_volumes[c] = glm::clamp(dot_dir, 0.f, 1.f); + spatial_volumes[c] = lerp(0.f, 1.f, dot_dir + 0.85f); if (isnan(spatial_volumes[c]) || spatial_volumes[c] == 0.0f) { /* @@ -430,14 +461,11 @@ void on_pipewire_process(void *user_data) { vol2 *= (spatial_volumes[c] * distance_volume); } if (vol2 <= 0.0) { - // fprintf(stderr, "[pw] vol2 is <= 0.0\n"); + // fprintf(stderr, "[pw] chan: %i vol2 is <= 0.0\n", c); dst += 1; continue; } - val = ((float*)a->ptr)[aobj->play_heads[pc]]; - - // vol2 = PK_CLAMP(vol2, 0.0, 0.5); /* if (isnan(vol2)) { fprintf(stderr, "[pw] vol2 is NaN\n"); @@ -446,6 +474,11 @@ void on_pipewire_process(void *user_data) { fprintf(stderr, "[pw] vol2 is 0, %f, %f, %f\n", pke_audio_mstr.master_volume, pke_audio_mstr.source_volumes[c], spatial_volumes[c]); } */ + + // val = ((float*)a->ptr)[aobj->play_heads[pc]]; // val is read inside fx_low_pass_filter + val = pke_audio_fx_low_pass_filter((float*)a->ptr, a->size / sizeof(float), (uint32_t)aobj->play_heads[pc], ¶ms_low_pass_filter[pc]); + val += pke_audio_fx_reverb((float*)a->ptr, a->size / sizeof(float), (uint32_t)aobj->play_heads[pc], ¶ms_reverb[pc]); + val += pke_audio_fx_delay((float*)a->ptr, a->size / sizeof(float), (uint32_t)aobj->play_heads[pc], ¶ms_delay[pc]); *dst += val * vol2; /* if (isnan(*dst)) { @@ -481,6 +514,7 @@ void on_pipewire_process(void *user_data) { memset(dst, 0, sizeof(float) * n_frames * pke_audio_mstr.channel_count); } +audio_done: pw_stream_queue_buffer(pke_audio_pw.stream, b); pke_audio_mstr.mtx_buffer.unlock(); return; |
