summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-30 23:46:40 -0500
committersanine <sanine.not@pm.me>2022-08-30 23:46:40 -0500
commiteb4e4cab2d3f24ee7f8d0be7149162084fe98392 (patch)
tree37affdd321ee4f14965eb98000ae82a051efba40 /src
parent489c3771e648d412cab283c660996c880149315d (diff)
add mono panning
Diffstat (limited to 'src')
-rw-r--r--src/channel.c33
-rw-r--r--src/channel.test.c58
-rw-r--r--src/test/lily-test.c5
3 files changed, 83 insertions, 13 deletions
diff --git a/src/channel.c b/src/channel.c
index 2fd0324..a29e7f7 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <plibsys.h>
#include "channel.h"
@@ -64,6 +65,15 @@ void channel_set_pan(struct channel_t *chan, float pan_left, float pan_right)
}
+#define QUARTER_PI 0.785397
+static void pan_gain(float *gain_l, float *gain_r, float pan)
+{
+ float theta = (QUARTER_PI * pan) + QUARTER_PI; /* 0-PI/2 */
+ *gain_l = cos(theta);
+ *gain_r = sin(theta);
+}
+
+
void channel_get_next_sample(float *left, float *right, struct channel_t *chan)
{
bool active = p_atomic_int_get(&(chan->active));
@@ -82,17 +92,24 @@ void channel_get_next_sample(float *left, float *right, struct channel_t *chan)
return;
}
- float l, r;
+ float volume = ((float)p_atomic_int_get(&(chan->volume)))/255;
- l = chan->sound.left[chan->pos];
- if (chan->sound.mono)
- r = l;
- else
+ if (chan->sound.mono) {
+ float x = chan->sound.left[chan->pos];
+ float pan = ((float)p_atomic_int_get(&(chan->pan_left)))/128;
+ float gain_l, gain_r;
+ pan_gain(&gain_l, &gain_r, pan);
+ *left = volume * gain_l * x;
+ *right = volume * gain_r * x;
+ }
+ else {
+ float l, r;
+ l = chan->sound.left[chan->pos];
r = chan->sound.right[chan->pos];
+ *left = volume * l;
+ *right = volume * r;
+ }
- 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.test.c b/src/channel.test.c
index 427fd63..150adb9 100644
--- a/src/channel.test.c
+++ b/src/channel.test.c
@@ -336,20 +336,71 @@ void test_channel_get_next_sample_mono()
float l, r;
+ const float gain = 0.7071; /* constant-power panning center gain */
+
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_assert_float_equal(l, gain * 0.0f, 0.1f);
+ lily_assert_float_equal(r, gain * 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, gain * 0.5f, 0.1f);
+ lily_assert_float_equal(r, gain * 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, gain * 1.0f, 0.1f);
+ lily_assert_float_equal(r, gain * 1.0f, 0.1f);
+}
+
+
+void test_channel_get_next_sample_mono_panned()
+{
+ 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 = -128;
+ 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;
+
+ const float gain = 0.7071; /* constant-power panning center gain */
+
+ 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, gain * 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.5f, 0.1f);
lily_assert_float_equal(r, 0.0f, 0.1f);
lily_store_value(mock_p_mutex_trylock, pboolean, TRUE);
@@ -358,7 +409,7 @@ void test_channel_get_next_sample_mono()
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(l, 1.0f, 0.1f);
lily_assert_float_equal(r, 0.0f, 0.1f);
}
@@ -379,6 +430,7 @@ void suite_channel()
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_run_test(test_channel_get_next_sample_mono_panned);
lily_mock_destroy(mock_p_mutex_new);
}
diff --git a/src/test/lily-test.c b/src/test/lily-test.c
index a8381d0..30f96d5 100644
--- a/src/test/lily-test.c
+++ b/src/test/lily-test.c
@@ -47,6 +47,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include "lily-test.h"
struct lily_globals_t _lily_globals = { {0}, 0, NULL, "" };
@@ -209,7 +210,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, location,
+ lily_assert_msg(fabs(a - b) <= epsilon, location,
"%s (%f) is not equal to %s (%f) (epsilon: %f)",
name_a, a, name_b, b, epsilon);
}
@@ -218,7 +219,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, location,
+ lily_assert_msg(fabs(a - b) > epsilon, location,
"%s (%f) is equal to %s (%f) (epsilon: %f)",
name_a, a, name_b, b, epsilon);
}