diff options
-rw-r--r-- | include/xas/synth.h | 3 | ||||
-rw-r--r-- | src/synth.c | 89 |
2 files changed, 92 insertions, 0 deletions
diff --git a/include/xas/synth.h b/include/xas/synth.h index 7ec4af4..e513f2a 100644 --- a/include/xas/synth.h +++ b/include/xas/synth.h @@ -65,4 +65,7 @@ void xas_synth_stop(xas_synth *synth); xas_audio_stream *xas_synth_stream_new(xas_synth *synth); +xas_audio_stream *xas_synth_stream_new_poly(xas_synth **synths, + size_t count); + #endif /* _XAS_SYNTH_H */ 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; +} |