diff options
| author | Lennart Poettering <lennart@poettering.net> | 2007-08-23 22:35:40 +0000 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2007-08-23 22:35:40 +0000 | 
| commit | ed4dc16b95ce73862540a9669c273b9d0b888100 (patch) | |
| tree | 882490ec7c118c77fc29d96c1c93e40253985faa | |
| parent | 4eb9bb074653a6ebbb925c701c69d2b101098142 (diff) | |
big resampler rework: support integer-only resampling, support speex resampler
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1712 fefdeb5f-60dc-0310-8127-8f9354f1896f
| -rw-r--r-- | src/pulsecore/resampler.c | 764 | ||||
| -rw-r--r-- | src/pulsecore/resampler.h | 5 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16be.c | 3 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16be.h | 15 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16le.c | 68 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16le.h | 15 | ||||
| -rw-r--r-- | src/pulsecore/sconv.c | 261 | ||||
| -rw-r--r-- | src/pulsecore/sconv.h | 10 | 
8 files changed, 711 insertions, 430 deletions
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 1405d7e1..57de0d15 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -28,6 +28,7 @@  #include <string.h>  #include <samplerate.h> +  #include <liboil/liboilfuncs.h>  #include <liboil/liboil.h> @@ -36,41 +37,93 @@  #include <pulsecore/log.h>  #include <pulsecore/macro.h> +#include "speexwrap.h" +  #include "resampler.h"  struct pa_resampler {      pa_resample_method_t resample_method;      pa_sample_spec i_ss, o_ss;      pa_channel_map i_cm, o_cm; -    size_t i_fz, o_fz; +    size_t i_fz, o_fz, w_sz;      pa_mempool *mempool; -    void (*impl_free)(pa_resampler *r); -    void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate); -    void (*impl_update_output_rate)(pa_resampler *r, uint32_t rate); -    void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); -    void *impl_data; -}; - -struct impl_libsamplerate {      pa_memchunk buf1, buf2, buf3, buf4;      unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; -    pa_convert_to_float32ne_func_t to_float32ne_func; -    pa_convert_from_float32ne_func_t from_float32ne_func; -    SRC_STATE *src_state; +    pa_sample_format_t work_format; +     +    pa_convert_func_t to_work_format_func; +    pa_convert_func_t from_work_format_func;      int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX];      int map_required; -}; -struct impl_trivial { -    unsigned o_counter; -    unsigned i_counter; +    void (*impl_free)(pa_resampler *r); +    void (*impl_update_rates)(pa_resampler *r); +    void (*impl_resample)(pa_resampler *r, const pa_memchunk *in, unsigned in_samples, pa_memchunk *out, unsigned *out_samples); +     +    struct { /* data specific to the trivial resampler */ +        unsigned o_counter; +        unsigned i_counter; +    } trivial; + +    struct { /* data specific to libsamplerate */ +        SRC_STATE *state; +    } src; + +    struct { /* data specific to speex */ +        SpeexResamplerState* state; +    } speex;  };  static int libsamplerate_init(pa_resampler*r);  static int trivial_init(pa_resampler*r); +static int speex_init(pa_resampler*r); + +static void calc_map_table(pa_resampler *r); + +static int (* const init_table[])(pa_resampler*r) = { +    [PA_RESAMPLER_SRC_SINC_BEST_QUALITY]   = libsamplerate_init, +    [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = libsamplerate_init, +    [PA_RESAMPLER_SRC_SINC_FASTEST]        = libsamplerate_init, +    [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD]     = libsamplerate_init, +    [PA_RESAMPLER_SRC_LINEAR]              = libsamplerate_init, +    [PA_RESAMPLER_TRIVIAL]                 = trivial_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+0]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+1]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+2]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+3]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+4]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+5]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+6]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+7]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+8]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+9]      = speex_init, +    [PA_RESAMPLER_SPEEX_FLOAT_BASE+10]     = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+0]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+1]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+2]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+3]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+4]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+5]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+6]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+7]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+8]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+9]      = speex_init, +    [PA_RESAMPLER_SPEEX_FIXED_BASE+10]     = speex_init, +    [PA_RESAMPLER_AUTO]                    = NULL, +}; + +static inline size_t sample_size(pa_sample_format_t f) { +    pa_sample_spec ss = { +        .format = f, +        .rate = 0, +        .channels = 1 +    }; + +    return pa_sample_size(&ss); +}  pa_resampler* pa_resampler_new(          pa_mempool *pool, @@ -87,16 +140,25 @@ pa_resampler* pa_resampler_new(      pa_assert(b);      pa_assert(pa_sample_spec_valid(a));      pa_assert(pa_sample_spec_valid(b)); -    pa_assert(resample_method != PA_RESAMPLER_INVALID); - +    pa_assert(resample_method >= 0); +    pa_assert(resample_method < PA_RESAMPLER_MAX); + +    /* Fix method */ +    if (resample_method == PA_RESAMPLER_AUTO) { +        if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE || +            b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE) +            resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0; +        else +            resample_method = PA_RESAMPLER_SPEEX_FIXED_BASE + 0; +    } +          r = pa_xnew(pa_resampler, 1); -    r->impl_data = NULL;      r->mempool = pool;      r->resample_method = resample_method;      r->impl_free = NULL; -    r->impl_update_input_rate = NULL; -    r->impl_run = NULL; +    r->impl_update_rates = NULL; +    r->impl_resample = NULL;      /* Fill sample specs */      r->i_ss = *a; @@ -115,25 +177,62 @@ pa_resampler* pa_resampler_new(      r->i_fz = pa_frame_size(a);      r->o_fz = pa_frame_size(b); -    /* Choose implementation */ -    if (a->channels != b->channels || -        a->format != b->format || -        !pa_channel_map_equal(&r->i_cm, &r->o_cm) || -        resample_method != PA_RESAMPLER_TRIVIAL) { +    pa_memchunk_reset(&r->buf1); +    pa_memchunk_reset(&r->buf2); +    pa_memchunk_reset(&r->buf3); +    pa_memchunk_reset(&r->buf4); + +    r->buf1_samples = r->buf2_samples = r->buf3_samples = r->buf4_samples = 0; -        /* Use the libsamplerate based resampler for the complicated cases */ -        if (resample_method == PA_RESAMPLER_TRIVIAL) -            r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD; +    calc_map_table(r); -        if (libsamplerate_init(r) < 0) +    pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method)); +     +    if (resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) +        r->work_format = PA_SAMPLE_S16NE; +    else if (resample_method == PA_RESAMPLER_TRIVIAL) { + +        if (r->map_required || a->format != b->format) { + +            if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE) +                r->work_format = PA_SAMPLE_FLOAT32NE; +            else +                r->work_format = PA_SAMPLE_S16NE; +             +        } else +            r->work_format = a->format; +         +    } else +        r->work_format = PA_SAMPLE_FLOAT32NE; + +    r->w_sz = sample_size(r->work_format); +         +    if (r->i_ss.format == r->work_format) +        r->to_work_format_func = NULL; +    else if (r->work_format == PA_SAMPLE_FLOAT32NE) { +        if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))              goto fail; +    } else { +        pa_assert(r->work_format == PA_SAMPLE_S16NE); +        if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format))) +            goto fail; +    } +    if (r->o_ss.format == r->work_format) +        r->from_work_format_func = NULL; +    else if (r->work_format == PA_SAMPLE_FLOAT32NE) { +        if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format))) +            goto fail;      } else { -        /* Use our own simple non-fp resampler for the trivial cases and when the user selects it */ -        if (trivial_init(r) < 0) +        pa_assert(r->work_format == PA_SAMPLE_S16NE); +        if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format)))              goto fail;      } +    /* initialize implementation */ +    if (init_table[resample_method](r) < 0) +        goto fail; +      return r;  fail: @@ -149,6 +248,15 @@ void pa_resampler_free(pa_resampler *r) {      if (r->impl_free)          r->impl_free(r); +    if (r->buf1.memblock) +        pa_memblock_unref(r->buf1.memblock); +    if (r->buf2.memblock) +        pa_memblock_unref(r->buf2.memblock); +    if (r->buf3.memblock) +        pa_memblock_unref(r->buf3.memblock); +    if (r->buf4.memblock) +        pa_memblock_unref(r->buf4.memblock); +          pa_xfree(r);  } @@ -160,9 +268,7 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {          return;      r->i_ss.rate = rate; - -    if (r->impl_update_input_rate) -        r->impl_update_input_rate(r, rate); +    r->impl_update_rates(r);  }  void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) { @@ -173,15 +279,7 @@ void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {          return;      r->o_ss.rate = rate; - -    if (r->impl_update_output_rate) -        r->impl_update_output_rate(r, rate); -} - -void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { -    pa_assert(r && in && out && r->impl_run); - -    r->impl_run(r, in, out); +    r->impl_update_rates(r);  }  size_t pa_resampler_request(pa_resampler *r, size_t out_length) { @@ -192,6 +290,7 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {  pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {      pa_assert(r); +          return r->resample_method;  } @@ -201,7 +300,30 @@ static const char * const resample_methods[] = {      "src-sinc-fastest",      "src-zero-order-hold",      "src-linear", -    "trivial" +    "trivial", +    "speex-float-0", +    "speex-float-1", +    "speex-float-2", +    "speex-float-3", +    "speex-float-4", +    "speex-float-5", +    "speex-float-6", +    "speex-float-7", +    "speex-float-8", +    "speex-float-9", +    "speex-float-10", +    "speex-fixed-0", +    "speex-fixed-1", +    "speex-fixed-2", +    "speex-fixed-3", +    "speex-fixed-4", +    "speex-fixed-5", +    "speex-fixed-6", +    "speex-fixed-7", +    "speex-fixed-8", +    "speex-fixed-9", +    "speex-fixed-10", +    "auto"  };  const char *pa_resample_method_to_string(pa_resample_method_t m) { @@ -221,44 +343,21 @@ pa_resample_method_t pa_parse_resample_method(const char *string) {          if (!strcmp(string, resample_methods[m]))              return m; -    return PA_RESAMPLER_INVALID; -} - +    if (!strcmp(string, "speex-fixed")) +        return PA_RESAMPLER_SPEEX_FIXED_BASE + 0; -/*** libsamplerate based implementation ***/ +    if (!strcmp(string, "speex-float")) +        return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0; -static void libsamplerate_free(pa_resampler *r) { -    struct impl_libsamplerate *u; - -    pa_assert(r); -    pa_assert(r->impl_data); - -    u = r->impl_data; - -    if (u->src_state) -        src_delete(u->src_state); - -    if (u->buf1.memblock) -        pa_memblock_unref(u->buf1.memblock); -    if (u->buf2.memblock) -        pa_memblock_unref(u->buf2.memblock); -    if (u->buf3.memblock) -        pa_memblock_unref(u->buf3.memblock); -    if (u->buf4.memblock) -        pa_memblock_unref(u->buf4.memblock); -    pa_xfree(u); +    return PA_RESAMPLER_INVALID;  }  static void calc_map_table(pa_resampler *r) { -    struct impl_libsamplerate *u;      unsigned oc;      pa_assert(r); -    pa_assert(r->impl_data); - -    u = r->impl_data; -    if (!(u->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm)))) +    if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))          return;      for (oc = 0; oc < r->o_ss.channels; oc++) { @@ -276,17 +375,16 @@ static void calc_map_table(pa_resampler *r) {                  (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||                  (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO)) -                u->map_table[oc][i++] = ic; +                r->map_table[oc][i++] = ic;          }          /* Add an end marker */          if (i < PA_CHANNELS_MAX) -            u->map_table[oc][i] = -1; +            r->map_table[oc][i] = -1;      }  } -static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) { -    struct impl_libsamplerate *u; +static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {      unsigned n_samples;      void *src, *dst; @@ -294,192 +392,193 @@ static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {      pa_assert(input);      pa_assert(input->memblock); -    pa_assert(r->impl_data); -    u = r->impl_data; - -    /* Convert the incoming sample into floats and place them in buf1 */ +    /* Convert the incoming sample into the work sample format and place them in buf1 */ -    if (!u->to_float32ne_func || !input->length) +    if (!r->to_work_format_func || !input->length)          return input;      n_samples = (input->length / r->i_fz) * r->i_ss.channels; -    if (!u->buf1.memblock || u->buf1_samples < n_samples) { -        if (u->buf1.memblock) -            pa_memblock_unref(u->buf1.memblock); +    r->buf1.index = 0; +    r->buf1.length = r->w_sz * n_samples; +     +    if (!r->buf1.memblock || r->buf1_samples < n_samples) { +        if (r->buf1.memblock) +            pa_memblock_unref(r->buf1.memblock); -        u->buf1_samples = n_samples; -        u->buf1.memblock = pa_memblock_new(r->mempool, u->buf1.length = sizeof(float) * n_samples); -        u->buf1.index = 0; +        r->buf1_samples = n_samples; +        r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length);      }      src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; -    dst = (uint8_t*) pa_memblock_acquire(u->buf1.memblock); +    dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock); -    u->to_float32ne_func(n_samples, src, dst); +    r->to_work_format_func(n_samples, src, dst);      pa_memblock_release(input->memblock); -    pa_memblock_release(u->buf1.memblock); - -    u->buf1.length = sizeof(float) * n_samples; +    pa_memblock_release(r->buf1.memblock); -    return &u->buf1; +    return &r->buf1;  }  static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { -    struct impl_libsamplerate *u;      unsigned in_n_samples, out_n_samples, n_frames;      int i_skip, o_skip;      unsigned oc; -    float *src, *dst; +    void *src, *dst;      pa_assert(r);      pa_assert(input);      pa_assert(input->memblock); -    pa_assert(r->impl_data); -    u = r->impl_data; -      /* Remap channels and place the result int buf2 */ -    if (!u->map_required || !input->length) +    if (!r->map_required || !input->length)          return input; -    in_n_samples = input->length / sizeof(float); +    in_n_samples = input->length / r->w_sz;      n_frames = in_n_samples / r->i_ss.channels;      out_n_samples = n_frames * r->o_ss.channels; -    if (!u->buf2.memblock || u->buf2_samples < out_n_samples) { -        if (u->buf2.memblock) -            pa_memblock_unref(u->buf2.memblock); +    r->buf2.index = 0; +    r->buf2.length = r->w_sz * out_n_samples; +     +    if (!r->buf2.memblock || r->buf2_samples < out_n_samples) { +        if (r->buf2.memblock) +            pa_memblock_unref(r->buf2.memblock); -        u->buf2_samples = out_n_samples; -        u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * out_n_samples); -        u->buf2.index = 0; +        r->buf2_samples = out_n_samples; +        r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length);      } -    src = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); -    dst = (float*) pa_memblock_acquire(u->buf2.memblock); - -    memset(dst, 0, u->buf2.length); - -    o_skip = sizeof(float) * r->o_ss.channels; -    i_skip = sizeof(float) * r->i_ss.channels; - -    for (oc = 0; oc < r->o_ss.channels; oc++) { -        unsigned i; -        static const float one = 1.0; - -        for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++) -            oil_vectoradd_f32( -                dst + oc, o_skip, -                dst + oc, o_skip, -                src + u->map_table[oc][i], i_skip, -                n_frames, -                &one, &one); +    src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); +    dst = pa_memblock_acquire(r->buf2.memblock); + +    memset(dst, 0, r->buf2.length); + +    o_skip = r->w_sz * r->o_ss.channels; +    i_skip = r->w_sz * r->i_ss.channels; + +    switch (r->work_format) { +        case PA_SAMPLE_FLOAT32NE: +             +            for (oc = 0; oc < r->o_ss.channels; oc++) { +                unsigned i; +                static const float one = 1.0; +                 +                for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++) +                    oil_vectoradd_f32( +                            (float*) dst + oc, o_skip, +                            (float*) dst + oc, o_skip, +                            (float*) src + r->map_table[oc][i], i_skip, +                            n_frames, +                            &one, &one); +            } + +            break; + +        case PA_SAMPLE_S16NE: + +            for (oc = 0; oc < r->o_ss.channels; oc++) { +                unsigned i; +                static const int16_t one = 1; +                 +                for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++) +                    oil_vectoradd_s16( +                            (int16_t*) dst + oc, o_skip, +                            (int16_t*) dst + oc, o_skip, +                            (int16_t*) src + r->map_table[oc][i], i_skip, +                            n_frames, +                            &one, &one); +            } + +            break; + +        default: +            pa_assert_not_reached();      }      pa_memblock_release(input->memblock); -    pa_memblock_release(u->buf2.memblock); +    pa_memblock_release(r->buf2.memblock); -    u->buf2.length = out_n_samples * sizeof(float); +    r->buf2.length = out_n_samples * r->w_sz; -    return &u->buf2; +    return &r->buf2;  }  static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) { -    struct impl_libsamplerate *u; -    SRC_DATA data;      unsigned in_n_frames, in_n_samples;      unsigned out_n_frames, out_n_samples; -    int ret;      pa_assert(r);      pa_assert(input); -    pa_assert(r->impl_data); -    u = r->impl_data;      /* Resample the data and place the result in buf3 */ -    if (!u->src_state || !input->length) +    if (!r->impl_resample || !input->length)          return input; -    in_n_samples = input->length / sizeof(float); +    in_n_samples = input->length / r->w_sz;      in_n_frames = in_n_samples / r->o_ss.channels;      out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+1024;      out_n_samples = out_n_frames * r->o_ss.channels; -    if (!u->buf3.memblock || u->buf3_samples < out_n_samples) { -        if (u->buf3.memblock) -            pa_memblock_unref(u->buf3.memblock); +    r->buf3.index = 0; +    r->buf3.length = r->w_sz * out_n_samples; +     +    if (!r->buf3.memblock || r->buf3_samples < out_n_samples) { +        if (r->buf3.memblock) +            pa_memblock_unref(r->buf3.memblock); -        u->buf3_samples = out_n_samples; -        u->buf3.memblock = pa_memblock_new(r->mempool, u->buf3.length = sizeof(float) * out_n_samples); -        u->buf3.index = 0; +        r->buf3_samples = out_n_samples; +        r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length);      } -    data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); -    data.input_frames = in_n_frames; - -    data.data_out = (float*) pa_memblock_acquire(u->buf3.memblock); -    data.output_frames = out_n_frames; - -    data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; -    data.end_of_input = 0; - -    ret = src_process(u->src_state, &data); -    pa_assert(ret == 0); -    pa_assert((unsigned) data.input_frames_used == in_n_frames); - -    pa_memblock_release(input->memblock); -    pa_memblock_release(u->buf3.memblock); - -    u->buf3.length = data.output_frames_gen * sizeof(float) * r->o_ss.channels; - -    return &u->buf3; +    r->impl_resample(r, input, in_n_frames, &r->buf3, &out_n_frames); +    r->buf3.length = out_n_frames * r->w_sz * r->o_ss.channels; +     +    return &r->buf3;  } -static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) { -    struct impl_libsamplerate *u; +static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) {      unsigned n_samples, n_frames;      void *src, *dst;      pa_assert(r);      pa_assert(input); -    pa_assert(r->impl_data); -    u = r->impl_data;      /* Convert the data into the correct sample type and place the result in buf4 */ -    if (!u->from_float32ne_func || !input->length) +    if (!r->from_work_format_func || !input->length)          return input; -    n_frames = input->length / sizeof(float) / r->o_ss.channels; -    n_samples = n_frames * r->o_ss.channels; +    n_samples = input->length / r->w_sz; +    n_frames =  n_samples / r->o_ss.channels; -    if (!u->buf4.memblock || u->buf4_samples < n_samples) { -        if (u->buf4.memblock) -            pa_memblock_unref(u->buf4.memblock); +    r->buf4.index = 0; +    r->buf4.length = r->o_fz * n_frames; +         +    if (!r->buf4.memblock || r->buf4_samples < n_samples) { +        if (r->buf4.memblock) +            pa_memblock_unref(r->buf4.memblock); -        u->buf4_samples = n_samples; -        u->buf4.memblock = pa_memblock_new(r->mempool, u->buf4.length = r->o_fz * n_frames); -        u->buf4.index = 0; +        r->buf4_samples = n_samples; +        r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length);      }      src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; -    dst = pa_memblock_acquire(u->buf4.memblock); -    u->from_float32ne_func(n_samples, src, dst); +    dst = pa_memblock_acquire(r->buf4.memblock); +    r->from_work_format_func(n_samples, src, dst);      pa_memblock_release(input->memblock); -    pa_memblock_release(u->buf4.memblock); +    pa_memblock_release(r->buf4.memblock); -    u->buf4.length = r->o_fz * n_frames; +    r->buf4.length = r->o_fz * n_frames; -    return &u->buf4; +    return &r->buf4;  } -static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { -    struct impl_libsamplerate *u; +void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {      pa_memchunk *buf;      pa_assert(r); @@ -488,19 +587,16 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun      pa_assert(in->length);      pa_assert(in->memblock);      pa_assert(in->length % r->i_fz == 0); -    pa_assert(r->impl_data); - -    u = r->impl_data;      buf = (pa_memchunk*) in; -    buf = convert_to_float(r, buf); +    buf = convert_to_work_format(r, buf);      buf = remap_channels(r, buf);      buf = resample(r, buf);      if (buf->length) { -        buf = convert_from_float(r, buf); +        buf = convert_from_work_format(r, buf);          *out = *buf; - +                  if (buf == in)              pa_memblock_ref(buf->memblock);          else @@ -509,188 +605,222 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun          pa_memchunk_reset(out);  } -static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) { -    struct impl_libsamplerate *u; +/*** libsamplerate based implementation ***/ +static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { +    SRC_DATA data; +          pa_assert(r); -    pa_assert(rate > 0); -    pa_assert(r->impl_data); -    u = r->impl_data; +    pa_assert(input); +    pa_assert(output); +    pa_assert(out_n_frames); +     +    memset(&data, 0, sizeof(data)); +     +    data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); +    data.input_frames = in_n_frames; -    if (!u->src_state) { -        int err; -        u->src_state = src_new(r->resample_method, r->o_ss.channels, &err); -        pa_assert(u->src_state); -    } else { -        int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate); -        pa_assert(ret == 0); -    } -} +    data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); +    data.output_frames = *out_n_frames; -static void libsamplerate_update_output_rate(pa_resampler *r, uint32_t rate) { -    struct impl_libsamplerate *u; +    data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; +    data.end_of_input = 0; + +    pa_assert_se(src_process(r->src.state, &data) == 0); +    pa_assert((unsigned) data.input_frames_used == in_n_frames); + +    pa_memblock_release(input->memblock); +    pa_memblock_release(output->memblock); +    *out_n_frames = data.output_frames_gen; +} + +static void libsamplerate_update_rates(pa_resampler *r) {      pa_assert(r); -    pa_assert(rate > 0); -    pa_assert(r->impl_data); -    u = r->impl_data; -    if (!u->src_state) { -        int err; -        u->src_state = src_new(r->resample_method, r->o_ss.channels, &err); -        pa_assert(u->src_state); -    } else { -        int ret = src_set_ratio(u->src_state, (double) rate / r->i_ss.rate); -        pa_assert(ret == 0); -    } +    pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0); +} + +static void libsamplerate_free(pa_resampler *r) { +    pa_assert(r); +     +    if (r->src.state) +        src_delete(r->src.state);  }  static int libsamplerate_init(pa_resampler *r) { -    struct impl_libsamplerate *u = NULL;      int err; +     +    pa_assert(r); +     +    if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err))) +        return -1; -    r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1); - -    pa_memchunk_reset(&u->buf1); -    pa_memchunk_reset(&u->buf2); -    pa_memchunk_reset(&u->buf3); -    pa_memchunk_reset(&u->buf4); -    u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0; +    r->impl_free = libsamplerate_free; +    r->impl_update_rates = libsamplerate_update_rates; +    r->impl_resample = libsamplerate_resample; -    if (r->i_ss.format == PA_SAMPLE_FLOAT32NE) -        u->to_float32ne_func = NULL; -    else if (!(u->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format))) -        goto fail; +    return 0; +} -    if (r->o_ss.format == PA_SAMPLE_FLOAT32NE) -        u->from_float32ne_func = NULL; -    else if (!(u->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format))) -        goto fail; +/*** speex based implementation ***/ -    if (r->o_ss.rate == r->i_ss.rate) -        u->src_state = NULL; -    else if (!(u->src_state = src_new(r->resample_method, r->o_ss.channels, &err))) -        goto fail; +static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { +    float *in, *out; +    uint32_t inf = in_n_frames, outf = *out_n_frames; -    r->impl_free = libsamplerate_free; -    r->impl_update_input_rate = libsamplerate_update_input_rate; -    r->impl_update_output_rate = libsamplerate_update_output_rate; -    r->impl_run = libsamplerate_run; +    pa_assert(r); +    pa_assert(input); +    pa_assert(output); +    pa_assert(out_n_frames); +     +    in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); +    out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); -    calc_map_table(r); +    pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0); -    return 0; +    pa_memblock_release(input->memblock); +    pa_memblock_release(output->memblock); -fail: -    pa_xfree(u); -    return -1; +    pa_assert(inf == in_n_frames); +    *out_n_frames = outf;  } -/* Trivial implementation */ - -static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { -    size_t fz; -    unsigned  n_frames; -    struct impl_trivial *u; +static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { +    int16_t *in, *out; +    uint32_t inf = in_n_frames, outf = *out_n_frames;      pa_assert(r); -    pa_assert(in); -    pa_assert(out); -    pa_assert(r->impl_data); - -    u = r->impl_data; - -    fz = r->i_fz; -    pa_assert(fz == r->o_fz); +    pa_assert(input); +    pa_assert(output); +    pa_assert(out_n_frames); +     +    in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); +    out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); -    n_frames = in->length/fz; +    pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0); -    if (r->i_ss.rate == r->o_ss.rate) { +    pa_memblock_release(input->memblock); +    pa_memblock_release(output->memblock); -        /* In case there's no diefference in sample types, do nothing */ -        *out = *in; -        pa_memblock_ref(out->memblock); +    pa_assert(inf == in_n_frames); +    *out_n_frames = outf; +} -        u->o_counter += n_frames; -    } else { -        /* Do real resampling */ -        size_t l; -        unsigned o_index; -        void *src, *dst; +static void speex_update_rates(pa_resampler *r) { +    pa_assert(r); -        /* The length of the new memory block rounded up */ -        l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; +    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)  +        pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0); +    else { +        pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); +        pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0); +    } +} -        out->index = 0; -        out->memblock = pa_memblock_new(r->mempool, l); +static void speex_free(pa_resampler *r) { +    pa_assert(r); +     +    if (r->speex.state) { +        if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)  +            paspfx_resampler_destroy(r->speex.state); +        else { +            pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); +            paspfl_resampler_destroy(r->speex.state); +        } +    } +} -        src = (uint8_t*) pa_memblock_acquire(in->memblock) + in->index; -        dst = pa_memblock_acquire(out->memblock); +static int speex_init(pa_resampler *r) { +    int q, err; +     +    pa_assert(r); -        for (o_index = 0;; o_index++, u->o_counter++) { -            unsigned j; +    r->impl_free = speex_free; +    r->impl_update_rates = speex_update_rates; +     +    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) { +        q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE; +        r->impl_resample = speex_resample_int; -            j = (u->o_counter * r->i_ss.rate / r->o_ss.rate); -            j = j > u->i_counter ? j - u->i_counter : 0; +        if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err))) +            return -1; -            if (j >= n_frames) -                break; +    } else { +        pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); +        q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE; +        r->impl_resample = speex_resample_float; -            pa_assert(o_index*fz < pa_memblock_get_length(out->memblock)); +        if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err))) +            return -1; +    } +     -            memcpy((uint8_t*) dst + fz*o_index, -                   (uint8_t*) src + fz*j, fz); +    return 0; +} -        } +/* Trivial implementation */ -        pa_memblock_release(in->memblock); -        pa_memblock_release(out->memblock); +static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { +    size_t fz; +    unsigned o_index; +    void *src, *dst; +     +    pa_assert(r); +    pa_assert(input); +    pa_assert(output); +    pa_assert(out_n_frames); -        out->length = o_index*fz; +    fz = r->w_sz * r->o_ss.channels; +     +    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; +    dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index; +     +    for (o_index = 0;; o_index++, r->trivial.o_counter++) { +        unsigned j; +         +        j = ((r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate); +        j = j > r->trivial.i_counter ? j - r->trivial.i_counter : 0; +         +        if (j >= in_n_frames) +            break; + +        pa_assert(o_index * fz < pa_memblock_get_length(output->memblock)); +         +        oil_memcpy((uint8_t*) dst + fz * o_index, +                   (uint8_t*) src + fz * j, fz);         } +     +    pa_memblock_release(input->memblock); +    pa_memblock_release(output->memblock); +     +    *out_n_frames = o_index; -    u->i_counter += n_frames; +    r->trivial.i_counter += in_n_frames;      /* Normalize counters */ -    while (u->i_counter >= r->i_ss.rate) { -        u->i_counter -= r->i_ss.rate; -        pa_assert(u->o_counter >= r->o_ss.rate); -        u->o_counter -= r->o_ss.rate; -    } -} - -static void trivial_free(pa_resampler *r) { -    pa_assert(r); +    while (r->trivial.i_counter >= r->i_ss.rate) { +        pa_assert(r->trivial.o_counter >= r->o_ss.rate); -    pa_xfree(r->impl_data); +        r->trivial.i_counter -= r->i_ss.rate; +        r->trivial.o_counter -= r->o_ss.rate; +    }  } -static void trivial_update_rate(pa_resampler *r, uint32_t rate) { -    struct impl_trivial *u; - +static void trivial_update_rates(pa_resampler *r) {      pa_assert(r); -    pa_assert(rate > 0); -    pa_assert(r->impl_data); -    u = r->impl_data; -    u->i_counter = 0; -    u->o_counter = 0; +    r->trivial.i_counter = 0; +    r->trivial.o_counter = 0;  }  static int trivial_init(pa_resampler*r) { -    struct impl_trivial *u; -      pa_assert(r); -    pa_assert(r->i_ss.format == r->o_ss.format); -    pa_assert(r->i_ss.channels == r->o_ss.channels); -    r->impl_data = u = pa_xnew(struct impl_trivial, 1); -    u->o_counter = u->i_counter = 0; +    r->trivial.o_counter = r->trivial.i_counter = 0; -    r->impl_run = trivial_run; -    r->impl_free = trivial_free; -    r->impl_update_input_rate = trivial_update_rate; -    r->impl_update_output_rate = trivial_update_rate; +    r->impl_resample = trivial_resample; +    r->impl_update_rates = trivial_update_rates;      return 0;  } diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index ada293e5..35f53db3 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -41,6 +41,11 @@ typedef enum pa_resample_method {      PA_RESAMPLER_SRC_ZERO_ORDER_HOLD     = SRC_ZERO_ORDER_HOLD,      PA_RESAMPLER_SRC_LINEAR              = SRC_LINEAR,      PA_RESAMPLER_TRIVIAL, +    PA_RESAMPLER_SPEEX_FLOAT_BASE, +    PA_RESAMPLER_SPEEX_FLOAT_MAX = PA_RESAMPLER_SPEEX_FLOAT_BASE + 10, +    PA_RESAMPLER_SPEEX_FIXED_BASE, +    PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10, +    PA_RESAMPLER_AUTO, /* automatic select based on sample format */      PA_RESAMPLER_MAX  } pa_resample_method_t; diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c index c530e79b..658b3f5c 100644 --- a/src/pulsecore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -33,6 +33,9 @@  #define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne  #define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne +#define pa_sconv_s16le_to_float32re pa_sconv_s16be_to_float32re +#define pa_sconv_s16le_from_float32re pa_sconv_s16be_from_float32re +  #ifdef WORDS_BIGENDIAN  #define SWAP_WORDS 0  #else diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h index 6b736f69..ad034489 100644 --- a/src/pulsecore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -24,7 +24,18 @@    USA.  ***/ -void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, float *b); -void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b); +#include <inttypes.h> + +void pa_sconv_s16be_to_float32ne(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, int16_t *b); +void pa_sconv_s16be_to_float32re(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16be_from_float32re(unsigned n, const float *a, int16_t *b); + +#ifdef WORDS_BIGENDIAN +#define pa_sconv_float32be_to_s16ne pa_sconv_s16be_from_float32ne +#define pa_sconv_float32be_from_s16ne pa_sconv_s16be_to_float32ne +#define pa_sconv_float32le_to_s16ne pa_sconv_s16be_from_float32re +#define pa_sconv_float32le_from_s16ne pa_sconv_s16be_to_float32re +#endif  #endif diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 5f45ef66..c82708ca 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -25,12 +25,12 @@  #include <config.h>  #endif -#include <assert.h>  #include <inttypes.h>  #include <liboil/liboilfuncs.h>  #include <pulsecore/sconv.h> +#include <pulsecore/macro.h>  #include <pulsecore/log.h>  #include "endianmacros.h" @@ -53,32 +53,28 @@  #endif  #endif -void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) { -    const int16_t *ca = a; - -    assert(a); -    assert(b); +void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) { +    pa_assert(a); +    pa_assert(b);  #if SWAP_WORDS == 1      for (; n > 0; n--) { -        int16_t s = *(ca++); +        int16_t s = *(a++);          *(b++) = ((float) INT16_FROM(s))/0x7FFF;      }  #else  {      static const double add = 0, factor = 1.0/0x7FFF; -    oil_scaleconv_f32_s16(b, ca, n, &add, &factor); +    oil_scaleconv_f32_s16(b, a, n, &add, &factor);  }  #endif  } -void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) { -    int16_t *cb = b; - -    assert(a); -    assert(b); +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b);  #if SWAP_WORDS == 1 @@ -93,13 +89,55 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {              v = -1;          s = (int16_t) (v * 0x7FFF); -        *(cb++) = INT16_TO(s); +        *(b++) = INT16_TO(s);      }  #else  {      static const double add = 0, factor = 0x7FFF; -    oil_scaleconv_s16_f32(cb, a, n, &add, &factor); +    oil_scaleconv_s16_f32(b, a, n, &add, &factor); +} +#endif  } + +void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { +    pa_assert(a); +    pa_assert(b); + +#if SWAP_WORDS == 1 + +    for (; n > 0; n--) { +        int16_t s = *(a++); +        float k = ((float) INT16_FROM(s))/0x7FFF; +        uint32_t *j = (uint32_t*) &k; +        *j = UINT32_SWAP(*j); +        *(b++) = k; +    } + +#endif +} + +void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); + +#if SWAP_WORDS == 1 + +    for (; n > 0; n--) { +        int16_t s; +        float v = *(a++); +        uint32_t *j = (uint32_t*) &v; +        *j = UINT32_SWAP(*j); + +        if (v > 1) +            v = 1; + +        if (v < -1) +            v = -1; + +        s = (int16_t) (v * 0x7FFF); +        *(b++) = INT16_TO(s); +    } +  #endif  } diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h index c4e4911a..4203315a 100644 --- a/src/pulsecore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -24,7 +24,18 @@    USA.  ***/ -void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b); -void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b); +#include <inttypes.h> + +void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b); +void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b); + +#ifndef WORDS_BIGENDIAN +#define pa_sconv_float32be_to_s16ne pa_sconv_s16le_from_float32re +#define pa_sconv_float32be_from_s16ne pa_sconv_s16le_to_float32re +#define pa_sconv_float32le_to_s16ne pa_sconv_s16le_from_float32ne +#define pa_sconv_float32le_from_s16ne pa_sconv_s16le_to_float32ne +#endif  #endif diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index d15cec84..4986ba7c 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -28,12 +28,12 @@  #include <stdio.h>  #include <stdlib.h> -#include <assert.h>  #include <liboil/liboilfuncs.h>  #include <liboil/liboil.h>  #include <pulsecore/g711.h> +#include <pulsecore/macro.h>  #include "endianmacros.h"  #include "sconv-s16le.h" @@ -41,71 +41,92 @@  #include "sconv.h" -static void u8_to_float32ne(unsigned n, const void *a, float *b) { -    const uint8_t *ca = a; +/* u8 */ +static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) {      static const double add = -128.0/127.0, factor = 1.0/127.0; -    assert(a); -    assert(b); +    pa_assert(a); +    pa_assert(b); -    oil_scaleconv_f32_u8(b, ca, n, &add, &factor); +    oil_scaleconv_f32_u8(b, a, n, &add, &factor);  } -static void u8_from_float32ne(unsigned n, const float *a, void *b) { -    uint8_t *cb = b; +static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) {      static const double add = 128.0, factor = 127.0; -    assert(a); -    assert(b); +    pa_assert(a); +    pa_assert(b); -    oil_scaleconv_u8_f32(cb, a, n, &add, &factor); +    oil_scaleconv_u8_f32(b, a, n, &add, &factor);  } -static void float32ne_to_float32ne(unsigned n, const void *a, float *b) { -    assert(a); -    assert(b); +static void u8_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { +    static const int16_t add = -128, factor = 0x100; -    oil_memcpy(b, a, sizeof(float) * n); +    pa_assert(a); +    pa_assert(b); + +    oil_conv_s16_u8(b, 2, a, 1, n); +    oil_scalaradd_s16(b, 2, b, 2, &add, n); +    oil_scalarmult_s16(b, 2, b, 2, &factor, n); +} + +static void u8_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { + +    pa_assert(a); +    pa_assert(b); +     +    for (; n > 0; n--, a ++, a++) +        *b = (uint8_t) (*a / 0x100 + 0x80);  } -static void float32ne_from_float32ne(unsigned n, const float *a, void *b) { -    assert(a); -    assert(b); +/* float32 */ + +static void float32ne_to_float32ne(unsigned n, const float *a, float *b) { +    pa_assert(a); +    pa_assert(b);      oil_memcpy(b, a, sizeof(float) * n);  } -static void float32re_to_float32ne(unsigned n, const void *a, float *b) { -    assert(a); -    assert(b); +static void float32re_to_float32ne(unsigned n, const float *a, float *b) { +    pa_assert(a); +    pa_assert(b); -    while (n-- > 0) -        ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]); +    for (; n > 0; n--, a++, b++) +        *((uint32_t *) b) = UINT32_SWAP(*((uint32_t *) a));  } -static void float32re_from_float32ne(unsigned n, const float *a, void *b) { -    assert(a); -    assert(b); +/* s16 */ -    while (n-- > 0) -        ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]); +static void s16ne_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); + +    oil_memcpy(b, a, sizeof(int16_t) * n);  } -static void ulaw_to_float32ne(unsigned n, const void *a, float *b) { -    const uint8_t *ca = a; +static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--, a++, b++) +        *b = UINT16_SWAP(*a); +} -    assert(a); -    assert(b); +/* ulaw */ + +static void ulaw_to_float32ne(unsigned n, const uint8_t *a, float *b) { +    pa_assert(a); +    pa_assert(b);      for (; n > 0; n--) -        *(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF; +        *(b++) = st_ulaw2linear16(*(a++)) * 1.0F / 0x7FFF;  } -static void ulaw_from_float32ne(unsigned n, const float *a, void *b) { -    uint8_t *cb = b; - -    assert(a); -    assert(b); +static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b);      for (; n > 0; n--) {          float v = *(a++); @@ -116,28 +137,42 @@ static void ulaw_from_float32ne(unsigned n, const float *a, void *b) {          if (v < -1)              v = -1; -        *(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF)); +        *(b++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));      }  } -static void alaw_to_float32ne(unsigned n, const void *a, float *b) { -    const uint8_t *ca = a; +static void ulaw_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); -    assert(a); -    assert(b); +    for (; n > 0; n--, a++, b++) +        *b = st_ulaw2linear16(*a); +} -    for (; n > 0; n--) -        *(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF; +static void ulaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--, a++, b++) +        *b = st_14linear2ulaw(*a >> 2);  } -static void alaw_from_float32ne(unsigned n, const float *a, void *b) { -    uint8_t *cb = b; +/* alaw */ -    assert(a); -    assert(b); +static void alaw_to_float32ne(unsigned n, const uint8_t *a, float *b) { +    pa_assert(a); +    pa_assert(b); -    for (; n > 0; n--) { -        float v = *(a++); +    for (; n > 0; n--, a++, b++) +        *b = st_alaw2linear16(*a) * 1.0F / 0x7FFF; +} + +static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--, a++, b++) { +        float v = *a;          if (v > 1)              v = 1; @@ -145,48 +180,94 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b) {          if (v < -1)              v = -1; -        *(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF)); +        *b = st_13linear2alaw((int16_t) (v * 0xFFF));      }  } -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) { -    switch(f) { -        case PA_SAMPLE_U8: -            return u8_to_float32ne; -        case PA_SAMPLE_S16LE: -            return pa_sconv_s16le_to_float32ne; -        case PA_SAMPLE_S16BE: -            return pa_sconv_s16be_to_float32ne; -        case PA_SAMPLE_FLOAT32NE: -            return float32ne_to_float32ne; -        case PA_SAMPLE_FLOAT32RE: -            return float32re_to_float32ne; -        case PA_SAMPLE_ALAW: -            return alaw_to_float32ne; -        case PA_SAMPLE_ULAW: -            return ulaw_to_float32ne; -        default: -            return NULL; -    } +static void alaw_to_s16ne(unsigned n, const int8_t *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--, a++, b++) +        *b = st_alaw2linear16(*a);  } -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) { -    switch(f) { -        case PA_SAMPLE_U8: -            return u8_from_float32ne; -        case PA_SAMPLE_S16LE: -            return pa_sconv_s16le_from_float32ne; -        case PA_SAMPLE_S16BE: -            return pa_sconv_s16be_from_float32ne; -        case PA_SAMPLE_FLOAT32NE: -            return float32ne_from_float32ne; -        case PA_SAMPLE_FLOAT32RE: -            return float32re_from_float32ne; -        case PA_SAMPLE_ALAW: -            return alaw_from_float32ne; -        case PA_SAMPLE_ULAW: -            return ulaw_from_float32ne; -        default: -            return NULL; -    } +static void alaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) +        *b = st_13linear2alaw(*a >> 3); +} + +pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) { + +    static const pa_convert_func_t table[] = { +        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_to_float32ne, +        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_to_float32ne, +        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_to_float32ne, +        [PA_SAMPLE_S16LE]     = (pa_convert_func_t) pa_sconv_s16le_to_float32ne, +        [PA_SAMPLE_S16BE]     = (pa_convert_func_t) pa_sconv_s16be_to_float32ne, +        [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne, +        [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne, +    }; + +    pa_assert(f >= 0); +    pa_assert(f < PA_SAMPLE_MAX); + +    return table[f]; +} + +pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) { + +    static const pa_convert_func_t table[] = { +        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_from_float32ne, +        [PA_SAMPLE_S16LE]     = (pa_convert_func_t) pa_sconv_s16le_from_float32ne, +        [PA_SAMPLE_S16BE]     = (pa_convert_func_t) pa_sconv_s16be_from_float32ne, +        [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne, +        [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne, +        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_from_float32ne, +        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_from_float32ne +    }; + +    pa_assert(f >= 0); +    pa_assert(f < PA_SAMPLE_MAX); + +    return table[f]; +} + +pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) { + +    static const pa_convert_func_t table[] = { +        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_to_s16ne, +        [PA_SAMPLE_S16NE]     = (pa_convert_func_t) s16ne_to_s16ne, +        [PA_SAMPLE_S16RE]     = (pa_convert_func_t) s16re_to_s16ne, +        [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_to_s16ne, +        [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_to_s16ne, +        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_to_s16ne, +        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_to_s16ne +    }; + +    pa_assert(f >= 0); +    pa_assert(f < PA_SAMPLE_MAX); + +    return table[f]; +} + +pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) { + +    static const pa_convert_func_t table[] = { +        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_from_s16ne, +        [PA_SAMPLE_S16NE]     = (pa_convert_func_t) s16ne_to_s16ne, +        [PA_SAMPLE_S16RE]     = (pa_convert_func_t) s16re_to_s16ne, +        [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_from_s16ne, +        [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_from_s16ne, +        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_from_s16ne, +        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_from_s16ne, +    }; + +    pa_assert(f >= 0); +    pa_assert(f < PA_SAMPLE_MAX); + +    return table[f];  } diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h index 1e97aad9..5e8fa684 100644 --- a/src/pulsecore/sconv.h +++ b/src/pulsecore/sconv.h @@ -27,10 +27,12 @@  #include <pulse/sample.h> -typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b); -typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b); +typedef void (*pa_convert_func_t)(unsigned n, const void *a, void *b); -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f); -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f); +pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f); +pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f); + +pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f); +pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f);  #endif  | 
