From d232fd1b3add3a93b81fc040d8b7e165590930cf Mon Sep 17 00:00:00 2001 From: sanine Date: Sun, 28 Aug 2022 14:21:42 -0500 Subject: add channel_get_next_sample() --- src/channel.c | 30 +++++++++++ src/channel.h | 1 + src/channel.test.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/test/lily-test.c | 12 ++--- 4 files changed, 174 insertions(+), 6 deletions(-) diff --git a/src/channel.c b/src/channel.c index e6e6c3f..b9242c4 100644 --- a/src/channel.c +++ b/src/channel.c @@ -26,3 +26,33 @@ void channel_reset(struct channel_t *chan) chan->pos = 0; p_atomic_int_set(&(chan->active), false); } + + +void channel_get_next_sample(float *left, float *right, struct channel_t *chan) +{ + bool active = p_atomic_int_get(&(chan->active)); + bool paused = p_atomic_int_get(&(chan->paused)); + if (!active || paused) { + /* skip this channel */ + *left = 0; + *right = 0; + return; + } + + if (!p_mutex_trylock(chan->sound_mutex)) { + /* can't lock mutex, skip */ + *left = 0; + *right = 0; + return; + } + + *left = chan->sound.left[chan->pos]; + *right = chan->sound.right[chan->pos]; + chan->pos += 1; + + if (chan->pos >= chan->sound.len) { + channel_reset(chan); + } + + p_mutex_unlock(chan->sound_mutex); +} diff --git a/src/channel.h b/src/channel.h index 4d0800b..2bc45d2 100644 --- a/src/channel.h +++ b/src/channel.h @@ -21,6 +21,7 @@ struct channel_t { void channel_init(struct channel_t *chan); void channel_reset(struct channel_t *chan); +void channel_get_next_sample(float *left, float *right, struct channel_t *chan); #endif diff --git a/src/channel.test.c b/src/channel.test.c index e7f7e06..532d153 100644 --- a/src/channel.test.c +++ b/src/channel.test.c @@ -2,12 +2,18 @@ #include PMutex * mock_p_mutex_new_(); +pboolean mock_p_mutex_trylock_(); +pboolean mock_p_mutex_unlock_(); #define p_mutex_new mock_p_mutex_new_ +#define p_mutex_trylock mock_p_mutex_trylock_ +#define p_mutex_unlock mock_p_mutex_unlock_ #include "channel.c" #undef p_mutex_new +/* ~~~~~~~~ mocks ~~~~~~~~ */ + lily_mock_t *mock_p_mutex_new = NULL; PMutex * mock_p_mutex_new_() { @@ -16,6 +22,26 @@ PMutex * mock_p_mutex_new_() } +lily_mock_t *mock_p_mutex_trylock = NULL; +pboolean mock_p_mutex_trylock_(PMutex *m) +{ + mock_p_mutex_trylock->n_calls += 1; + pboolean result; + lily_get_value(mock_p_mutex_trylock, pboolean, &result); + return result; +} + + +lily_mock_t *mock_p_mutex_unlock = NULL; +pboolean mock_p_mutex_unlock_(PMutex *m) +{ + mock_p_mutex_unlock->n_calls += 1; + return TRUE; +} + + +/* ~~~~~~~~ tests ~~~~~~~~ */ + void test_channel_init() { lily_mock_use(&mock_p_mutex_new); @@ -55,10 +81,121 @@ void test_channel_reset() } +void test_channel_get_next_sample_inactive() +{ + lily_mock_use(&mock_p_mutex_trylock); + lily_mock_use(&mock_p_mutex_unlock); + + struct channel_t chan; + chan.active = false; + chan.pos = 0; + float l = 22; float r = 22; + channel_get_next_sample(&l, &r, &chan); + + lily_assert_int_equal(mock_p_mutex_trylock->n_calls, 0); + lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 0); + lily_assert_int_equal(chan.pos, 0); + lily_assert_float_equal(l, 0.0f, 0.1f); + lily_assert_float_equal(r, 0.0f, 0.1f); +} + + +void test_channel_get_next_sample_paused() +{ + lily_mock_use(&mock_p_mutex_trylock); + lily_mock_use(&mock_p_mutex_unlock); + + struct channel_t chan; + chan.active = true; + chan.paused = true; + chan.pos = 0; + float l = 22; float r = 22; + channel_get_next_sample(&l, &r, &chan); + + lily_assert_int_equal(mock_p_mutex_trylock->n_calls, 0); + lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 0); + lily_assert_int_equal(chan.pos, 0); + lily_assert_float_equal(l, 0.0f, 0.1f); + lily_assert_float_equal(r, 0.0f, 0.1f); +} + + +void test_channel_get_next_sample_nolock() +{ + lily_mock_use(&mock_p_mutex_trylock); + lily_mock_use(&mock_p_mutex_unlock); + + struct channel_t chan; + chan.active = true; + chan.paused = false; + chan.pos = 0; + float l = 22; float r = 22; + + lily_store_value(mock_p_mutex_trylock, pboolean, FALSE); + channel_get_next_sample(&l, &r, &chan); + lily_assert_int_equal(mock_p_mutex_trylock->n_calls, 1); + lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 0); + + lily_assert_int_equal(chan.pos, 0); + lily_assert_float_equal(l, 0.0f, 0.1f); + lily_assert_float_equal(r, 0.0f, 0.1f); +} + + +void test_channel_get_next_sample_normal() +{ + lily_mock_use(&mock_p_mutex_trylock); + lily_mock_use(&mock_p_mutex_unlock); + + struct channel_t chan; + chan.active = true; + chan.paused = false; + chan.volume = 255; + chan.pan = 0; + float audio_left[] = { 0.0, 0.5, 1.0 }; + float audio_right[] = { 1.0, 0.5, 0.0 }; + chan.sound.left = audio_left; + chan.sound.right = audio_right; + chan.sound.len = 3; + chan.pos = 0; + + float l, r; + + lily_store_value(mock_p_mutex_trylock, pboolean, TRUE); + channel_get_next_sample(&l, &r, &chan); + lily_assert_int_equal(mock_p_mutex_trylock->n_calls, 1); + lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1); + lily_assert_int_equal(chan.pos, 1); + lily_assert_float_equal(l, 0.0f, 0.1f); + lily_assert_float_equal(r, 1.0f, 0.1f); + + lily_store_value(mock_p_mutex_trylock, pboolean, TRUE); + channel_get_next_sample(&l, &r, &chan); + lily_assert_int_equal(mock_p_mutex_trylock->n_calls, 2); + lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 2); + lily_assert_int_equal(chan.pos, 2); + lily_assert_float_equal(l, 0.5f, 0.1f); + lily_assert_float_equal(r, 0.5f, 0.1f); + + lily_store_value(mock_p_mutex_trylock, pboolean, TRUE); + channel_get_next_sample(&l, &r, &chan); + lily_assert_int_equal(mock_p_mutex_trylock->n_calls, 3); + lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 3); + lily_assert_int_equal(chan.pos, 0); + lily_assert_int_equal(chan.active, false); + lily_assert_float_equal(l, 1.0f, 0.1f); + lily_assert_float_equal(r, 0.0f, 0.1f); +} + + void suite_channel() { lily_run_test(test_channel_init); lily_run_test(test_channel_reset); + lily_run_test(test_channel_get_next_sample_inactive); + lily_run_test(test_channel_get_next_sample_paused); + lily_run_test(test_channel_get_next_sample_normal); + lily_run_test(test_channel_get_next_sample_nolock); lily_mock_destroy(mock_p_mutex_new); } diff --git a/src/test/lily-test.c b/src/test/lily-test.c index 2f43a28..a8381d0 100644 --- a/src/test/lily-test.c +++ b/src/test/lily-test.c @@ -209,7 +209,7 @@ void _lily_assert_int_not_equal(const char *name_a, const char *name_b, void _lily_assert_float_equal(const char *name_a, const char *name_b, double a, double b, double epsilon, const char *location) { - lily_assert_msg(abs(a - b) <= epsilon, + lily_assert_msg(abs(a - b) <= epsilon, location, "%s (%f) is not equal to %s (%f) (epsilon: %f)", name_a, a, name_b, b, epsilon); } @@ -218,7 +218,7 @@ void _lily_assert_float_equal(const char *name_a, const char *name_b, void _lily_assert_float_not_equal(const char *name_a, const char *name_b, double a, double b, double epsilon, const char *location) { - lily_assert_msg(abs(a - b) > epsilon, + lily_assert_msg(abs(a - b) > epsilon, location, "%s (%f) is equal to %s (%f) (epsilon: %f)", name_a, a, name_b, b, epsilon); } @@ -227,7 +227,7 @@ void _lily_assert_float_not_equal(const char *name_a, const char *name_b, void _lily_assert_string_equal(const char *name_a, const char *name_b, char *a, char *b, const char *location) { - lily_assert_msg(strcmp(a, b) == 0, + lily_assert_msg(strcmp(a, b) == 0, location, "%s ('%s') is not equal to %s ('%s')", name_a, a, name_b, b); } @@ -236,7 +236,7 @@ void _lily_assert_string_equal(const char *name_a, const char *name_b, void _lily_assert_string_not_equal(const char *name_a, const char *name_b, char *a, char *b, const char *location) { - lily_assert_msg(strcmp(a, b) != 0, + lily_assert_msg(strcmp(a, b) != 0, location, "%s ('%s') is equal to %s", name_a, a, name_b); } @@ -245,7 +245,7 @@ void _lily_assert_string_not_equal(const char *name_a, const char *name_b, void _lily_assert_memory_equal(const char *name_a, const char *name_b, void *a, void *b, size_t size, const char *location) { - lily_assert_msg(memcmp(a, b, size) == 0, + lily_assert_msg(memcmp(a, b, size) == 0, location, "%s and %s contain different data", name_a, name_b); } @@ -253,7 +253,7 @@ void _lily_assert_memory_equal(const char *name_a, const char *name_b, void _lily_assert_memory_not_equal(const char *name_a, const char *name_b, void *a, void *b, size_t size, const char *location) { - lily_assert_msg(memcmp(a, b, size) == 0, + lily_assert_msg(memcmp(a, b, size) == 0, location, "%s contains the same data s %s", name_a, name_b); } -- cgit v1.2.1