summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/xas/script.h28
-rw-r--r--src/script.c139
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;
+}