summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXANTRONIX Development2022-03-15 17:45:12 -0400
committerXANTRONIX Development2022-03-15 17:45:12 -0400
commit1bbe0659cfc4f1ea17e2c05869578959cc11fdfc (patch)
tree7a7e90e7fb3b31861810922bedb62de37fc078ab
parent61af5fa6dfe680e67f1c5b904667b1a9060e0804 (diff)
downloadxas-1bbe0659cfc4f1ea17e2c05869578959cc11fdfc.tar.gz
xas-1bbe0659cfc4f1ea17e2c05869578959cc11fdfc.tar.bz2
xas-1bbe0659cfc4f1ea17e2c05869578959cc11fdfc.zip
Implement polyphonic synth streams
Implement polyphonic synth streams by allowing one to create a new audio source passing multiple streams at once, wherein each synth is sampled and merged with the final stream output
-rw-r--r--include/xas/synth.h3
-rw-r--r--src/synth.c89
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;
+}