summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/synth.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/synth.c b/src/synth.c
index 596539f..56bbe5b 100644
--- a/src/synth.c
+++ b/src/synth.c
@@ -4,6 +4,11 @@
#include <xas/synth.h>
+struct poly {
+ xas_synth **synths;
+ size_t count;
+};
+
static int16_t sample_sine(xas_synth *synth) {
int16_t ret;
static float tau = 2.0f * M_PI;
@@ -220,3 +225,87 @@ xas_audio_stream *xas_synth_stream_new(xas_synth *synth) {
synth->buffer_size,
synth);
}
+
+static ssize_t poly_fill(struct poly *poly, int16_t *samples, size_t count) {
+ size_t s;
+
+ for (s=0; s<count; s++) {
+ samples[s] = 0;
+
+ size_t i;
+
+ for (i=0; i<poly->count; i++) {
+ xas_synth *synth = poly->synths[i];
+
+ samples[s] += synth->sample(synth);
+ }
+ }
+
+ return count;
+}
+
+static void poly_cleanup(struct poly *poly) {
+ free(poly->synths);
+ free(poly);
+}
+
+xas_audio_stream *xas_synth_stream_new_poly(xas_synth **synths,
+ size_t count) {
+ struct poly *poly;
+ size_t i;
+
+ xas_audio_format format;
+ size_t buffer_size;
+
+ if (count == 0) {
+ errno = EINVAL;
+
+ goto error_invalid_count;
+ }
+
+ format = synths[0]->format;
+ buffer_size = synths[0]->buffer_size;
+
+ if ((poly = malloc(sizeof(*poly))) == NULL) {
+ goto error_malloc_poly;
+ }
+
+ if ((poly->synths = malloc(count * sizeof(xas_synth *))) == NULL) {
+ goto error_malloc_synths;
+ }
+
+ for (i=0; i<count; i++) {
+ if (!xas_audio_format_eq(synths[i]->format, format)) {
+ errno = EINVAL;
+
+ goto error_invalid_format;
+ }
+
+ if (synths[i]->buffer_size != buffer_size) {
+ errno = EINVAL;
+
+ goto error_invalid_buffer_size;
+ }
+
+ poly->synths[i] = synths[i];
+ }
+
+ poly->count = count;
+
+ return xas_audio_stream_new_source((xas_audio_fill)poly_fill,
+ (xas_audio_cleanup)poly_cleanup,
+ format,
+ buffer_size,
+ poly);
+
+error_invalid_buffer_size:
+error_invalid_format:
+ free(poly->synths);
+
+error_malloc_synths:
+ free(poly);
+
+error_malloc_poly:
+error_invalid_count:
+ return NULL;
+}