diff options
author | sanine <sanine.not@pm.me> | 2022-09-03 21:32:25 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-09-03 21:32:25 -0500 |
commit | 2cf000fb7cbe653c2e96e0b3b8f3c1425401d3fc (patch) | |
tree | e172ef67b253d1eaa0fb22186b5901edd4de793a | |
parent | a416cfb6881b8ff99c29ba87c1d940d6143e44b1 (diff) |
add looping
-rw-r--r-- | examples/CMakeLists.txt | 5 | ||||
-rw-r--r-- | examples/example.c | 6 | ||||
-rw-r--r-- | examples/loop.c | 40 | ||||
-rw-r--r-- | examples/panning.c | 2 | ||||
-rw-r--r-- | include/mossrose.h | 2 | ||||
-rw-r--r-- | src/channel.c | 10 | ||||
-rw-r--r-- | src/channel.h | 3 | ||||
-rw-r--r-- | src/channel.test.c | 56 | ||||
-rw-r--r-- | src/mossrose.c | 7 |
9 files changed, 108 insertions, 23 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 46e02d4..7fe2030 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,3 +8,8 @@ add_dependencies(examples example) add_executable(panning ${CMAKE_CURRENT_LIST_DIR}/panning.c) target_link_libraries(panning mossrose) add_dependencies(examples panning) + + +add_executable(loop ${CMAKE_CURRENT_LIST_DIR}/loop.c) +target_link_libraries(loop mossrose) +add_dependencies(examples loop) diff --git a/examples/example.c b/examples/example.c index 5e65d82..eefc41d 100644 --- a/examples/example.c +++ b/examples/example.c @@ -35,17 +35,17 @@ int main() Pa_Sleep(500); printf("play 1\n"); - mossrose_play(&sound_512, -1); + mossrose_play(&sound_512, -1, 1); printf("wait\n"); Pa_Sleep(1000); printf("play 2\n"); - mossrose_play(&sound_440, -1); + mossrose_play(&sound_440, -1, 1); printf("wait\n"); Pa_Sleep(500); printf("play 3\n"); - mossrose_play(&sound_512, -1); + mossrose_play(&sound_512, -1, 1); printf("wait\n"); Pa_Sleep(1000); diff --git a/examples/loop.c b/examples/loop.c new file mode 100644 index 0000000..1be04a9 --- /dev/null +++ b/examples/loop.c @@ -0,0 +1,40 @@ +#include <stdio.h> +#include <math.h> +#include <mossrose.h> +#include <portaudio.h> + +#define PI 3.14159 + + +#define SAMPLE_RATE 44100 +#define N_CHANNELS 8 + +float f(float t) +{ + const int f0 = 440; + const int f1 = 880; + return ( t*f1 ) + ( (1-t)*f0 ); +} + +int main() +{ + float data[SAMPLE_RATE]; + for (long i=0; i<SAMPLE_RATE; i++) { + float time = ((float)i)/SAMPLE_RATE; + data[i] = sin(2*PI*f(time)*time); + } + + struct mossrose_sound_t sound = { + .left = data, .right = NULL, .mono = true, .len = SAMPLE_RATE + }; + + int err = mossrose_init(SAMPLE_RATE, N_CHANNELS, true); + if (err != 0) + fprintf(stderr, "FAILED TO INITIALIZE MOSSROSE\n"); + + int chan = mossrose_play(&sound, -1, 5); + Pa_Sleep(5000); + + mossrose_terminate(); + return 0; +} diff --git a/examples/panning.c b/examples/panning.c index 485833a..b63727b 100644 --- a/examples/panning.c +++ b/examples/panning.c @@ -28,7 +28,7 @@ int main() Pa_Sleep(500); - int chan = mossrose_play(&sound, -1); + int chan = mossrose_play(&sound, -1, 1); for (int i=0; i<8000; i++) { float time = ((float)i)/1000; diff --git a/include/mossrose.h b/include/mossrose.h index 81f71db..72f7b99 100644 --- a/include/mossrose.h +++ b/include/mossrose.h @@ -15,7 +15,7 @@ int mossrose_init(double sample_rate, int n_channels, bool init_plibsys); int mossrose_terminate(); -int mossrose_play(struct mossrose_sound_t *sound, int channel); +int mossrose_play(struct mossrose_sound_t *sound, int channel, int loops); void mossrose_channel_set_volume(int channel, float volume); void mossrose_channel_set_pan(int channel, float left, float right); void mossrose_channel_pause(int channel); diff --git a/src/channel.c b/src/channel.c index 1d0b63b..8615265 100644 --- a/src/channel.c +++ b/src/channel.c @@ -25,7 +25,12 @@ void channel_init(struct channel_t *chan) void channel_reset(struct channel_t *chan) { - p_atomic_int_set(&(chan->shared.active), false); + chan->pos = 0; + int loops = channel_atomic_get(chan->shared.loops); + if (loops) { + if (p_atomic_int_dec_and_test(&(chan->shared.loops))) + channel_atomic_set(chan->shared.active, false); + } } @@ -63,7 +68,7 @@ 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) +int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, bool force, int loops) { if (!force && channel_atomic_get(chan->shared.active)) /* active, fail! */ @@ -74,6 +79,7 @@ int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, b chan->pos = 0; p_atomic_int_set(&(chan->shared.paused), false); + p_atomic_int_set(&(chan->shared.loops), loops); if (!force) { /* overwrite channel settings */ diff --git a/src/channel.h b/src/channel.h index ae9c24b..5be42a2 100644 --- a/src/channel.h +++ b/src/channel.h @@ -13,6 +13,7 @@ struct channel_shared_t { volatile pint volume; /* 0-255 */ volatile pint pan_left; /* -255-255 */ volatile pint pan_right; /* -255-255 */ + volatile pint loops; }; @@ -34,7 +35,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); +int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, bool force, int loops); 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 4591b43..067879f 100644 --- a/src/channel.test.c +++ b/src/channel.test.c @@ -71,15 +71,11 @@ void test_channel_init() } -void test_channel_reset() +void test_channel_reset_last_loop() { struct channel_t chan; - chan.pos = 255; chan.shared.active = true; - chan.shared.paused = true; - chan.shared.volume = 5; - chan.shared.pan_left = 30; - chan.shared.pan_right = 30; + chan.shared.loops = 1; channel_reset(&chan); @@ -87,6 +83,36 @@ void test_channel_reset() } +void test_channel_reset_penultimate_loop() +{ + struct channel_t chan; + chan.shared.active = true; + chan.shared.loops = 2; + chan.pos = 98; + + channel_reset(&chan); + + lily_assert_int_equal(chan.shared.active, true); + lily_assert_int_equal(chan.shared.loops, 1); + lily_assert_int_equal(chan.pos, 0); +} + + +void test_channel_reset_infinite_loop() +{ + struct channel_t chan; + chan.shared.active = true; + chan.shared.loops = 0; + chan.pos = 17; + + channel_reset(&chan); + + lily_assert_int_equal(chan.shared.active, true); + lily_assert_int_equal(chan.shared.loops, 0); + lily_assert_int_equal(chan.pos, 0); +} + + void test_channel_pause() { struct channel_t chan; @@ -180,7 +206,7 @@ void test_channel_sound_load() chan.sound.right = NULL; chan.pos = 5; - int result = channel_sound_load(&chan, &sound, false); + int result = channel_sound_load(&chan, &sound, false, 1); lily_assert_int_equal(mock_p_mutex_lock->n_calls, 1); lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1); @@ -216,7 +242,7 @@ void test_channel_sound_load_mono() chan.sound.left = NULL; chan.sound.right = NULL; - int result = channel_sound_load(&chan, &sound, false); + int result = channel_sound_load(&chan, &sound, false, 1); lily_assert_int_equal(mock_p_mutex_lock->n_calls, 1); lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1); @@ -256,7 +282,7 @@ void test_channel_sound_load_preserve() chan.shared.pan_left = 0; chan.shared.pan_right = 64; - int result = channel_sound_load(&chan, &sound, true); + int result = channel_sound_load(&chan, &sound, true, 1); lily_assert_int_equal(mock_p_mutex_lock->n_calls, 1); lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 1); @@ -299,7 +325,7 @@ void test_channel_sound_fail() chan.sound.mono = true; chan.pos = 6; - int result = channel_sound_load(&chan, &sound, false); + int result = channel_sound_load(&chan, &sound, false, 1); lily_assert_int_equal(mock_p_mutex_lock->n_calls, 0); lily_assert_int_equal(mock_p_mutex_unlock->n_calls, 0); @@ -391,6 +417,7 @@ void test_channel_get_next_sample_normal() struct channel_t chan; chan.shared.active = true; chan.shared.paused = false; + chan.shared.loops = 1; chan.shared.volume = 255; chan.shared.pan_left = -128; chan.shared.pan_right = 128; @@ -441,6 +468,7 @@ void test_channel_get_next_sample_volume_0() struct channel_t chan; chan.shared.active = true; chan.shared.paused = false; + chan.shared.loops = 1; chan.shared.volume = 0; chan.shared.pan_left = -128; chan.shared.pan_right = 128; @@ -491,6 +519,7 @@ void test_channel_get_next_sample_mono() struct channel_t chan; chan.shared.active = true; chan.shared.paused = false; + chan.shared.loops = 1; chan.shared.volume = 255; chan.shared.pan_left = 0; chan.shared.pan_right = 128; @@ -542,6 +571,7 @@ void test_channel_get_next_sample_mono_panned() struct channel_t chan; chan.shared.active = true; chan.shared.paused = false; + chan.shared.loops = 1; chan.shared.volume = 255; chan.shared.pan_left = -128; chan.shared.pan_right = 128; @@ -591,6 +621,7 @@ void test_channel_get_next_sample_panned() struct channel_t chan; chan.shared.active = true; chan.shared.paused = false; + chan.shared.loops = 1; chan.shared.volume = 255; chan.shared.pan_left = 128; chan.shared.pan_right = 0; @@ -638,12 +669,15 @@ void test_channel_get_next_sample_panned() void suite_channel() { lily_run_test(test_channel_init); - lily_run_test(test_channel_reset); lily_run_test(test_channel_pause); lily_run_test(test_channel_resume); lily_run_test(test_channel_set_volume); lily_run_test(test_channel_set_pan); + lily_run_test(test_channel_reset_last_loop); + lily_run_test(test_channel_reset_penultimate_loop); + lily_run_test(test_channel_reset_infinite_loop); + lily_run_test(test_channel_sound_load); lily_run_test(test_channel_sound_load_mono); lily_run_test(test_channel_sound_load_preserve); diff --git a/src/mossrose.c b/src/mossrose.c index 04770f5..cd1b98d 100644 --- a/src/mossrose.c +++ b/src/mossrose.c @@ -21,7 +21,6 @@ static int callback( PaStreamCallbackFlags status_flags, void *user_data) { - printf("frame count: %d\n", frame_count); float *out = output; float *left, *right; float l, r; @@ -88,11 +87,11 @@ int mossrose_init(double sample_rate, int n_channels, bool init_plibsys) }; -int mossrose_play(struct mossrose_sound_t *sound, int channel) +int mossrose_play(struct mossrose_sound_t *sound, int channel, int loops) { if (channel >= 0) { /* play on specified channel */ - if (channel_sound_load(mossrose_global.channels + channel, sound, true) == 0) + if (channel_sound_load(mossrose_global.channels + channel, sound, true, loops) == 0) return channel; else return -1; @@ -101,7 +100,7 @@ int mossrose_play(struct mossrose_sound_t *sound, int channel) /* play on first available channel */ for (int i=0; i<mossrose_global.n_channels; i++) { struct channel_t *chan = mossrose_global.channels + i; - if (channel_sound_load(chan, sound, false) == 0) return i; + if (channel_sound_load(chan, sound, false, loops) == 0) return i; } return -1; } |