diff options
| -rw-r--r-- | src/channel.c | 36 | ||||
| -rw-r--r-- | src/channel.h | 1 | ||||
| -rw-r--r-- | src/channel.test.c | 172 | ||||
| -rw-r--r-- | src/mossrose.c | 21 | ||||
| -rw-r--r-- | src/sound.c | 1 | 
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) {  | 
