diff options
-rw-r--r-- | include/mossrose.h | 6 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/mossrose.c | 101 |
3 files changed, 106 insertions, 2 deletions
diff --git a/include/mossrose.h b/include/mossrose.h index 44d5477..81f71db 100644 --- a/include/mossrose.h +++ b/include/mossrose.h @@ -11,10 +11,14 @@ struct mossrose_sound_t { size_t len; }; -int mossrose_init(double sample_rate, int n_channels); +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); +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); +void mossrose_channel_resume(int channel); #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cca9610..0453c34 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ project(mossrose) target_sources(mossrose PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mossrose.c ${CMAKE_CURRENT_LIST_DIR}/channel.c + ${CMAKE_CURRENT_LIST_DIR}/sound.c ) diff --git a/src/mossrose.c b/src/mossrose.c index 4babfd7..fb017cd 100644 --- a/src/mossrose.c +++ b/src/mossrose.c @@ -13,26 +13,125 @@ struct mossrose_global_t { } mossrose_global; +static int callback( + const void *input, + void *output, + unsigned long frame_count, + const PaStreamCallbackTimeInfo* time_info, + PaStreamCallbackFlags status_flags, + void *user_data) +{ + float *out = output; + float *left, *right; + float l, r; + + for (int i=0; i<frame_count; i++) { + left = out + 2*i; + right = left + 1; + *left = 0; + *right = 0; + for (int j=0; j<mossrose_global.n_channels; j++) { + struct channel_t *chan = mossrose_global.channels + j; + channel_get_next_sample(&l, &r, chan); + *left += l; + *right += r; + } + } + return 0; +} + + int mossrose_init(double sample_rate, int n_channels, bool init_plibsys) { + /* optionally initialze plibsys */ + if (init_plibsys) + p_libsys_init(); + /* 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); + fprintf(stderr, "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); + PaError err; + /* initialize portaudio */ + err = Pa_Initialize(); + if (err != paNoError) { + fprintf(stderr, "failed to initialize portaudio\n"); + return 2; + } + + /* initialize stream */ + err = Pa_OpenDefaultStream(&(mossrose_global.stream), 0, 2, paFloat32, sample_rate, 0, callback, NULL); + if (err != paNoError) { + fprintf(stderr, "failed to open audio stream!\n"); + return 3; + } + + + /* start stream */ + err = Pa_StartStream(mossrose_global.stream); + if (err != paNoError) { + fprintf(stderr, "failed to start audio stream\n"); + return 4; + } + + return 0; }; int mossrose_play(struct mossrose_sound_t *sound, int channel) { + if (channel >= 0) { + /* play on specified channel */ + if (channel_sound_load(mossrose_global.channels + channel, sound, true) == 0) + return channel; + else + return -1; + } + else { + /* 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; + } + return -1; + } +} + + +void mossrose_channel_set_volume(int channel, float volume) { + struct channel_t *chan = mossrose_global.channels + channel; + channel_set_volume(chan, volume); +} + + +void mossrose_channel_set_pan(int channel, float left, float right) { + struct channel_t *chan = mossrose_global.channels + channel; + channel_set_pan(chan, left, right); +} + + +void mossrose_channel_pause(int channel) { + struct channel_t *chan = mossrose_global.channels + channel; + channel_pause(chan); +} + + +void mossrose_channel_resume(int channel) { + struct channel_t *chan = mossrose_global.channels + channel; + channel_resume(chan); } int mossrose_terminate() { + Pa_AbortStream(mossrose_global.stream); + Pa_CloseStream(mossrose_global.stream); + Pa_Terminate(); + return 0; } |