summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-30 22:25:43 -0500
committersanine <sanine.not@pm.me>2022-08-30 22:25:43 -0500
commit489c3771e648d412cab283c660996c880149315d (patch)
tree07c8734f4352c460f83e0c9fd0cf9ee00b34e210
parentb9761d521087e23ee7a83b854d356b1fa07fe06e (diff)
refactor: use stereo panning model
-rw-r--r--include/mossrose.h2
-rw-r--r--src/channel.c31
-rw-r--r--src/channel.h11
-rw-r--r--src/channel.test.c151
4 files changed, 162 insertions, 33 deletions
diff --git a/include/mossrose.h b/include/mossrose.h
index 5ca454a..44d5477 100644
--- a/include/mossrose.h
+++ b/include/mossrose.h
@@ -2,10 +2,12 @@
#define MOSSROSE_H
#include <stddef.h>
+#include <stdbool.h>
struct mossrose_sound_t {
float *left;
float *right;
+ bool mono;
size_t len;
};
diff --git a/src/channel.c b/src/channel.c
index 603a980..2fd0324 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -9,7 +9,8 @@ void channel_init(struct channel_t *chan)
chan->active = false;
chan->paused = false;
chan->volume = 255;
- chan->pan = 0;
+ chan->pan_left = -128;
+ chan->pan_right = 128;
chan->sound_mutex = p_mutex_new();
chan->sound.left = NULL;
@@ -22,7 +23,8 @@ void channel_reset(struct channel_t *chan)
{
p_atomic_int_set(&(chan->paused), false);
p_atomic_int_set(&(chan->volume), 255);
- p_atomic_int_set(&(chan->pan), 0);
+ p_atomic_int_set(&(chan->pan_left), -128);
+ p_atomic_int_set(&(chan->pan_right), 128);
chan->pos = 0;
p_atomic_int_set(&(chan->active), false);
}
@@ -49,12 +51,16 @@ void channel_set_volume(struct channel_t *chan, float volume)
}
-void channel_set_pan(struct channel_t *chan, float pan)
+void channel_set_pan(struct channel_t *chan, float pan_left, float pan_right)
{
- if (pan > 1.0f) pan = 1.0f;
- if (pan < -1.0f) pan = -1.0f;
+ if (pan_left > 1.0f) pan_left = 1.0f;
+ if (pan_left < -1.0f) pan_left = -1.0f;
- p_atomic_int_set(&(chan->pan), 128*pan);
+ if (pan_right > 1.0f) pan_right = 1.0f;
+ if (pan_right < -1.0f) pan_right = -1.0f;
+
+ p_atomic_int_set(&(chan->pan_left), 128*pan_left);
+ p_atomic_int_set(&(chan->pan_right), 128*pan_right);
}
@@ -76,8 +82,17 @@ void channel_get_next_sample(float *left, float *right, struct channel_t *chan)
return;
}
- *left = chan->sound.left[chan->pos];
- *right = chan->sound.right[chan->pos];
+ float l, r;
+
+ l = chan->sound.left[chan->pos];
+ if (chan->sound.mono)
+ r = l;
+ else
+ r = chan->sound.right[chan->pos];
+
+ float volume = ((float)p_atomic_int_get(&(chan->active)))/255;
+ *left = volume * l;
+ *right = volume * r;
chan->pos += 1;
if (chan->pos >= chan->sound.len) {
diff --git a/src/channel.h b/src/channel.h
index 6f06803..ec1f645 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -8,10 +8,11 @@
struct channel_t {
- volatile pint active; /* boolean */
- volatile pint paused; /* boolean */
- volatile pint volume; /* 0-255 */
- volatile pint pan; /* -128-128 */
+ volatile pint active; /* boolean */
+ volatile pint paused; /* boolean */
+ volatile pint volume; /* 0-255 */
+ volatile pint pan_left; /* -128-128 */
+ volatile pint pan_right; /* -128-128 */
PMutex *sound_mutex;
struct mossrose_sound_t sound;
@@ -24,7 +25,7 @@ void channel_reset(struct channel_t *chan);
void channel_pause(struct channel_t *chan);
void channel_resume(struct channel_t *chan);
void channel_set_volume(struct channel_t *chan, float volume);
-void channel_set_pan(struct channel_t *chan, float pan);
+void channel_set_pan(struct channel_t *chan, float pan_left, float pan_right);
void channel_get_next_sample(float *left, float *right, struct channel_t *chan);
diff --git a/src/channel.test.c b/src/channel.test.c
index 2c5cdad..427fd63 100644
--- a/src/channel.test.c
+++ b/src/channel.test.c
@@ -54,7 +54,8 @@ void test_channel_init()
lily_assert_int_equal(chan.active, false);
lily_assert_int_equal(chan.paused, false);
lily_assert_int_equal(chan.volume, 255);
- lily_assert_int_equal(chan.pan, 0);
+ lily_assert_int_equal(chan.pan_left, -128);
+ lily_assert_int_equal(chan.pan_right, 128);
lily_assert_null(chan.sound.left);
lily_assert_null(chan.sound.right);
@@ -69,7 +70,8 @@ void test_channel_reset()
chan.active = true;
chan.paused = true;
chan.volume = 5;
- chan.pan = 30;
+ chan.pan_left = 30;
+ chan.pan_right = 30;
channel_reset(&chan);
@@ -77,7 +79,8 @@ void test_channel_reset()
lily_assert_int_equal(chan.active, false);
lily_assert_int_equal(chan.paused, false);
lily_assert_int_equal(chan.volume, 255);
- lily_assert_int_equal(chan.pan, 0);
+ lily_assert_int_equal(chan.pan_left, -128);
+ lily_assert_int_equal(chan.pan_right, 128);
}
@@ -126,24 +129,32 @@ void test_channel_set_volume()
void test_channel_set_pan()
{
struct channel_t chan;
- chan.pan = 255;
-
- channel_set_pan(&chan, -1.0f);
- lily_assert_int_equal(chan.pan, -128);
- channel_set_pan(&chan, -0.5f);
- lily_assert_int_equal(chan.pan, -64);
- channel_set_pan(&chan, 0.0f);
- lily_assert_int_equal(chan.pan, 0);
- channel_set_pan(&chan, 0.5f);
- lily_assert_int_equal(chan.pan, 64);
- channel_set_pan(&chan, 1.0f);
- lily_assert_int_equal(chan.pan, 128);
+ chan.pan_left = 255;
+ chan.pan_right = 255;
+
+ channel_set_pan(&chan, -1.0f, 1.0f);
+ lily_assert_int_equal(chan.pan_left, -128);
+ lily_assert_int_equal(chan.pan_right, 128);
+ channel_set_pan(&chan, -0.5f, 0.5f);
+ lily_assert_int_equal(chan.pan_left, -64);
+ lily_assert_int_equal(chan.pan_right, 64);
+ channel_set_pan(&chan, 0.0f, 0.0f);
+ lily_assert_int_equal(chan.pan_left, 0);
+ lily_assert_int_equal(chan.pan_right, 0);
+ channel_set_pan(&chan, 0.5f, -0.5f);
+ lily_assert_int_equal(chan.pan_left, 64);
+ lily_assert_int_equal(chan.pan_right, -64);
+ channel_set_pan(&chan, 1.0f, -1.0f);
+ lily_assert_int_equal(chan.pan_left, 128);
+ lily_assert_int_equal(chan.pan_right, -128);
/* oob */
- channel_set_pan(&chan, -10.0f);
- lily_assert_int_equal(chan.pan, -128);
- channel_set_pan(&chan, 2.0f);
- lily_assert_int_equal(chan.pan, 128);
+ channel_set_pan(&chan, -10.0f, 2.0f);
+ lily_assert_int_equal(chan.pan_left, -128);
+ lily_assert_int_equal(chan.pan_right, 128);
+ channel_set_pan(&chan, 2.0f, -10.0f);
+ lily_assert_int_equal(chan.pan_left, 128);
+ lily_assert_int_equal(chan.pan_right, -128);
}
@@ -218,11 +229,13 @@ void test_channel_get_next_sample_normal()
chan.active = true;
chan.paused = false;
chan.volume = 255;
- chan.pan = 0;
+ chan.pan_left = -128;
+ chan.pan_right = 128;
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.mono = false;
chan.sound.len = 3;
chan.pos = 0;
@@ -255,6 +268,102 @@ void test_channel_get_next_sample_normal()
}
+void test_channel_get_next_sample_volume_0()
+{
+ 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 = 0;
+ chan.pan_left = -128;
+ chan.pan_right = 128;
+ 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.mono = false;
+ 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, 0.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.0f, 0.1f);
+ lily_assert_float_equal(r, 0.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, 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, 0.0f, 0.1f);
+ lily_assert_float_equal(r, 0.0f, 0.1f);
+}
+
+
+void test_channel_get_next_sample_mono()
+{
+ 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_left = 0;
+ chan.pan_right = 128;
+ float audio[] = { 0.0, 0.5, 1.0 };
+ chan.sound.left = audio;
+ chan.sound.right = NULL;
+ chan.sound.mono = true;
+ 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, 0.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.0f, 0.1f);
+ lily_assert_float_equal(r, 0.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, 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, 0.0f, 0.1f);
+ lily_assert_float_equal(r, 0.0f, 0.1f);
+}
+
+
+
void suite_channel()
{
lily_run_test(test_channel_init);
@@ -268,6 +377,8 @@ void suite_channel()
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_run_test(test_channel_get_next_sample_volume_0);
+ lily_run_test(test_channel_get_next_sample_mono);
lily_mock_destroy(mock_p_mutex_new);
}