summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-07-15 14:12:52 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-07-15 14:59:13 -0400
commit2e84deb2b1837b62677cbf88e1f8e1c54e339c21 (patch)
tree81587a42fa402ba13d83add0e9b8c321d30704bc
parent7f0b0a59425321dcc880ddc0f4b479bce85e0bb0 (diff)
pke: audio: spatial audio tweaking
-rw-r--r--src/audio.cpp59
-rw-r--r--tests/pke-test-audio.cpp6
2 files changed, 37 insertions, 28 deletions
diff --git a/src/audio.cpp b/src/audio.cpp
index e42d7e0..2743f82 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -143,7 +143,7 @@ void pke_audio_process_frames(int64_t frame_count) {
uint32_t i, ii, c;
int64_t i_frame;
float *dst;
- float val, vol, vol2;
+ float val, vol, vol2, dot, dot2;
glm::vec3 listener_origin;
glm::vec3 audio_dir = glm::vec3(0);
float *spatial_volumes = nullptr;
@@ -156,11 +156,11 @@ void pke_audio_process_frames(int64_t frame_count) {
frame_count = PK_MIN(frame_count, (pke_audio_mstr.buffer_size / stride) - pke_audio_mstr.buffer_frames);
// init
- spatial_volumes = pk_new<float>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- spatial_normals = pk_new<glm::vec3>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- params_reverb = pk_new<pke_audio_fx_params_reverb>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- params_delay = pk_new<pke_audio_fx_params_delay>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- params_low_pass_filter = pk_new<pke_audio_fx_params_low_pass_filter>(pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
+ spatial_volumes = pk_new<float>(pke_audio_mstr.channel_count, pkeSettings.mem_bkt.game_transient);
+ spatial_normals = pk_new<glm::vec3>(pke_audio_mstr.channel_count, pkeSettings.mem_bkt.game_transient);
+ params_reverb = pk_new<pke_audio_fx_params_reverb>(pke_audio_mstr.channel_count, pkeSettings.mem_bkt.game_transient);
+ params_delay = pk_new<pke_audio_fx_params_delay>(pke_audio_mstr.channel_count, pkeSettings.mem_bkt.game_transient);
+ params_low_pass_filter = pk_new<pke_audio_fx_params_low_pass_filter>(pke_audio_mstr.channel_count, pkeSettings.mem_bkt.game_transient);
dst = pke_audio_mstr.buffer + (pke_audio_mstr.buffer_frames * pke_audio_mstr.channel_count);
@@ -244,22 +244,38 @@ void pke_audio_process_frames(int64_t frame_count) {
break;
}
}
- 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);
+ dot = glm::dot(glm::vec3(0.f, 0.f, 1.f), audio_dir);
+ dot2 = glm::dot(spatial_normals[c], audio_dir);
- // 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_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) {
+ spatial_volumes[c] = PK_CLAMP(dot2, 0.f, 1.f);
+ if (pke_audio_mstr.channel_count == 2) {
+ /* 2025-07-15 JCB
+ * I changed this to always calculate for "forward".
+ * I believe this is only needed if channel_count == 2; this is to simulate surround through stereo (headphones).
+ * If the user is actually using surround sound, their own ears will do this.
+ */
+ if (!glm::isnan(dot)) {
+ val = (dot + 1.f) / 2.f; // padding lerp val
+ spatial_volumes[c] = PK_CLAMP(dot2 + lerp(0.5, 1.f, val) + 0.05, 0.0f, 1.f);
+ if (dot < 0.0) {
+ // 20k max, 500 min
+ params_low_pass_filter[c].cutoff_freq = log_interp(40000.f, 500.f, abs(dot));
+ }
+ }
+ }
+ /*
+ fprintf(stdout, "[pw] normal: % 02.0f,% 02.0f, audio_dir: % 02.6f,% 02.6f, dot: % 02.6f, dot2: % 02.6f, dot3: % 02.6f, cutoff: % 5.6f, spatial_volumes:% 02.6f\n",
+ spatial_normals[c].x, spatial_normals[c].z,
+ audio_dir.x, audio_dir.z,
+ dot, dot2, dot + dot2, params_low_pass_filter[c].cutoff_freq, spatial_volumes[c]);
+ */
+
+ if (isnan(spatial_volumes[c])) {
/*
+ * || spatial_volumes[c] == 0.0f
fprintf(stderr, "[pw] NaN or 0: chan: %i, norm: %f,%f,%f, src: %f,%f,%f, origin: %f,%f,%f\n",
c,
audio_dir.x, audio_dir.y, audio_dir.z,
@@ -356,12 +372,5 @@ void pke_audio_process_frames(int64_t frame_count) {
memset(dst, 0, sizeof(float) * frame_count * pke_audio_mstr.channel_count);
}
- // cleanup (reverse order)
- pk_delete<pke_audio_fx_params_low_pass_filter>(params_low_pass_filter, pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- pk_delete<pke_audio_fx_params_delay>(params_delay, pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- pk_delete<pke_audio_fx_params_reverb>(params_reverb, pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- pk_delete<glm::vec3>(spatial_normals, pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
- pk_delete<float>(spatial_volumes, pke_audio_mstr.channel_count, pke_audio_mstr.bkt);
-
pke_audio_mstr.buffer_frames += frame_count;
}
diff --git a/tests/pke-test-audio.cpp b/tests/pke-test-audio.cpp
index 4607033..3299576 100644
--- a/tests/pke-test-audio.cpp
+++ b/tests/pke-test-audio.cpp
@@ -140,13 +140,13 @@ int pke_test_audio_003() {
Entity_Base *ent = ECS_CreateGenericEntity();
CompInstance *inst = ECS_CreateInstance(ent, pk_uuid_zed, nullptr, &inst_pos);
- uint64_t dur_seconds = 2;
+ uint64_t dur_seconds = 4;
uint64_t total_frames = PKE_AUDIO_BITRATE * dur_seconds;
AssetHandle ahs[1];
const AssetKey aks[1] {"sawtooth"};
float freqs[1] = {2000.f};
glm::vec3 src_poss[1] = {
- glm::vec3(5, 0, 5),
+ glm::vec3(-5, 0, 0),
};
for(k = 0; k < 1; ++k) {
@@ -179,7 +179,7 @@ int pke_test_audio_003() {
delta_elapsed += delta;
pke_audio_tick(delta);
- glm::vec3 rot_pos = glm::rotate(glm::mat4(1.f), glm::radians(360.f) * delta_elapsed, glm::vec3(0.f, 1.f, 0.f)) * glm::vec4(5.f, 0.f, 5.f, 1.f);
+ glm::vec3 rot_pos = glm::rotate(glm::mat4(1.f), glm::radians(180.f) * delta_elapsed, glm::vec3(0.f, 1.f, 0.f)) * glm::vec4(src_poss[0], 1.f);
GlmToBullet(rot_pos, trfm.getOrigin());
// NOTE: fine for a test, but prefer ECS_UpdateInstance()
inst->bt.rigidBody->setWorldTransform(trfm);