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; +} | 
 
    