summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--src/audio-impl-pw.cpp70
-rw-r--r--src/audio-impl-shared.cpp22
-rw-r--r--src/audio-impl-shared.hpp12
-rw-r--r--src/audio-types.hpp15
-rw-r--r--src/audio.cpp23
-rw-r--r--src/audio.hpp3
-rw-r--r--src/math-helpers.cpp16
-rw-r--r--src/math-helpers.hpp3
-rw-r--r--tests/pke-test-audio.cpp92
10 files changed, 234 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index 18d09b7..d4ac4cc 100644
--- a/Makefile
+++ b/Makefile
@@ -180,6 +180,7 @@ $(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/arg-handler.$(OBJ_EXT)
$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/asset-manager.$(OBJ_EXT)
$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/audio.$(OBJ_EXT)
$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/audio-impl-pw.$(OBJ_EXT)
+$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/audio-impl-shared.$(OBJ_EXT)
$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/camera.$(OBJ_EXT)
$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/dynamic-array.$(OBJ_EXT)
$(DIR_OBJ)/libpke.$(LIB_EXT): $(DIR_OBJ)/ecs.$(OBJ_EXT)
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], &params_low_pass_filter[pc]);
+ val += pke_audio_fx_reverb((float*)a->ptr, a->size / sizeof(float), (uint32_t)aobj->play_heads[pc], &params_reverb[pc]);
+ val += pke_audio_fx_delay((float*)a->ptr, a->size / sizeof(float), (uint32_t)aobj->play_heads[pc], &params_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;
diff --git a/src/audio-impl-shared.cpp b/src/audio-impl-shared.cpp
new file mode 100644
index 0000000..0c3c730
--- /dev/null
+++ b/src/audio-impl-shared.cpp
@@ -0,0 +1,22 @@
+
+#include "audio-impl-shared.hpp"
+
+float pke_audio_fx_reverb(float *buffer, uint64_t buffer_len, uint64_t buffer_idx, pke_audio_fx_params_reverb *params) {
+ if (buffer_idx >= buffer_len-1) return 0.f;
+ // simple feedback
+ return buffer[buffer_idx - 1] * params->reverb_strength;
+}
+
+float pke_audio_fx_delay(float *buffer, uint64_t buffer_len, uint64_t buffer_idx, pke_audio_fx_params_delay *params) {
+ if (buffer_idx >= buffer_len-1) return 0.f;
+ return buffer[buffer_idx - params->delay_frames];
+}
+
+float pke_audio_fx_low_pass_filter(float *buffer, uint64_t buffer_len, uint64_t buffer_idx, pke_audio_fx_params_low_pass_filter *params) {
+ if (buffer_idx >= buffer_len-1) return 0.f;
+ float rc = 1.f / std::numbers::pi * 2.0 * params->cutoff_freq;
+ float dt = 1.f / 48000.f; // TODO reference global or pass this in
+ float alpha = dt / (rc + dt);
+ params->prev_output = (alpha * buffer[buffer_idx]) + ((1.f - alpha) * params->prev_output);
+ return params->prev_output;
+}
diff --git a/src/audio-impl-shared.hpp b/src/audio-impl-shared.hpp
new file mode 100644
index 0000000..3b7b158
--- /dev/null
+++ b/src/audio-impl-shared.hpp
@@ -0,0 +1,12 @@
+#ifndef PKE_AUDIO_IMPL_SHARED_HPP
+#define PKE_AUDIO_IMPL_SHARED_HPP
+
+#include "audio-types.hpp"
+
+#include <cstdint>
+
+float pke_audio_fx_reverb(float *buffer, uint64_t buffer_len, uint64_t buffer_idx, pke_audio_fx_params_reverb *params);
+float pke_audio_fx_delay(float *buffer, uint64_t buffer_len, uint64_t buffer_idx, pke_audio_fx_params_delay *params);
+float pke_audio_fx_low_pass_filter(float *buffer, uint64_t buffer_len, uint64_t buffer_idx, pke_audio_fx_params_low_pass_filter *params);
+
+#endif /* PKE_AUDIO_IMPL_SHARED_HPP */
diff --git a/src/audio-types.hpp b/src/audio-types.hpp
index aeba5db..a0ab3fb 100644
--- a/src/audio-types.hpp
+++ b/src/audio-types.hpp
@@ -2,6 +2,7 @@
#define PKE_AUDIO_TYPES_INTERNAL_HPP
#include "asset-manager.hpp"
+#include "components.hpp"
#include "pk.h"
#include "vendor-glm-include.hpp"
@@ -20,9 +21,23 @@ const pke_audio_source pke_audio_source_ambient = pke_audio_source{0x01};
const pke_audio_source pke_audio_source_voices = pke_audio_source{0x02};
const pke_audio_source pke_audio_source_sfx = pke_audio_source{0x03};
+struct pke_audio_fx_params_reverb {
+ float reverb_strength;
+};
+
+struct pke_audio_fx_params_delay {
+ uint64_t delay_frames;
+};
+
+struct pke_audio_fx_params_low_pass_filter {
+ float cutoff_freq;
+ float prev_output;
+};
+
struct pke_audio_obj {
AssetHandle handle; // key
pke_audio_source source; // key
+ InstanceHandle instance_handle[PKE_AUDIO_MAX_CONCURRENT_COUNT];
glm::vec3 position_source[PKE_AUDIO_MAX_CONCURRENT_COUNT];
pke_audio_flags flags[PKE_AUDIO_MAX_CONCURRENT_COUNT];
uint32_t play_heads[PKE_AUDIO_MAX_CONCURRENT_COUNT];
diff --git a/src/audio.cpp b/src/audio.cpp
index 194c01c..33ea740 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -3,6 +3,8 @@
#include "asset-manager.hpp"
#include "audio-impl-pw.hpp"
#include "audio.hpp"
+#include "ecs.hpp"
+#include "math-helpers.hpp"
#include "pk.h"
struct pke_audio_master pke_audio_mstr{};
@@ -26,11 +28,29 @@ void pke_audio_teardown() {
}
void pke_audio_tick(double delta) {
(void)delta;
+ uint32_t i, k;
#ifdef PKE_AUDIO_IMPL_PIPEWIRE
if (pke_audio_pw.is_needing_output_remapped == true) {
pke_audio_pw_remap_outputs();
}
#endif
+ pke_audio_mstr.mtx_buffer.lock();
+ for (i = 0; i < pke_audio_mstr.playing_objects.next; ++i) {
+ for (k = 0; k < pke_audio_mstr.playing_objects[i].play_count; ++k) {
+ if (pke_audio_mstr.playing_objects[i].instance_handle[k] == InstanceHandle_MAX) {
+ continue;
+ }
+ CompInstance *inst = ECS_GetInstance(pke_audio_mstr.playing_objects[i].instance_handle[k]);
+ if (inst == nullptr || inst->instanceHandle == InstanceHandle_MAX) {
+ continue;
+ }
+ BulletToGlm(
+ inst->bt.rigidBody->getWorldTransform().getOrigin(),
+ pke_audio_mstr.playing_objects[i].position_source[k]
+ );
+ }
+ }
+ pke_audio_mstr.mtx_buffer.unlock();
}
float pke_audio_get_volume(pke_audio_source source) {
@@ -46,7 +66,7 @@ bool pke_audio_playing_objects_find_first_by_key(void *user_data, void *arr_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) {
+void pke_audio_play(AssetHandle handle, pke_audio_source audio_source, pke_audio_flags flags, glm::vec3 position_source, InstanceHandle instance_handle) {
// 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};
@@ -67,6 +87,7 @@ void pke_audio_play(AssetHandle handle, pke_audio_source audio_source, glm::vec3
idx = aobj->play_count;
aobj->play_count += 1;
}
+ aobj->instance_handle[idx] = instance_handle;
aobj->position_source[idx] = position_source;
aobj->flags[idx] = flags;
aobj->play_heads[idx] = 0;
diff --git a/src/audio.hpp b/src/audio.hpp
index b2eaa80..5c66b58 100644
--- a/src/audio.hpp
+++ b/src/audio.hpp
@@ -4,6 +4,7 @@
#include "audio-types.hpp"
#include "asset-manager.hpp"
+#include "components.hpp"
#include "vendor-glm-include.hpp"
void pke_audio_init();
@@ -13,7 +14,7 @@ void pke_audio_tick(double delta);
float pke_audio_get_volume(pke_audio_source source);
void pke_audio_set_volume(pke_audio_source source, float volume);
-void pke_audio_play(AssetHandle handle, pke_audio_source audio_source, glm::vec3 position_source = glm::vec3(0), pke_audio_flags flags = pke_audio_flag_none);
+void pke_audio_play(AssetHandle handle, pke_audio_source audio_source, pke_audio_flags flags, glm::vec3 position_source = glm::vec3(0), InstanceHandle instance_handle = InstanceHandle_MAX);
void pke_audio_stop_all();
#endif /* PKE_AUDIO_HPP */
diff --git a/src/math-helpers.cpp b/src/math-helpers.cpp
index 5150e55..d153ce5 100644
--- a/src/math-helpers.cpp
+++ b/src/math-helpers.cpp
@@ -48,3 +48,19 @@ void BulletToGlm(const btTransform &trans, glm::mat4 &glmMat4) {
glmMat4[3][3] = 1.0f;
}
+template<typename T>
+T log_interp_T(T min_value, T max_value, T t) {
+ T start = log10(min_value);
+ T end = log10(max_value);
+ T intrp = start + (t * (end - start));
+ return pow(T(10), intrp);
+}
+
+float log_interp(float min_value, float max_value, float t) {
+ return log_interp_T<float>(min_value, max_value, t);
+}
+
+double log_interp(double min_value, double max_value, double t) {
+ return log_interp_T<double>(min_value, max_value, t);
+}
+
diff --git a/src/math-helpers.hpp b/src/math-helpers.hpp
index 2039348..8625758 100644
--- a/src/math-helpers.hpp
+++ b/src/math-helpers.hpp
@@ -12,4 +12,7 @@ void BulletToGlm(const btVector3 &vec, glm::vec3 &glmVec);
void BulletToGlm(const btQuaternion &quat, glm::quat &glmQuat);
void BulletToGlm(const btTransform &trans, glm::mat4 &glmMat4);
+float log_interp(float min_value, float max_value, float t);
+double log_interp(double min_value, double max_value, double t);
+
#endif /* PKE_MATH_HELPERS_HPP */
diff --git a/tests/pke-test-audio.cpp b/tests/pke-test-audio.cpp
index 076634a..2d48022 100644
--- a/tests/pke-test-audio.cpp
+++ b/tests/pke-test-audio.cpp
@@ -1,7 +1,10 @@
#include "./pke-test-audio.h"
+#include "ecs.hpp"
#include "game-settings.hpp"
+#include "math-helpers.hpp"
+#include "physics.hpp"
#include "pk.h"
#include "audio-types.hpp"
@@ -21,13 +24,18 @@ void pke_test_audio_spinup() {
pkeSettings.isSimulationPaused = true;
PkeThreads_Init();
AM_Init();
+ Physics_Init();
+ ECS_Init();
pke_audio_init();
+ pke_audio_mstr.master_volume = 0.125;
// pk_funcinstr_teardown();
};
void pke_test_audio_teardown() {
// pk_funcinstr_init();
pke_audio_teardown();
+ ECS_Teardown();
+ Physics_Teardown();
AM_Teardown();
PkeThreads_Teardown();
bkt = nullptr;
@@ -54,7 +62,7 @@ int pke_test_audio_001() {
AssetHandle ah_sawtooth = AM_Register(ak_sawtooth, PKE_ASSET_TYPE_AUDIO, zip_bop_bytes, sizeof(float) * 48000, 64);
pk_delete<float>(zip_bop_bytes, 48000, bkt);
- pke_audio_play(ah_sawtooth, pke_audio_source_music, glm::vec3(0), pke_audio_flag_none);
+ pke_audio_play(ah_sawtooth, pke_audio_source_music, pke_audio_flag_none, glm::vec3(0));
while (pke_audio_mstr.playing_objects.next > 0) {
pke_audio_tick(0.001f);
@@ -101,7 +109,7 @@ int pke_test_audio_002() {
}
std::chrono::milliseconds(1);
for(k = 0; k < 3; ++k) {
- pke_audio_play(ahs[k], pke_audio_source_music, src_poss[k], pke_audio_flag_pos_spatial);
+ pke_audio_play(ahs[k], pke_audio_source_music, pke_audio_flag_pos_spatial, src_poss[k]);
}
while (pke_audio_mstr.playing_objects.next > 0) {
@@ -121,8 +129,81 @@ int pke_test_audio_002() {
return 0;
}
+int pke_test_audio_003() {
+ uint64_t i, k;
+ try {
+ bkt = pk_mem_bucket_create("pke_test_serialization", PK_MEM_DEFAULT_BUCKET_SIZE, PK_MEMBUCKET_FLAG_NONE);
+
+ UBO.model = glm::translate(glm::mat4(1.f), glm::vec3(0, 0, 0));
+
+ InstPos inst_pos{};
+ Entity_Base *ent = ECS_CreateGenericEntity();
+ CompInstance *inst = ECS_CreateInstance(ent, pk_uuid_zed, nullptr, &inst_pos);
+
+ uint64_t dur_seconds = 2;
+ uint64_t bit_rate = 48000;
+ uint64_t total_frames = bit_rate * 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),
+ };
+
+ for(k = 0; k < 1; ++k) {
+ float *zip_bop_bytes = pk_new<float>(total_frames, bkt);
+ float phase = 0.0f;
+ float phase_increment = freqs[k] / float(bit_rate);
+ for (i = 0; i < total_frames; ++i) {
+ zip_bop_bytes[i] = 2.f * (phase - floor(phase + 0.5f));
+ phase += phase_increment;
+ if (phase >= 1.f) phase -= 1.f;
+ }
+ ahs[k] = AM_Register(aks[k], PKE_ASSET_TYPE_AUDIO, zip_bop_bytes, sizeof(float) * total_frames, 64);
+ pk_delete<float>(zip_bop_bytes, total_frames, bkt);
+ }
+
+ for(k = 0; k < 1; ++k) {
+ pke_audio_play(ahs[k], pke_audio_source_music, pke_audio_flag_pos_spatial, src_poss[k], inst->instanceHandle);
+ }
+
+
+ float delta = 0.f;
+ float delta_elapsed = 0.f;
+ btTransform trfm{};
+ std::chrono::time_point ts = std::chrono::steady_clock::now();
+ std::chrono::time_point now = std::chrono::steady_clock::now();
+ while (pke_audio_mstr.playing_objects.next > 0) {
+ now = std::chrono::steady_clock::now();
+ auto ts_diff = now - ts;
+ delta = ts_diff.count() / 1000000000.f;
+ ts = now;
+
+ 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);
+ GlmToBullet(rot_pos, trfm.getOrigin());
+ // NOTE: fine for a test, but prefer ECS_UpdateInstance()
+ inst->bt.rigidBody->setWorldTransform(trfm);
+ // fprintf(stdout, "%f,%f,%f\n", rot_pos.x, rot_pos.y, rot_pos.z);
+
+ std::this_thread::sleep_for(std::chrono::nanoseconds(1));
+ }
+
+ for(k = 0; k < 1; ++k) {
+ AM_Release(ahs[k]);
+ }
+
+ } catch (const std::exception &ex) {
+ pk_mem_bucket_destroy(bkt);
+ throw;
+ }
+ pk_mem_bucket_destroy(bkt);
+ return 0;
+}
+
struct pke_test_group *pke_test_audio_get_group() {
- static const uint64_t test_count = 2;
+ static const uint64_t test_count = 3;
static struct pke_test tests[test_count] = {
{
.title = "test 001",
@@ -134,6 +215,11 @@ struct pke_test_group *pke_test_audio_get_group() {
.func = pke_test_audio_002,
.expected_result = 0,
},
+ {
+ .title = "test 003",
+ .func = pke_test_audio_003,
+ .expected_result = 0,
+ },
};
static struct pke_test_group group = {};
group.title = "audio";