diff options
-rw-r--r-- | include/xas/script.h | 28 | ||||
-rw-r--r-- | src/script.c | 139 |
2 files changed, 142 insertions, 25 deletions
diff --git a/include/xas/script.h b/include/xas/script.h index 102d421..5f0af87 100644 --- a/include/xas/script.h +++ b/include/xas/script.h @@ -5,9 +5,6 @@ #include <sys/time.h> #include <xas/audio.h> -#include <xas/vox.h> -#include <xas/bank.h> -#include <xas/synth.h> #include <xas/spatial.h> enum xas_script_event_type { @@ -15,14 +12,22 @@ enum xas_script_event_type { XAS_SCRIPT_EVENT_ON, XAS_SCRIPT_EVENT_SET_POSITION, XAS_SCRIPT_EVENT_SET_GAIN, - XAS_SCRIPT_EVENT_SET_BANK_INDEX, - XAS_SCRIPT_EVENT_SET_FREQUENCY + XAS_SCRIPT_EVENT_SET_FREQUENCY, + XAS_SCRIPT_EVENT_SET_BANK_INDEX +}; + +enum xas_script_object_type { + XAS_SCRIPT_OBJECT_ANY, + XAS_SCRIPT_OBJECT_SYNTH, + XAS_SCRIPT_OBJECT_VOX, + XAS_SCRIPT_OBJECT_BANK_PLAYER }; typedef struct _xas_script_event xas_script_event; struct _xas_script_event { enum xas_script_event_type type; + enum xas_script_object_type objtype; xas_spatial_object *object; @@ -43,10 +48,7 @@ typedef struct _xas_script { xas_script_event *first; - struct timeval timestamp; - - size_t buffer_size, - current_index; + size_t buffer_size; } xas_script; xas_script *xas_script_new(xas_spatial_scene *scene, size_t buffer_size); @@ -61,22 +63,22 @@ int xas_script_add_event_on(xas_script *script, xas_spatial_object *object, struct timeval timestamp); -int xas_script_add_position_set(xas_script *script, +int xas_script_add_set_position(xas_script *script, xas_spatial_object *object, struct timeval timestamp, xas_spatial_coord point); -int xas_script_add_gain_set(xas_script *script, +int xas_script_add_set_gain(xas_script *script, xas_spatial_object *object, struct timeval timestamp, float gain); -int xas_script_add_bank_set(xas_script *script, +int xas_script_add_set_bank(xas_script *script, xas_spatial_object *object, struct timeval timestamp, size_t index); -int xas_script_add_frequency_set(xas_script *script, +int xas_script_add_set_frequency(xas_script *script, xas_spatial_object *object, struct timeval timestamp, size_t frequency); diff --git a/src/script.c b/src/script.c index 8c58f7f..b983577 100644 --- a/src/script.c +++ b/src/script.c @@ -1,6 +1,9 @@ #include <stdlib.h> #include <string.h> +#include <xas/object.h> +#include <xas/bank.h> +#include <xas/synth.h> #include <xas/script.h> xas_script *xas_script_new(xas_spatial_scene *scene, size_t buffer_size) { @@ -10,13 +13,9 @@ xas_script *xas_script_new(xas_spatial_scene *scene, size_t buffer_size) { goto error_malloc_script; } - script->scene = scene; - script->first = NULL; - - timerclear(&script->timestamp); - - script->buffer_size = buffer_size; - script->current_index = 0; + script->scene = scene; + script->first = NULL; + script->buffer_size = buffer_size; return script; @@ -78,6 +77,7 @@ int xas_script_add_event_off(xas_script *script, } ev->type = XAS_SCRIPT_EVENT_OFF; + ev->objtype = XAS_SCRIPT_OBJECT_ANY; ev->object = object; ev->timestamp = timestamp; ev->next = NULL; @@ -100,6 +100,7 @@ int xas_script_add_event_on(xas_script *script, } ev->type = XAS_SCRIPT_EVENT_ON; + ev->objtype = XAS_SCRIPT_OBJECT_ANY; ev->object = object; ev->timestamp = timestamp; ev->next = NULL; @@ -112,7 +113,7 @@ error_malloc_ev: return -1; } -int xas_script_add_position_set(xas_script *script, +int xas_script_add_set_position(xas_script *script, xas_spatial_object *object, struct timeval timestamp, xas_spatial_coord point) { @@ -123,6 +124,7 @@ int xas_script_add_position_set(xas_script *script, } ev->type = XAS_SCRIPT_EVENT_SET_POSITION; + ev->objtype = XAS_SCRIPT_OBJECT_ANY; ev->object = object; ev->timestamp = timestamp; ev->point = point; @@ -136,7 +138,7 @@ error_malloc_ev: return -1; } -int xas_script_add_gain_set(xas_script *script, +int xas_script_add_set_gain(xas_script *script, xas_spatial_object *object, struct timeval timestamp, float gain) { @@ -147,6 +149,7 @@ int xas_script_add_gain_set(xas_script *script, } ev->type = XAS_SCRIPT_EVENT_ON; + ev->objtype = XAS_SCRIPT_OBJECT_ANY; ev->object = object; ev->timestamp = timestamp; ev->gain = gain; @@ -160,7 +163,7 @@ error_malloc_ev: return -1; } -int xas_script_add_bank_set(xas_script *script, +int xas_script_add_set_bank(xas_script *script, xas_spatial_object *object, struct timeval timestamp, size_t index) { @@ -171,6 +174,7 @@ int xas_script_add_bank_set(xas_script *script, } ev->type = XAS_SCRIPT_EVENT_SET_BANK_INDEX; + ev->objtype = XAS_SCRIPT_OBJECT_BANK_PLAYER; ev->object = object; ev->timestamp = timestamp; ev->next = NULL; @@ -184,7 +188,7 @@ error_malloc_ev: return -1; } -int xas_script_add_frequency_set(xas_script *script, +int xas_script_add_set_frequency(xas_script *script, xas_spatial_object *object, struct timeval timestamp, size_t frequency) { @@ -195,6 +199,7 @@ int xas_script_add_frequency_set(xas_script *script, } ev->type = XAS_SCRIPT_EVENT_SET_FREQUENCY; + ev->objtype = XAS_SCRIPT_OBJECT_SYNTH; ev->object = object; ev->timestamp = timestamp; ev->next = NULL; @@ -208,4 +213,114 @@ error_malloc_ev: return -1; } -int xas_script_play(xas_script *script, xas_audio_stream *sink); +static inline void timerupdate(struct timeval *tv, + suseconds_t interval, + size_t frame) { + struct timeval zero = { 0, 0 }, + timer = { 0, frame * interval }; + + timeradd(&zero, &timer, tv); +} + +static int event_trigger(xas_spatial_scene *scene, xas_script_event *ev) { + switch (ev->type) { + case XAS_SCRIPT_EVENT_OFF: + return xas_spatial_object_stop(ev->object); + + case XAS_SCRIPT_EVENT_ON: + return xas_spatial_object_start(ev->object); + + case XAS_SCRIPT_EVENT_SET_POSITION: + xas_spatial_scene_position_object(scene, + ev->object, + ev->point); + + break; + + case XAS_SCRIPT_EVENT_SET_GAIN: + xas_object_set_gain(ev->object->ctx, ev->gain); + + break; + + case XAS_SCRIPT_EVENT_SET_FREQUENCY: + if (ev->objtype != XAS_SCRIPT_OBJECT_SYNTH) { + goto error_invalid_event; + } + + xas_synth_set_frequency(ev->object->ctx, ev->frequency); + + break; + + case XAS_SCRIPT_EVENT_SET_BANK_INDEX: + if (ev->objtype != XAS_SCRIPT_OBJECT_BANK_PLAYER) { + goto error_invalid_event; + } + + xas_bank_player_set_entry(ev->object->ctx, ev->gain); + + break; + } + + return 0; + +error_invalid_event: + return -1; +} + +int xas_script_play(xas_script *script, xas_audio_stream *sink) { + xas_script_event *ev = script->first; + xas_audio_stream *source; + + size_t frame = 0, + sample_rate = script->scene->format.sample_rate, + buffer_size = script->buffer_size; + + suseconds_t interval = 1000000 / (sample_rate / buffer_size); + + int16_t *samples; + + if ((source = xas_spatial_scene_new_stream(script->scene, + script->buffer_size)) == NULL) { + goto error_spatial_scene_new_stream; + } + + while (ev) { + xas_script_event *next = ev->next; + struct timeval tv; + + ssize_t readlen; + + timerupdate(&tv, interval, frame); + + if (timercmp(&ev->timestamp, &tv, >)) { + if (event_trigger(script->scene, ev) < 0) { + goto error_event_trigger; + } + + ev = next; + } + + if ((readlen = xas_audio_stream_read(source, + (void **)&samples, + buffer_size)) < 0) { + goto error_audio_stream_io; + } else if (readlen == 0) { + break; + } + + if (xas_audio_stream_write(sink, samples, readlen) < 0) { + goto error_audio_stream_io; + } + + frame++; + } + + return frame * buffer_size; + +error_audio_stream_io: +error_event_trigger: + xas_audio_stream_destroy(source); + +error_spatial_scene_new_stream: + return -1; +} |