summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-31 11:51:54 -0500
committersanine <sanine.not@pm.me>2022-08-31 11:51:54 -0500
commit54351358e17b36212872313f4a820d59f14fdf12 (patch)
treeecbbf34f0d2958600956c485d3f1739279b7ee81
parentb4db9391540442f9708388731d5bcd6fc59b6f5c (diff)
add channel sound loading
-rw-r--r--src/channel.c36
-rw-r--r--src/channel.h1
-rw-r--r--src/channel.test.c172
-rw-r--r--src/mossrose.c21
-rw-r--r--src/sound.c1
5 files changed, 223 insertions, 8 deletions
diff --git a/src/channel.c b/src/channel.c
index d039701..62e32fc 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -3,6 +3,7 @@
#include <math.h>
#include <plibsys.h>
#include "channel.h"
+#include "sound.h"
void channel_init(struct channel_t *chan)
@@ -23,9 +24,6 @@ void channel_init(struct channel_t *chan)
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_left), -128);
- p_atomic_int_set(&(chan->pan_right), 128);
chan->pos = 0;
p_atomic_int_set(&(chan->active), false);
}
@@ -65,6 +63,38 @@ void channel_set_pan(struct channel_t *chan, float pan_left, float pan_right)
}
+int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, bool force)
+{
+ if (!force && p_atomic_int_get(&(chan->active)))
+ /* active, fail! */
+ return 1;
+
+ p_mutex_lock(chan->sound_mutex);
+ sound_copy(&(chan->sound), sound);
+ chan->pos = 0;
+
+ p_atomic_int_set(&(chan->paused), false);
+
+ if (!force) {
+ /* overwrite channel settings */
+ p_atomic_int_set(&(chan->volume), 255);
+ if (sound->mono) {
+ p_atomic_int_set(&(chan->pan_left), 0);
+ p_atomic_int_set(&(chan->pan_right), 0);
+ }
+ else {
+ /* stereo */
+ p_atomic_int_set(&(chan->pan_left), -128);
+ p_atomic_int_set(&(chan->pan_right), 128);
+ }
+ }
+ p_mutex_unlock(chan->sound_mutex);
+
+ p_atomic_int_set(&(chan->active), true);
+ return 0;
+}
+
+
#define QUARTER_PI 0.785397
static void pan_gain(float *gain_l, float *gain_r, float pan)
{
diff --git a/src/channel.h b/src/channel.h
index ec1f645..d4ff6ee 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -26,6 +26,7 @@ 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_left, float pan_right);
+int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, bool force);
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 c0a7e73..cab741b 100644
--- a/src/channel.test.c
+++ b/src/channel.test.c
@@ -3,10 +3,12 @@
PMutex * mock_p_mutex_new_();
pboolean mock_p_mutex_trylock_();
+pboolean mock_p_mutex_lock_();
pboolean mock_p_mutex_unlock_();
#define p_mutex_new mock_p_mutex_new_
#define p_mutex_trylock mock_p_mutex_trylock_
+#define p_mutex_lock mock_p_mutex_lock_
#define p_mutex_unlock mock_p_mutex_unlock_
#include "channel.c"
#undef p_mutex_new
@@ -31,6 +33,12 @@ pboolean mock_p_mutex_trylock_(PMutex *m)
return result;
}
+lily_mock_t *mock_p_mutex_lock = NULL;
+pboolean mock_p_mutex_lock_(PMutex *m)
+{
+ mock_p_mutex_lock->n_calls += 1;
+ return TRUE;
+}
lily_mock_t *mock_p_mutex_unlock = NULL;
pboolean mock_p_mutex_unlock_(PMutex *m)
@@ -78,9 +86,6 @@ void test_channel_reset()
lily_assert_int_equal(chan.pos, 0);
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_left, -128);
- lily_assert_int_equal(chan.pan_right, 128);
}
@@ -158,6 +163,162 @@ void test_channel_set_pan()
}
+void test_channel_sound_load()
+{
+ lily_mock_use(&mock_p_mutex_lock);
+ lily_mock_use(&mock_p_mutex_unlock);
+
+ float audio_left[] = { 0.2, 0.5, 1.0 };
+ float audio_right[] = { 1.0, 0.5, 0.2 };
+ struct mossrose_sound_t sound;
+ sound.left = audio_left;
+ sound.right = audio_right;
+ sound.mono = false;
+ sound.len = 3;
+
+ struct channel_t chan;
+ chan.active = false;
+ chan.sound.left = NULL;
+ chan.sound.right = NULL;
+
+ int result = channel_sound_load(&chan, &sound, false);
+
+ lily_assert_int_equal(mock_p_mutex_lock->n_calls, 1);
+ lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1);
+ lily_assert_int_equal(result, 0);
+
+ lily_assert_int_equal(chan.active, true);
+ lily_assert_int_equal(chan.paused, false);
+ lily_assert_int_equal(chan.volume, 255);
+ lily_assert_int_equal(chan.pan_left, -128);
+ lily_assert_int_equal(chan.pan_right, 128);
+
+ lily_assert_memory_equal(chan.sound.left, audio_left, sizeof(audio_left));
+ lily_assert_memory_equal(chan.sound.right, audio_right, sizeof(audio_right));
+ lily_assert_int_equal(chan.sound.mono, false);
+ lily_assert_int_equal(chan.pos, 0);
+}
+
+
+void test_channel_sound_load_mono()
+{
+ lily_mock_use(&mock_p_mutex_lock);
+ lily_mock_use(&mock_p_mutex_unlock);
+
+ float audio[] = { 0.2, 0.5, 1.0 };
+ struct mossrose_sound_t sound;
+ sound.left = audio;
+ sound.right = NULL;
+ sound.mono = true;
+ sound.len = 3;
+
+ struct channel_t chan;
+ chan.active = false;
+ chan.sound.left = NULL;
+ chan.sound.right = NULL;
+
+ int result = channel_sound_load(&chan, &sound, false);
+
+ lily_assert_int_equal(mock_p_mutex_lock->n_calls, 1);
+ lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1);
+ lily_assert_int_equal(result, 0);
+
+ lily_assert_int_equal(chan.active, true);
+ lily_assert_int_equal(chan.paused, false);
+ lily_assert_int_equal(chan.volume, 255);
+ lily_assert_int_equal(chan.pan_left, 0);
+ lily_assert_int_equal(chan.pan_right, 0);
+
+ lily_assert_memory_equal(chan.sound.left, audio, sizeof(audio));
+ lily_assert_null(chan.sound.right);
+ lily_assert_int_equal(chan.sound.mono, true);
+ lily_assert_int_equal(chan.pos, 0);
+}
+
+
+void test_channel_sound_load_preserve()
+{
+ lily_mock_use(&mock_p_mutex_lock);
+ lily_mock_use(&mock_p_mutex_unlock);
+
+ float audio_left[] = { 0.2, 0.5, 1.0 };
+ float audio_right[] = { 1.0, 0.5, 0.2 };
+ struct mossrose_sound_t sound;
+ sound.left = audio_left;
+ sound.right = audio_right;
+ sound.mono = false;
+ sound.len = 3;
+
+ struct channel_t chan;
+ chan.active = false;
+ chan.sound.left = NULL;
+ chan.sound.right = NULL;
+ chan.volume = 127;
+ chan.pan_left = 0;
+ chan.pan_right = 64;
+
+ int result = channel_sound_load(&chan, &sound, true);
+
+ lily_assert_int_equal(mock_p_mutex_lock->n_calls, 1);
+ lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1);
+ lily_assert_int_equal(result, 0);
+
+ lily_assert_int_equal(chan.active, true);
+ lily_assert_int_equal(chan.paused, false);
+ lily_assert_int_equal(chan.volume, 127);
+ lily_assert_int_equal(chan.pan_left, 0);
+ lily_assert_int_equal(chan.pan_right, 64);
+
+ lily_assert_memory_equal(chan.sound.left, audio_left, sizeof(audio_left));
+ lily_assert_memory_equal(chan.sound.right, audio_right, sizeof(audio_right));
+ lily_assert_int_equal(chan.sound.mono, false);
+ lily_assert_int_equal(chan.pos, 0);
+}
+
+
+void test_channel_sound_fail()
+{
+ lily_mock_use(&mock_p_mutex_lock);
+ lily_mock_use(&mock_p_mutex_unlock);
+
+ float audio_left[] = { 0.2, 0.5, 1.0 };
+ float audio_right[] = { 1.0, 0.5, 0.2 };
+ struct mossrose_sound_t sound;
+ sound.left = audio_left;
+ sound.right = audio_right;
+ sound.mono = false;
+ sound.len = 3;
+
+ struct channel_t chan;
+ chan.active = true;
+ chan.paused = true;
+ chan.volume = 2;
+ chan.pan_left = 4;
+ chan.pan_right = 4;
+ chan.sound.left = NULL;
+ chan.sound.right = NULL;
+ chan.sound.mono = true;
+ chan.pos = 6;
+
+ int result = channel_sound_load(&chan, &sound, false);
+
+ lily_assert_int_equal(mock_p_mutex_lock->n_calls, 0);
+ lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 0);
+ lily_assert_int_equal(result, 1);
+
+ lily_assert_int_equal(chan.active, true);
+ lily_assert_int_equal(chan.paused, true);
+ lily_assert_int_equal(chan.volume, 2);
+ lily_assert_int_equal(chan.pan_left, 4);
+ lily_assert_int_equal(chan.pan_right, 4);
+
+ lily_assert_null(chan.sound.left);
+ lily_assert_null(chan.sound.right);
+ lily_assert_int_equal(chan.sound.mono, true);
+ lily_assert_int_equal(chan.pos, 6);
+}
+
+
/* get_next_sample tests */
void test_channel_get_next_sample_inactive()
{
@@ -471,6 +632,11 @@ void suite_channel()
lily_run_test(test_channel_set_volume);
lily_run_test(test_channel_set_pan);
+ lily_run_test(test_channel_sound_load);
+ lily_run_test(test_channel_sound_load_mono);
+ lily_run_test(test_channel_sound_load_preserve);
+ lily_run_test(test_channel_sound_fail);
+
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);
diff --git a/src/mossrose.c b/src/mossrose.c
index 40f4393..4babfd7 100644
--- a/src/mossrose.c
+++ b/src/mossrose.c
@@ -6,8 +6,25 @@
#include "channel.h"
-int mossrose_init(double sample_rate, int n_channels)
+struct mossrose_global_t {
+ PaStream *stream;
+ struct channel_t *channels;
+ int n_channels;
+} mossrose_global;
+
+
+int mossrose_init(double sample_rate, int n_channels, bool init_plibsys)
{
+ /* initialize channels */
+ mossrose_global.n_channels = n_channels;
+ mossrose_global.channels = malloc(n_channels * sizeof(struct channel_t));
+ if (mossrose_global.channels == NULL) {
+ fprintf("failed to allocate memory for %d channels\n", n_channels);
+ return 1;
+ }
+ for (int i=0; i<n_channels; i++)
+ channel_init(mossrose_global.channels + i);
+
};
@@ -16,6 +33,6 @@ int mossrose_play(struct mossrose_sound_t *sound, int channel)
}
-int mossrose_terminate(double sample_rate, int n_channels)
+int mossrose_terminate()
{
}
diff --git a/src/sound.c b/src/sound.c
index 36c1e5b..7296578 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -8,6 +8,7 @@ int sound_copy(struct mossrose_sound_t *dest, struct mossrose_sound_t *src)
{
sound_free_audio(dest);
dest->len = src->len;
+ dest->mono = src->mono;
/* left channel */
if (src->left != NULL) {