summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/test.c114
-rw-r--r--include/xas/audio.h2
-rw-r--r--include/xas/mixer.h7
-rw-r--r--include/xas/synth.h23
-rw-r--r--src/audio.c6
-rw-r--r--src/mixer.c38
-rw-r--r--src/synth.c60
7 files changed, 174 insertions, 76 deletions
diff --git a/examples/test.c b/examples/test.c
index e1da192..49937aa 100644
--- a/examples/test.c
+++ b/examples/test.c
@@ -8,6 +8,7 @@
#include <xas/synth.h>
#include <xas/audio.h>
+#include <xas/mixer.h>
#include <xas/riff.h>
#define SYNTH_STATUS_CLEAR 0
@@ -51,61 +52,112 @@ static int16_t sine_sample(xas_synth *synth, synth_sine *sine) {
return ret;
}
-static void sine_destroy(xas_synth *synth, synth_sine *sine) {
+static void sine_cleanup(xas_synth *synth, synth_sine *sine) {
return;
}
int main(int argc, char **argv) {
- xas_audio_stream *stream;
- xas_synth *synth;
+ xas_mixer *mixer;
- synth_sine sine = {
- .flags = SYNTH_STATUS_ON,
- .phase = 0.0f,
- .frequency = 220
+ xas_audio_stream *synth_l,
+ *synth_r,
+ *wave;
+
+ synth_sine sine_channels[2] = {
+ { SYNTH_STATUS_ON, 0.0f, 220 },
+ { SYNTH_STATUS_ON, 0.0f, 420 },
};
size_t sample_rate = 44100,
- duration_s = 60;
-
- int i;
+ duration_s = 60,
+ i;
if (argc != 2) {
usage(argc, argv, "No output file provided");
}
- if ((stream = xas_riff_file_open(argv[1],
- 2,
- sample_rate,
- 1,
- O_WRONLY | O_CREAT | O_TRUNC)) == NULL) {
+ if ((wave = xas_riff_file_open(argv[1],
+ XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ XAS_AUDIO_STREAM_STEREO,
+ O_WRONLY | O_CREAT | O_TRUNC)) == NULL) {
goto error_riff_file_open;
}
- if ((synth = xas_synth_new(sample_rate,
- (xas_synth_callback_sample)sine_sample,
- (xas_synth_callback_destroy)sine_destroy,
- &sine)) == NULL) {
- goto error_synth_new;
+ if ((synth_l = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ sample_rate,
+ (xas_synth_callback_sample)sine_sample,
+ (xas_synth_callback_cleanup)sine_cleanup,
+ &sine_channels[0])) == NULL) {
+ goto error_synth_new_l;
}
- for (i=0; i < duration_s * sample_rate; i++) {
- int16_t samples[1] = {
- xas_synth_sample(synth)
- };
+ if ((synth_r = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ sample_rate,
+ (xas_synth_callback_sample)sine_sample,
+ (xas_synth_callback_cleanup)sine_cleanup,
+ &sine_channels[1])) == NULL) {
+ goto error_synth_new_r;
+ }
+
+ if ((mixer = xas_mixer_new(XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ XAS_AUDIO_STREAM_STEREO,
+ sample_rate)) == NULL) {
+ goto error_mixer_new;
+ }
- xas_audio_stream_write(stream,
- samples,
- 1);
+ if (xas_mixer_input_add(mixer, synth_l, 0.3, -1.0) == NULL) {
+ goto error_mixer_input_add;
}
- xas_audio_stream_flush(stream);
- xas_audio_stream_destroy(stream);
+ if (xas_mixer_input_add(mixer, synth_r, 0.3, 1.0) == NULL) {
+ goto error_mixer_input_add;
+ }
+
+ printf("Good here\n");
+
+ for (i=0; i<duration_s; i++) {
+ int16_t *buf;
+ ssize_t readlen;
+
+ printf("one second\n");
+
+ if ((readlen = xas_audio_stream_read(mixer->output,
+ (void **)&buf,
+ sample_rate)) < 0) {
+ goto error_audio_stream_read;
+ }
+
+ if (xas_audio_stream_write(wave, buf, readlen) < 0) {
+ goto error_audio_stream_write;
+ }
+ }
+
+ xas_audio_stream_flush(wave);
+
+ xas_mixer_destroy(mixer);
+ xas_audio_stream_destroy(synth_r);
+ xas_audio_stream_destroy(synth_l);
+ xas_audio_stream_destroy(wave);
return EX_OK;
-error_synth_new:
- xas_audio_stream_destroy(stream);
+error_audio_stream_write:
+error_audio_stream_read:
+error_mixer_input_add:
+ xas_mixer_destroy(mixer);
+
+error_mixer_new:
+ xas_audio_stream_destroy(synth_r);
+
+error_synth_new_r:
+ xas_audio_stream_destroy(synth_l);
+
+error_synth_new_l:
+ xas_audio_stream_destroy(wave);
error_riff_file_open:
return EX_OSERR;
diff --git a/include/xas/audio.h b/include/xas/audio.h
index 76d1e68..9c40dd8 100644
--- a/include/xas/audio.h
+++ b/include/xas/audio.h
@@ -74,7 +74,7 @@ ssize_t xas_audio_stream_write(xas_audio_stream *stream,
size_t count);
ssize_t xas_audio_stream_read(xas_audio_stream *stream,
- void *samples,
+ void **samples,
size_t count);
int xas_audio_stream_flush(xas_audio_stream *stream);
diff --git a/include/xas/mixer.h b/include/xas/mixer.h
index ca60976..9fd77cb 100644
--- a/include/xas/mixer.h
+++ b/include/xas/mixer.h
@@ -25,10 +25,15 @@ typedef struct _xas_mixer {
size_t buffer_size;
} xas_mixer;
-xas_mixer *xas_mixer_new(xas_audio_stream *output);
+xas_mixer *xas_mixer_new(size_t sample_size,
+ size_t sample_rate,
+ size_t channels,
+ size_t buffer_size);
void xas_mixer_destroy(xas_mixer *mixer);
+xas_audio_stream *xas_mixer_output(xas_mixer *mixer);
+
xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer,
xas_audio_stream *stream,
float gain,
diff --git a/include/xas/synth.h b/include/xas/synth.h
index fe3ce9f..1d070aa 100644
--- a/include/xas/synth.h
+++ b/include/xas/synth.h
@@ -10,23 +10,22 @@ typedef struct _xas_synth xas_synth;
typedef int16_t (*xas_synth_callback_sample)(xas_synth *synth, void *ctx);
-typedef void (*xas_synth_callback_destroy)(xas_synth *synth, void *ctx);
+typedef void (*xas_synth_callback_cleanup)(xas_synth *synth, void *ctx);
struct _xas_synth {
- size_t sample_rate;
+ size_t sample_size,
+ sample_rate;
- xas_synth_callback_sample sample;
- xas_synth_callback_destroy destroy;
+ xas_synth_callback_sample sample;
+ xas_synth_callback_cleanup cleanup;
void *ctx;
};
-xas_synth *xas_synth_new(size_t sample_rate,
- xas_synth_callback_sample sample,
- xas_synth_callback_destroy destroy,
- void *ctx);
-
-void xas_synth_destroy(xas_synth *synth);
-
-int16_t xas_synth_sample(xas_synth *synth);
+xas_audio_stream *xas_synth_new(size_t sample_size,
+ size_t sample_rate,
+ size_t buffer_size,
+ xas_synth_callback_sample sample,
+ xas_synth_callback_cleanup cleanup,
+ void *ctx);
#endif /* _XAS_SYNTH_H */
diff --git a/src/audio.c b/src/audio.c
index 85f417d..d0a1e63 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -161,10 +161,12 @@ error_stream_flush:
}
ssize_t xas_audio_stream_read(xas_audio_stream *stream,
- void *samples,
+ void **samples,
size_t count) {
+ *samples = stream + 1;
+
return stream->fill(stream->ctx,
- samples,
+ *samples,
count,
stream);
}
diff --git a/src/mixer.c b/src/mixer.c
index 8007cae..3fc1ac9 100644
--- a/src/mixer.c
+++ b/src/mixer.c
@@ -34,11 +34,11 @@ static void mixer_apply_int16_t_stereo(int16_t *dest,
static ssize_t mixer_fill(xas_mixer *mixer,
void *samples,
- size_t count) {
- ssize_t ret = 0;
+ size_t count,
+ xas_audio_stream *output) {
+ ssize_t total = 0;
- xas_mixer_input *input = mixer->inputs,
- *output = mixer->output;
+ xas_mixer_input *input = mixer->inputs;
void (*mixer_apply)(int16_t *,
int16_t *,
@@ -54,29 +54,34 @@ static ssize_t mixer_fill(xas_mixer *mixer,
while (input) {
xas_mixer_input *next = input->next;
+ int16_t *buf;
ssize_t readlen;
if ((readlen = xas_audio_stream_read(input->stream,
- mixer->buf,
+ (void **)&buf,
count)) < 0) {
goto error_audio_read_stream;
}
- mixer_apply((int16_t *)mixer->buf,
- (int16_t *)(input + 1),
+ mixer_apply((int16_t *)(mixer->buf),
+ buf,
readlen,
input->bias_l,
input->bias_r);
- if (ret < readlen) {
- ret = readlen;
+ if (total < readlen) {
+ total = readlen;
}
input = next;
}
- return ret;
+ memcpy(samples,
+ mixer->buf,
+ total * output->sample_size * output->channels);
+
+ return total;
error_audio_read_stream:
return -1;
@@ -126,7 +131,7 @@ void xas_mixer_destroy(xas_mixer *mixer) {
xas_mixer_input *input = mixer->inputs;
while (input) {
- xas_mixer_input *next = input;
+ xas_mixer_input *next = input->next;
free(input);
@@ -138,6 +143,10 @@ void xas_mixer_destroy(xas_mixer *mixer) {
free(mixer);
}
+xas_audio_stream *xas_mixer_output(xas_mixer *mixer) {
+ return mixer->output;
+}
+
static inline void input_set_pan(xas_mixer_input *input, float pan) {
float angle,
term,
@@ -165,7 +174,6 @@ xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer,
if (stream->sample_size != mixer->output->sample_size
|| stream->sample_rate != mixer->output->sample_rate
- || stream->channels != mixer->output->channels
|| stream->buffer_size != mixer->buffer_size) {
errno = EINVAL;
@@ -178,12 +186,16 @@ xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer,
input->stream = stream;
input->gain = gain;
+ input->next = NULL;
input_set_pan(input, pan);
if (mixer->inputs == NULL) {
mixer->inputs = input;
- mixer->last = NULL;
+ mixer->last = input;
+ } else {
+ mixer->last->next = input;
+ mixer->last = input;
}
return input;
diff --git a/src/synth.c b/src/synth.c
index 9b18daf..a482875 100644
--- a/src/synth.c
+++ b/src/synth.c
@@ -2,33 +2,61 @@
#include <xas/synth.h>
-xas_synth *xas_synth_new(size_t sample_rate,
- xas_synth_callback_sample sample,
- xas_synth_callback_destroy destroy,
- void *ctx) {
+static ssize_t synth_fill(xas_synth *synth,
+ int16_t *samples,
+ size_t count,
+ xas_audio_stream *stream) {
+ size_t i;
+
+ for (i=0; i<count; i++) {
+ samples[i] = synth->sample(synth, synth->ctx);
+ }
+
+ return count;
+}
+
+static void synth_cleanup(xas_synth *synth, xas_audio_stream *stream) {
+ if (synth->cleanup) {
+ synth->cleanup(synth, synth->ctx);
+ }
+
+ free(synth);
+}
+
+xas_audio_stream *xas_synth_new(size_t sample_size,
+ size_t sample_rate,
+ size_t buffer_size,
+ xas_synth_callback_sample sample,
+ xas_synth_callback_cleanup cleanup,
+ void *ctx) {
+ xas_audio_stream *stream;
xas_synth *synth;
if ((synth = malloc(sizeof(*synth))) == NULL) {
goto error_malloc_synth;
}
+ synth->sample_size = sample_size;
synth->sample_rate = sample_rate;
synth->sample = sample;
- synth->destroy = destroy;
+ synth->cleanup = cleanup;
synth->ctx = ctx;
- return synth;
+ if ((stream = xas_audio_stream_new_source((xas_audio_fill)synth_fill,
+ (xas_audio_cleanup)synth_cleanup,
+ synth,
+ sample_size,
+ sample_rate,
+ XAS_AUDIO_STREAM_MONO,
+ buffer_size)) == NULL) {
+ goto error_audio_stream_new_source;
+ }
-error_malloc_synth:
- return NULL;
-}
+ return stream;
-void xas_synth_destroy(xas_synth *synth) {
- if (synth->destroy) {
- synth->destroy(synth, synth->ctx);
- }
-}
+error_audio_stream_new_source:
+ free(synth);
-int16_t xas_synth_sample(xas_synth *synth) {
- return synth->sample(synth, synth->ctx);
+error_malloc_synth:
+ return NULL;
}