diff options
author | sanine <sanine.not@pm.me> | 2022-08-31 14:34:22 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-08-31 14:34:22 -0500 |
commit | 48e6520f6517f196a0a8f39bf86159075ad44c6b (patch) | |
tree | 505134e8bd48b740feb2b952dae7945cfedfd76f /src/mossrose.c | |
parent | 54351358e17b36212872313f4a820d59f14fdf12 (diff) |
finish basic implementation
Diffstat (limited to 'src/mossrose.c')
-rw-r--r-- | src/mossrose.c | 101 |
1 files changed, 100 insertions, 1 deletions
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; } |