summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-31 14:34:22 -0500
committersanine <sanine.not@pm.me>2022-08-31 14:34:22 -0500
commit48e6520f6517f196a0a8f39bf86159075ad44c6b (patch)
tree505134e8bd48b740feb2b952dae7945cfedfd76f /src
parent54351358e17b36212872313f4a820d59f14fdf12 (diff)
finish basic implementation
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/mossrose.c101
2 files changed, 101 insertions, 1 deletions
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;
}