diff options
Diffstat (limited to 'src/mossrose.c')
-rw-r--r-- | src/mossrose.c | 110 |
1 files changed, 93 insertions, 17 deletions
diff --git a/src/mossrose.c b/src/mossrose.c index fdaa10c..02f063a 100644 --- a/src/mossrose.c +++ b/src/mossrose.c @@ -1,17 +1,67 @@ #include <stdio.h> +#include <stdlib.h> #include <portaudio.h> #include "mossrose.h" +#include "mossrose-mutex.h" +#include "mossrose-channel.h" -PaStream *stream; - +/* ~~~~~~~~~~~~~~~~ type definitions ~~~~~~~~~~~~~~~~ */ +/* audio output */ struct audio_output_t { float l; float r; }; + +/* ~~~~~~~~~~~~~~~~ globals ~~~~~~~~~~~~~~~~ */ + +struct mossrose_globals_t { + PaStream *stream; + struct mossrose_channel_t *channels; + int n_channels; +} mossrose_global; + + +struct audio_output_t build_sample() +{ + struct audio_output_t out; + out.l = 0; out.r = 0; + + /* loop variables */ + struct mossrose_channel_t *chan; + float chan_l, chan_r; + + for (int i=0; i<mossrose_global.n_channels; i++) { + chan = mossrose_global.channels + i; + if (mossrose_mutex_trylock(&(chan->mutex)) != 0) { + /* can't lock the mutex, this channel is being modified */ + printf("can't lock channel %d\n", i); + continue; + } + + if (chan->n_samples == 0) { + /* channel is not currently in use, skip */ + } + else { + if (mossrose_channel_advance(&chan_l, &chan_r, chan) != 0) + /* channel is done playing, reset */ + mossrose_channel_reset(chan); + else { + out.l += chan_l; + out.r += chan_r; + } + } + + mossrose_mutex_unlock(&(chan->mutex)); + } + + return out; +} + + static int callback( const void *input, void *output, @@ -19,39 +69,49 @@ static int callback( const PaStreamCallbackTimeInfo *time_info, void *userdata) { - static float left = 0; - static float right = 0; - struct audio_output_t *out = output; + struct audio_output_t sample; + for (int i=0; i<frame_count; i++) { - out[i].l = left; - out[i].r = right; - left += 0.01; - right += 0.03; - if (left > 1) left -= 2; - if (right > 1) right -= 2; + sample = build_sample(); + out[i].l = sample.l; + out[i].r = sample.r; } return 0; } -int mr_init(double sample_rate, int n_channels) +int mossrose_init(double sample_rate, int n_channels) { + /* initialize channels */ + mossrose_global.n_channels = n_channels; + mossrose_global.channels = malloc(n_channels * sizeof(struct mossrose_channel_t)); + if (mossrose_global.channels == NULL) { + fprintf(stderr, "failed to allocate memory for %d channels", n_channels); + return 1; + } + for (int i=0; i<n_channels; i++) { + mossrose_channel_init(mossrose_global.channels + i); + } + PaError err; + /* initialize portaudio */ err = Pa_Initialize(); if (err != paNoError) { fprintf(stderr, "failed to initialize PortAudio!\n"); return 1; } - err = Pa_OpenDefaultStream(&stream, 0, 2, paFloat32, sample_rate, 0, callback, NULL); + /* open 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 1; } - err = Pa_StartStream(stream); + /* start stream */ + err = Pa_StartStream(mossrose_global.stream); if (err != paNoError) { fprintf(stderr, "failed to start audio stream!\n"); return 1; @@ -61,10 +121,26 @@ int mr_init(double sample_rate, int n_channels) }; -int mr_terminate(double sample_rate, int n_channels) +int mossrose_play(float *left, float *right, size_t len, int channel) +{ + if (channel > 0) { + return mossrose_channel_set(mossrose_global.channels+channel, left, right, len, 1); + } + else { + struct mossrose_channel_t *chan; + for (int i=0; i<mossrose_global.n_channels; i++) { + chan = mossrose_global.channels + i; + if (mossrose_channel_set(chan, left, right, len, 0) == 0) return 0; + } + return 1; + } +} + + +int mossrose_terminate(double sample_rate, int n_channels) { - Pa_AbortStream(stream); - Pa_CloseStream(stream); + Pa_AbortStream(mossrose_global.stream); + Pa_CloseStream(mossrose_global.stream); Pa_Terminate(); return 0; } |