diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio.c | 107 | ||||
| -rw-r--r-- | src/bank.c | 44 | ||||
| -rw-r--r-- | src/mixer.c | 45 | ||||
| -rw-r--r-- | src/riff.c | 123 | ||||
| -rw-r--r-- | src/synth.c | 27 | ||||
| -rw-r--r-- | src/vox.c | 51 | 
6 files changed, 196 insertions, 201 deletions
| diff --git a/src/audio.c b/src/audio.c index 001d449..561870f 100644 --- a/src/audio.c +++ b/src/audio.c @@ -4,32 +4,54 @@  #include <xas/audio.h> +void xas_audio_copy(xas_audio_format format, +                      void *dest, +                      void *src, +                      size_t index_dest, +                      size_t index_src, +                      size_t count) { +    size_t stride = format.channels * format.sample_size; + +    memcpy(((uint8_t *)dest) + stride * index_dest, +           ((uint8_t *)src)  + stride * index_src, +           stride * count); +} + +void xas_audio_zero(xas_audio_format format, +                      void *dest, +                      size_t index, +                      size_t count) { +    size_t stride = format.channels * format.sample_size; + +    memset((uint8_t *)dest + stride * index, +           '\0', +           stride * count); +} +  static xas_audio_stream *stream_new(enum xas_audio_stream_type type,                                        void *callback,                                        xas_audio_cleanup cleanup, -                                      void *ctx, -                                      size_t channels, -                                      size_t sample_size, -                                      size_t sample_rate, -                                      size_t buffer_size) { +                                      xas_audio_format format, +                                      size_t buffer_size, +                                      void *ctx) {      xas_audio_stream *stream;      size_t total = sizeof(xas_audio_stream) -                 + channels * sample_size * buffer_size; +                 + format.channels * format.sample_size * buffer_size;      if ((stream = malloc(total)) == NULL) {          goto error_malloc_stream;      } -    stream->type         = type; -    stream->channels     = channels; -    stream->sample_size  = sample_size; -    stream->sample_rate  = sample_rate; -    stream->buffer_size  = buffer_size; -    stream->buffer_count = 0; -    stream->callback     = callback; -    stream->cleanup      = cleanup; -    stream->ctx          = ctx; +    stream->type               = type; +    stream->format.channels    = format.channels; +    stream->format.sample_size = format.sample_size; +    stream->format.sample_rate = format.sample_rate; +    stream->buffer_size        = buffer_size; +    stream->buffer_count       = 0; +    stream->callback           = callback; +    stream->cleanup            = cleanup; +    stream->ctx                = ctx;      return stream; @@ -39,36 +61,28 @@ error_malloc_stream:  xas_audio_stream *xas_audio_stream_new_sink(xas_audio_drain drain,                                                  xas_audio_cleanup cleanup, -                                                void *ctx, -                                                size_t channels, -                                                size_t sample_size, -                                                size_t sample_rate, -                                                size_t buffer_size) { +                                                xas_audio_format format, +                                                size_t buffer_size, +                                                void *ctx) {      return stream_new(XAS_AUDIO_STREAM_SINK,                        drain,                        cleanup, -                      ctx, -                      channels, -                      sample_size, -                      sample_rate, -                      buffer_size); +                      format, +                      buffer_size, +                      ctx);  }  xas_audio_stream *xas_audio_stream_new_source(xas_audio_fill fill,                                                    xas_audio_cleanup cleanup, -                                                  void *ctx, -                                                  size_t channels, -                                                  size_t sample_size, -                                                  size_t sample_rate, -                                                  size_t buffer_size) { +                                                  xas_audio_format format, +                                                  size_t buffer_size, +                                                  void *ctx) {      return stream_new(XAS_AUDIO_STREAM_SOURCE,                        fill,                        cleanup, -                      ctx, -                      channels, -                      sample_size, -                      sample_rate, -                      buffer_size); +                      format, +                      buffer_size, +                      ctx);  }  void xas_audio_stream_destroy(xas_audio_stream *stream) { @@ -100,7 +114,8 @@ error_stream_drain:  }  static inline void *ptr(xas_audio_stream *stream, void *buf, size_t index) { -    return ((uint8_t *)buf) + stream->channels * stream->sample_size * index; +    return ((uint8_t *)buf) +        + stream->format.channels * stream->format.sample_size * index;  }  ssize_t xas_audio_stream_write(xas_audio_stream *stream, @@ -116,12 +131,15 @@ ssize_t xas_audio_stream_write(xas_audio_stream *stream,           */          size_t remaining = stream->buffer_size - stream->buffer_count; -        memcpy(ptr(stream, stream + 1, stream->buffer_count), -               ptr(stream, samples,    index_i), -               remaining * stream->channels * stream->sample_size); +        xas_audio_copy(stream->format, +                         stream + 1, +                         samples, +                         stream->buffer_count, +                         index_i, +                         remaining);          if (stream->drain(stream->ctx, -                          ptr(stream, stream + 1, 0), +                          stream + 1,                            stream->buffer_size,                            stream) < 0) {              goto error_stream_drain; @@ -157,9 +175,12 @@ ssize_t xas_audio_stream_write(xas_audio_stream *stream,               * Enough of the input has been drained that it can be copied to               * the target buffer.               */ -            memcpy(ptr(stream, stream + 1, stream->buffer_count), -                   ptr(stream, samples,    index_i), -                   remaining * stream->channels * stream->sample_size); +            xas_audio_copy(stream->format, +                             stream + 1, +                             samples, +                             stream->buffer_count, +                             index_i, +                             remaining);              index_i += remaining; @@ -3,13 +3,12 @@  #include <xas/bank.h> -xas_bank *xas_bank_new(size_t sample_size, -                           size_t sample_rate, +xas_bank *xas_bank_new(xas_audio_format format,                             size_t entry_size,                             size_t entry_count) {      xas_bank *bank; -    size_t entry_size_total = sizeof(xas_bank_entry) + sample_size +    size_t entry_size_total = sizeof(xas_bank_entry) + format.sample_size                                                         * entry_size;      size_t total = sizeof(xas_bank) + entry_count @@ -21,8 +20,10 @@ xas_bank *xas_bank_new(size_t sample_size,      memset(bank, '\0', total); -    bank->sample_size = sample_size; -    bank->sample_rate = sample_rate; +    bank->format.channels    = XAS_AUDIO_MONO; +    bank->format.sample_size = format.sample_size; +    bank->format.sample_rate = format.sample_rate; +      bank->entry_size  = entry_size;      bank->entry_count = entry_count; @@ -36,9 +37,9 @@ void xas_bank_destroy(xas_bank *bank) {      free(bank);  } -int xas_bank_play(xas_bank *bank, size_t entry, float force) { +int xas_bank_play(xas_bank *bank, size_t entry, float gain) {      bank->flags |= XAS_BANK_ACTIVE; -    bank->force  = force; +    bank->gain   = gain;      bank->entry  = entry;      bank->index  = 0; @@ -47,7 +48,7 @@ int xas_bank_play(xas_bank *bank, size_t entry, float force) {  void xas_bank_stop(xas_bank *bank) {      bank->flags &= ~XAS_BANK_ACTIVE; -    bank->force  = 0.0; +    bank->gain   = 0.0;      bank->entry  = 0;      bank->index  = 0;  } @@ -56,10 +57,6 @@ int xas_bank_active(xas_bank *bank) {      return bank->flags & XAS_BANK_ACTIVE;  } -static inline void *ptr(xas_audio_stream *stream, void *buf, size_t index) { -    return ((uint8_t *)buf) + stream->channels * stream->sample_size * index; -} -  ssize_t xas_bank_record(xas_bank *bank,                            xas_audio_stream *input,                            size_t entry_index, @@ -83,9 +80,12 @@ ssize_t xas_bank_record(xas_bank *bank,              goto error_audio_stream_read;          } -        memcpy(ptr(input, entry + 1, index_o), -               ptr(input, buf,       0), -               readlen * bank->sample_size); +        xas_audio_copy(bank->format, +                         entry + 1, +                         buf, +                         index_o, +                         0, +                         readlen);          left    -= readlen;          index_o += readlen; @@ -117,7 +117,7 @@ static ssize_t stream_fill(xas_bank *bank,              size_t i;              for (i=0; i<amount; i++) { -                dest[index_o + i] = bank->force * src[bank->index + i]; +                dest[index_o + i] = bank->gain * src[bank->index + i];              }              left        -= amount; @@ -128,9 +128,7 @@ static ssize_t stream_fill(xas_bank *bank,                  xas_bank_stop(bank);              }          } else { -            memset(ptr(stream, dest, index_o), -                   '\0', -                   left * stream->channels * stream->sample_size); +            xas_audio_zero(bank->format, dest, index_o, left);              index_o += left;              left     = 0; @@ -147,9 +145,7 @@ void stream_cleanup(xas_bank *bank, xas_audio_stream *stream) {  xas_audio_stream *xas_bank_stream_new(xas_bank *bank) {      return xas_audio_stream_new_source((xas_audio_fill)stream_fill,                                           (xas_audio_cleanup)stream_cleanup, -                                         bank, -                                         XAS_AUDIO_MONO, -                                         bank->sample_size, -                                         bank->sample_rate, -                                         bank->entry_size); +                                         bank->format, +                                         bank->entry_size, +                                         bank);  } diff --git a/src/mixer.c b/src/mixer.c index b1f2e47..b4e3bf1 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -69,9 +69,7 @@ static ssize_t mixer_fill(xas_mixer *mixer,      xas_mixer_input *input = mixer->inputs; -    memset(mixer->buf, -           '\0', -           output->channels * output->sample_size * output->buffer_size); +    xas_audio_zero(output->format, mixer->buf, 0, mixer->buffer_size);      while (input) {          void (*mixer_apply)(int16_t *, @@ -86,13 +84,16 @@ static ssize_t mixer_fill(xas_mixer *mixer,          ssize_t readlen; -        if (output->channels == 2 && input->stream->channels == 2) { +        size_t channels_in  = input->stream->format.channels, +               channels_out = output->format.channels; + +        if (channels_in == 2 && channels_out == 2) {              mixer_apply = mixer_apply_stereo_to_stereo; -        } else if (output->channels == 2 && input->stream->channels == 1) { +        } else if (channels_in == 1 && channels_out == 2) {              mixer_apply = mixer_apply_mono_to_stereo; -        } else if (output->channels == 1 && input->stream->channels == 1) { +        } else if (channels_in == 1 && channels_out == 1) {              mixer_apply = mixer_apply_mono_to_mono; -        } else if (output->channels == 1 && input->stream->channels == 2) { +        } else if (channels_in == 2 && channels_out == 2) {              mixer_apply = mixer_apply_stereo_to_mono;          } else {              goto error_invalid_input; @@ -118,9 +119,12 @@ static ssize_t mixer_fill(xas_mixer *mixer,          input = next;      } -    memcpy(samples, -           mixer->buf, -           total * output->channels * output->sample_size); +    xas_audio_copy(output->format, +                     samples, +                     mixer->buf, +                     0, +                     0, +                     total);      return total; @@ -129,27 +133,24 @@ error_audio_read_stream:      return -1;  } -xas_mixer *xas_mixer_new(size_t channels, -                             size_t sample_size, -                             size_t sample_rate, -                             size_t buffer_size) { +xas_mixer *xas_mixer_new(xas_audio_format format, size_t buffer_size) {      xas_mixer *mixer; +    size_t total = buffer_size * format.channels * format.sample_size; +      if ((mixer = malloc(sizeof(*mixer))) == NULL) {          goto error_malloc_mixer;      } -    if ((mixer->buf = malloc(channels * sample_size * buffer_size)) == NULL) { +    if ((mixer->buf = malloc(total)) == NULL) {          goto error_malloc_buf;      }      if ((mixer->output = xas_audio_stream_new_source((xas_audio_fill)mixer_fill,                                                         NULL, -                                                       mixer, -                                                       channels, -                                                       sample_size, -                                                       sample_rate, -                                                       buffer_size)) == NULL) { +                                                       format, +                                                       buffer_size, +                                                       mixer)) == NULL) {          goto error_audio_stream_new_source;      } @@ -217,8 +218,8 @@ xas_mixer_input *xas_mixer_input_add(xas_mixer *mixer,                                           float pan) {      xas_mixer_input *input; -    if (stream->sample_size != mixer->output->sample_size -     || stream->sample_rate != mixer->output->sample_rate) { +    if (stream->format.sample_size != mixer->output->format.sample_size +     || stream->format.sample_rate != mixer->output->format.sample_rate) {          errno = EINVAL;          goto error_invalid_stream; @@ -12,9 +12,7 @@ struct _xas_riff {      int fd;      size_t size; -    size_t channels, -           sample_size, -           sample_rate; +    xas_audio_format format;  };  static int header_write(xas_riff *riff) { @@ -38,11 +36,13 @@ static int header_write(xas_riff *riff) {              },              .type             = XAS_RIFF_WAVE_DEFAULT_TYPE, -            .channels         = riff->channels, -            .sample_rate      = riff->sample_rate, -            .byte_rate        = riff->channels * riff->sample_size * riff->sample_rate, -            .sample_size      = riff->sample_size, -            .sample_size_bits = riff->sample_size << 3 +            .channels         = riff->format.channels, +            .sample_rate      = riff->format.sample_rate, +            .sample_size      = riff->format.sample_size, +            .sample_size_bits = riff->format.sample_size << 3, +            .byte_rate        = riff->format.channels +                              * riff->format.sample_size +                              * riff->format.sample_rate          },          { @@ -70,9 +70,7 @@ error_io:  }  static xas_riff *new_file(const char *path, -                            size_t channels, -                            size_t sample_size, -                            size_t sample_rate, +                            xas_audio_format format,                              int flags) {      xas_riff *riff; @@ -86,11 +84,12 @@ static xas_riff *new_file(const char *path,          goto error_open;      } -    riff->file        = path; -    riff->size        = 0; -    riff->channels    = channels; -    riff->sample_size = sample_size; -    riff->sample_rate = sample_rate; +    riff->file = path; +    riff->size = 0; + +    riff->format.channels    = format.channels; +    riff->format.sample_size = format.sample_size; +    riff->format.sample_rate = format.sample_rate;      if (header_write(riff) < 0) {          goto error_header_write; @@ -167,9 +166,9 @@ static int wave_header_parse(xas_riff *riff,          goto error_invalid_wave_data_format_id;      } -    riff->channels    = header->wave.channels; -    riff->sample_size = header->wave.sample_size; -    riff->sample_rate = header->wave.sample_rate; +    riff->format.channels    = header->wave.channels; +    riff->format.sample_size = header->wave.sample_size; +    riff->format.sample_rate = header->wave.sample_rate;      return 0; @@ -196,12 +195,13 @@ static xas_riff *open_fd(int fd) {          goto error_malloc_riff;      } -    riff->file        = NULL; -    riff->fd          = fd; -    riff->size        = 0; -    riff->channels    = 0; -    riff->sample_size = 0; -    riff->sample_rate = 0; +    riff->file = NULL; +    riff->fd   = fd; +    riff->size = 0; + +    riff->format.channels    = 0; +    riff->format.sample_size = 0; +    riff->format.sample_rate = 0;      if ((readlen = read(fd, &header, sizeof(header))) < 0) {          goto error_read; @@ -244,11 +244,12 @@ static xas_riff *open_file(const char *path, int flags) {          goto error_open;      } -    riff->file        = path; -    riff->size        = 0; -    riff->channels    = 0; -    riff->sample_size = 0; -    riff->sample_rate = 0; +    riff->file = path; +    riff->size = 0; + +    riff->format.channels    = 0; +    riff->format.sample_size = 0; +    riff->format.sample_rate = 0;      if (lseek(riff->fd, 0, SEEK_SET) < 0) {          goto error_lseek; @@ -299,8 +300,8 @@ static ssize_t audio_drain(xas_riff *riff,                             void *samples,                             size_t count,                             xas_audio_stream *stream) { -    size_t len = count * stream->channels -                       * stream->sample_size; +    size_t stride = stream->format.channels * stream->format.sample_size, +           len    = stride * count;      ssize_t wrlen; @@ -310,7 +311,7 @@ static ssize_t audio_drain(xas_riff *riff,      riff->size += wrlen; -    return wrlen / stream->channels / stream->sample_size; +    return wrlen / stride;  error_write:      return -1; @@ -320,8 +321,8 @@ static ssize_t audio_fill(xas_riff *riff,                            void *samples,                            size_t count,                            xas_audio_stream *stream) { -    size_t len = count * stream->channels -                       * stream->sample_size; +    size_t stride = stream->format.channels * stream->format.sample_size, +           len    = count * stride;      ssize_t rdlen; @@ -329,46 +330,36 @@ static ssize_t audio_fill(xas_riff *riff,          goto error_read;      } -    return rdlen / stream->channels / stream->sample_size; +    return rdlen / stride;  error_read:      return -1;  }  xas_audio_stream *xas_riff_new_file(const char *path, -                                        size_t channels, -                                        size_t sample_size, -                                        size_t sample_rate, +                                        xas_audio_format format,                                          int flags) {      xas_audio_stream *stream;      xas_riff *riff; -    if ((riff = new_file(path, -                         channels, -                         sample_size, -                         sample_rate, -                         flags)) == NULL) { +    if ((riff = new_file(path, format, flags)) == NULL) {          goto error_new_file;      }      if (flags & (O_RDWR | O_WRONLY)) {          if ((stream = xas_audio_stream_new_sink((xas_audio_drain)audio_drain,                                                    (xas_audio_cleanup)close_file, -                                                  riff, -                                                  channels, -                                                  sample_size, -                                                  sample_rate, -                                                  4096)) == NULL) { +                                                  format, +                                                  4096, +                                                  riff)) == NULL) {              goto error_audio_stream_new_sink;          }      } else {          if ((stream = xas_audio_stream_new_source((xas_audio_fill)audio_fill,                                                      (xas_audio_cleanup)close_file, -                                                    riff, -                                                    channels, -                                                    sample_size, -                                                    sample_rate, -                                                    4096)) == NULL) { +                                                    format, +                                                    4096, +                                                    riff)) == NULL) {              goto error_audio_stream_new_sink;          }      } @@ -393,21 +384,17 @@ xas_audio_stream *xas_riff_open_file(const char *path, int flags) {      if (flags & (O_RDWR | O_WRONLY)) {          if ((stream = xas_audio_stream_new_sink((xas_audio_drain)audio_drain,                                                    (xas_audio_cleanup)close_file, -                                                  riff, -                                                  riff->channels, -                                                  riff->sample_size, -                                                  riff->sample_rate, -                                                  4096)) == NULL) { +                                                  riff->format, +                                                  4096, +                                                  riff)) == NULL) {              goto error_audio_stream_new_sink;          }      } else {          if ((stream = xas_audio_stream_new_source((xas_audio_fill)audio_fill,                                                      (xas_audio_cleanup)close_file, -                                                    riff, -                                                    riff->channels, -                                                    riff->sample_size, -                                                    riff->sample_rate, -                                                    4096)) == NULL) { +                                                    riff->format, +                                                    4096, +                                                    riff)) == NULL) {              goto error_audio_stream_new_sink;          }      } @@ -431,11 +418,9 @@ xas_audio_stream *xas_riff_open_fd(int fd) {      if ((stream = xas_audio_stream_new_source((xas_audio_fill)audio_fill,                                                  (xas_audio_cleanup)close_file, -                                                riff, -                                                riff->channels, -                                                riff->sample_size, -                                                riff->sample_rate, -                                                4096)) == NULL) { +                                                riff->format, +                                                4096, +                                                riff)) == NULL) {          goto error_audio_stream_new_sink;      } diff --git a/src/synth.c b/src/synth.c index 6dd14ea..d96c1b5 100644 --- a/src/synth.c +++ b/src/synth.c @@ -23,11 +23,10 @@ static void synth_cleanup(xas_synth *synth, xas_audio_stream *stream) {      free(synth);  } -xas_audio_stream *xas_synth_new(size_t sample_size, -                                    size_t sample_rate, -                                    size_t buffer_size, -                                    xas_synth_callback_sample  sample, +xas_audio_stream *xas_synth_new(xas_synth_callback_sample  sample,                                      xas_synth_callback_cleanup cleanup, +                                    xas_audio_format format, +                                    size_t buffer_size,                                      void *ctx) {      xas_audio_stream *stream;      xas_synth *synth; @@ -36,19 +35,19 @@ xas_audio_stream *xas_synth_new(size_t sample_size,          goto error_malloc_synth;      } -    synth->sample_size = sample_size; -    synth->sample_rate = sample_rate; -    synth->sample      = sample; -    synth->cleanup     = cleanup; -    synth->ctx         = ctx; +    synth->format.channels    = XAS_AUDIO_MONO; +    synth->format.sample_size = format.sample_size; +    synth->format.sample_rate = format.sample_rate; + +    synth->sample  = sample; +    synth->cleanup = cleanup; +    synth->ctx     = ctx;      if ((stream = xas_audio_stream_new_source((xas_audio_fill)synth_fill,                                                  (xas_audio_cleanup)synth_cleanup, -                                                synth, -                                                XAS_AUDIO_MONO, -                                                sample_size, -                                                sample_rate, -                                                buffer_size)) == NULL) { +                                                synth->format, +                                                buffer_size, +                                                synth)) == NULL) {          goto error_audio_stream_new_source;      } @@ -64,7 +64,7 @@ static int vox_start(xas_vox *vox) {          NULL      }; -    snprintf(sample_rate, sizeof(sample_rate)-1, "%zu", vox->sample_rate); +    snprintf(sample_rate, sizeof(sample_rate)-1, "%zu", vox->format.sample_rate);      (void)vox_stop(vox); @@ -144,17 +144,15 @@ static ssize_t vox_fill(xas_vox *vox,      ssize_t readlen,              readcount; -    size_t i; -      if (!(vox->flags & XAS_VOX_ACTIVE)) { -        memset(samples, '\0', count * vox->sample_size); +        xas_audio_zero(vox->format, samples, 0, count);          return count;      }      if ((readlen = read(vox->stdout,                          samples, -                        count * vox->sample_size)) < 0) { +                        count * vox->format.sample_size)) < 0) {          goto error_read;      } @@ -162,11 +160,9 @@ static ssize_t vox_fill(xas_vox *vox,          vox_stop(vox);      } -    readcount = readlen / vox->sample_size; +    readcount = readlen / vox->format.sample_size; -    for (i=readcount; i<count-readcount; i++) { -        samples[i] = 0; -    } +    xas_audio_zero(vox->format, samples, readcount, count-readcount);      return count; @@ -175,10 +171,8 @@ error_read:  }  xas_vox *xas_vox_new(const char *text2wave_path, -                         size_t sample_size, -                         size_t sample_rate, -                         size_t buffer_size, -                         void *ctx) { +                         xas_audio_format format, +                         size_t buffer_size) {      xas_vox *vox;      if ((vox = malloc(sizeof(*vox))) == NULL) { @@ -186,16 +180,17 @@ xas_vox *xas_vox_new(const char *text2wave_path,      }      vox->text2wave_path = text2wave_path; -    vox->sample_size    = sample_size; -    vox->sample_rate    = sample_rate; -    vox->buffer_size    = buffer_size; -    vox->ctx            = ctx; -    vox->flags          = XAS_VOX_IDLE; -    vox->pid    = -1; -    vox->stdin  = -1; -    vox->stdout = -1; -    vox->in     = NULL; +    vox->format.channels    = XAS_AUDIO_MONO; +    vox->format.sample_size = format.sample_size; +    vox->format.sample_rate = format.sample_rate; + +    vox->buffer_size = buffer_size; +    vox->flags       = XAS_VOX_IDLE; +    vox->pid         = -1; +    vox->stdin       = -1; +    vox->stdout      = -1; +    vox->in          = NULL;      return vox; @@ -229,8 +224,8 @@ int xas_vox_generate(xas_vox *vox) {          goto error_riff_open_fd;      } -    if (output->sample_size != vox->sample_size -     || output->sample_rate != vox->sample_rate) { +    if (output->format.sample_size != vox->format.sample_size +     || output->format.sample_rate != vox->format.sample_rate) {          errno = EINVAL;          goto error_invalid_stream; @@ -274,9 +269,7 @@ int xas_vox_say(xas_vox *vox, const char *message) {  xas_audio_stream *xas_vox_stream_new(xas_vox *vox) {      return xas_audio_stream_new_source((xas_audio_fill)vox_fill,                                           (xas_audio_cleanup)vox_cleanup, -                                         vox, -                                         XAS_AUDIO_MONO, -                                         vox->sample_size, -                                         vox->sample_rate, -                                         vox->buffer_size); +                                         vox->format, +                                         vox->buffer_size, +                                         vox);  } | 
 
    