summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile2
-rw-r--r--examples/spatial.c166
2 files changed, 167 insertions, 1 deletions
diff --git a/examples/Makefile b/examples/Makefile
index 537d103..5604297 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -7,7 +7,7 @@ INCLUDE_PATH = ../include
CFLAGS += -I$(INCLUDE_PATH)
LDFLAGS += -L../src -lxas -lm
-EXAMPLES = test open say
+EXAMPLES = test open say spatial
all: $(EXAMPLES)
diff --git a/examples/spatial.c b/examples/spatial.c
new file mode 100644
index 0000000..9985ffe
--- /dev/null
+++ b/examples/spatial.c
@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sysexits.h>
+#include <fcntl.h>
+#include <math.h>
+
+#include <xas/spatial.h>
+#include <xas/synth.h>
+#include <xas/audio.h>
+#include <xas/riff.h>
+
+#define SYNTH_STATUS_CLEAR 0
+#define SYNTH_STATUS_ON (1 << 0)
+
+typedef struct _synth_sine {
+ int flags;
+ float phase;
+
+ size_t frequency;
+} synth_sine;
+
+static void usage(int argc, char **argv, const char *message, ...) {
+ va_list args;
+
+ va_start(args, message);
+
+ if (message) {
+ vfprintf(stderr, message, args);
+ fputc('\n', stderr);
+ }
+
+ va_end(args);
+
+ fprintf(stderr, "usage: %s output.wav\n", argv[0]);
+
+ exit(EX_USAGE);
+}
+
+static int16_t sine_sample(xas_synth *synth, synth_sine *sine) {
+ int16_t ret;
+ static float tau = 2.0f * M_PI;
+
+ if (sine->flags & SYNTH_STATUS_ON) {
+ ret = (int16_t)roundf((INT16_MAX >> 2) * sinf(sine->phase));
+
+ sine->phase += tau / (synth->format.sample_rate / sine->frequency);
+
+ if (sine->phase > tau) {
+ sine->phase -= tau;
+ }
+ } else {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static void sine_cleanup(xas_synth *synth, synth_sine *sine) {
+ return;
+}
+
+int main(int argc, char **argv) {
+ xas_spatial_scene *scene;
+
+ xas_audio_stream *synth,
+ *output,
+ *wave;
+
+ synth_sine sine_channels[2] = {
+ { SYNTH_STATUS_ON, 0.0f, 220 },
+ { SYNTH_STATUS_ON, 0.0f, 420 },
+ };
+
+ xas_audio_format format = {
+ .channels = XAS_AUDIO_STEREO,
+ .sample_size = XAS_AUDIO_PCM_16_BIT,
+ .sample_rate = 44100
+ };
+
+ size_t buffer_size = 4096,
+ duration_s = 60,
+ i;
+
+ xas_spatial_coord speakers[2] = {
+ { -0.09, 0.0, 0.0 },
+ { 0.09, 0.0, 0.0 }
+ };
+
+ if (argc != 2) {
+ usage(argc, argv, "No output file provided");
+ }
+
+ if ((wave = xas_riff_new_file(argv[1],
+ format,
+ O_WRONLY | O_CREAT | O_TRUNC)) == NULL) {
+ goto error_riff_new_file;
+ }
+
+ if ((synth = xas_synth_new((xas_synth_callback_sample)sine_sample,
+ (xas_synth_callback_cleanup)sine_cleanup,
+ format,
+ buffer_size,
+ &sine_channels[0])) == NULL) {
+ goto error_synth_new;
+ }
+
+ if ((scene = xas_spatial_scene_new(format,
+ speakers[0],
+ speakers[1])) == NULL) {
+ goto error_spatial_scene_new;
+ }
+
+ if ((output = xas_spatial_scene_new_stream(scene,
+ buffer_size)) == NULL) {
+ goto error_spatial_scene_new_stream;
+ }
+
+ if (xas_spatial_scene_add_object(scene,
+ (xas_spatial_coord){ 0.0, 0.0, 20.0 },
+ synth) == NULL) {
+ goto error_spatial_scene_add_object;
+ }
+
+ for (i=0; i<duration_s; i++) {
+ void *buf;
+ ssize_t readlen;
+
+ if ((readlen = xas_audio_stream_read(output,
+ &buf,
+ buffer_size)) < 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_audio_stream_destroy(output);
+ xas_spatial_scene_destroy(scene);
+ xas_audio_stream_destroy(synth);
+ xas_audio_stream_destroy(wave);
+
+ return EX_OK;
+
+error_audio_stream_read:
+error_audio_stream_write:
+error_spatial_scene_add_object:
+ xas_audio_stream_destroy(output);
+
+error_spatial_scene_new_stream:
+ xas_spatial_scene_destroy(scene);
+
+error_spatial_scene_new:
+ xas_audio_stream_destroy(synth);
+
+error_synth_new:
+ xas_audio_stream_destroy(wave);
+
+error_riff_new_file:
+ return EX_OSERR;
+}