summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/say.c111
1 files changed, 95 insertions, 16 deletions
diff --git a/examples/say.c b/examples/say.c
index 92d2b19..d72c7ff 100644
--- a/examples/say.c
+++ b/examples/say.c
@@ -9,8 +9,19 @@
#include <xas/audio.h>
#include <xas/mixer.h>
#include <xas/riff.h>
+#include <xas/synth.h>
#include <xas/vox.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;
@@ -28,31 +39,53 @@ static void usage(int argc, char **argv, const char *message, ...) {
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->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) {
+ synth_sine sine_channels[2] = {
+ { SYNTH_STATUS_ON, 0.0f, 220 },
+ { SYNTH_STATUS_ON, 0.0f, 420 },
+ };
+
xas_mixer *mixer;
xas_audio_stream *input,
+ *synth_l,
+ *synth_r,
*output;
xas_vox *vox;
- size_t sample_rate = 44100,
- buffer_size = 4096,
- duration_s = 60,
+ size_t sample_rate = 44100,
+ buffer_size = 735,
+ duration_frames = 3600,
i;
if (argc != 2) {
usage(argc, argv, "No output file provided");
}
- if ((output = xas_riff_new_file(argv[1],
- XAS_AUDIO_STREAM_PCM_16_BIT,
- sample_rate,
- XAS_AUDIO_STREAM_STEREO,
- O_WRONLY | O_CREAT | O_TRUNC)) == NULL) {
- goto error_riff_new_file;
- }
-
if ((vox = xas_vox_new("/usr/bin/text2wave",
XAS_AUDIO_STREAM_PCM_16_BIT,
sample_rate,
@@ -61,10 +94,36 @@ int main(int argc, char **argv) {
goto error_vox_new;
}
+ if ((output = xas_riff_new_file(argv[1],
+ XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ XAS_AUDIO_STREAM_STEREO,
+ O_WRONLY | O_CREAT | O_TRUNC)) == NULL) {
+ goto error_riff_new_file;
+ }
+
if ((input = xas_vox_stream_new(vox)) == NULL) {
goto error_vox_stream_new;
}
+ if ((synth_l = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ buffer_size,
+ (xas_synth_callback_sample)sine_sample,
+ (xas_synth_callback_cleanup)sine_cleanup,
+ &sine_channels[0])) == NULL) {
+ goto error_synth_new_l;
+ }
+
+ if ((synth_r = xas_synth_new(XAS_AUDIO_STREAM_PCM_16_BIT,
+ sample_rate,
+ buffer_size,
+ (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,
@@ -72,13 +131,23 @@ int main(int argc, char **argv) {
goto error_mixer_new;
}
- if (xas_mixer_input_add(mixer, input, 1.0, -1.0) == NULL) {
+ if (xas_mixer_input_add(mixer, input, 1.0, 0.0) == NULL) {
+ goto error_mixer_input_add;
+ }
+
+ if (xas_mixer_input_add(mixer, synth_l, 0.5, -1.0) == NULL) {
+ goto error_mixer_input_add;
+ }
+
+ if (xas_mixer_input_add(mixer, synth_r, 0.5, 1.0) == NULL) {
goto error_mixer_input_add;
}
xas_vox_say(vox, "I want to eat your soul. You don't understand. I really want to eat your soul.\n");
- for (i=0; i<duration_s; i++) {
+ xas_vox_generate(vox);
+
+ for (i=0; i<duration_frames; i++) {
void *buf;
ssize_t readlen;
@@ -96,9 +165,13 @@ int main(int argc, char **argv) {
xas_audio_stream_flush(output);
xas_mixer_destroy(mixer);
+ xas_audio_stream_destroy(synth_r);
+ xas_audio_stream_destroy(synth_l);
xas_audio_stream_destroy(input);
xas_audio_stream_destroy(output);
+ xas_vox_destroy(vox);
+
return EX_OK;
error_audio_stream_write:
@@ -107,14 +180,20 @@ 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(input);
error_vox_stream_new:
- xas_vox_destroy(vox);
-
-error_vox_new:
xas_audio_stream_destroy(output);
error_riff_new_file:
+ xas_vox_destroy(vox);
+
+error_vox_new:
return EX_OSERR;
}