diff options
Diffstat (limited to 'src/pulsecore/sample-util.c')
| -rw-r--r-- | src/pulsecore/sample-util.c | 420 | 
1 files changed, 191 insertions, 229 deletions
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index b42b79d1..9f0f795c 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -31,6 +31,8 @@  #include <liboil/liboilfuncs.h>  #include <liboil/liboil.h> +#include <pulse/timeval.h> +  #include <pulsecore/log.h>  #include <pulsecore/macro.h>  #include <pulsecore/g711.h> @@ -85,7 +87,6 @@ static uint8_t silence_byte(pa_sample_format_t format) {          default:              pa_assert_not_reached();      } -    return 0;  }  void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { @@ -97,56 +98,62 @@ void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {      return p;  } -static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { -    unsigned k; - -    pa_assert(streams); -    pa_assert(spec); +static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { +    unsigned channel; -    for (k = 0; k < nstreams; k++) { -        unsigned channel; +    pa_assert(linear); +    pa_assert(volume); -        for (channel = 0; channel < spec->channels; channel++) { -            pa_mix_info *m = streams + k; -            m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * 0x10000); -        } -    } +    for (channel = 0; channel < volume->channels; channel++) +        linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);  } -static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { +static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {      unsigned channel;      pa_assert(linear);      pa_assert(volume);      for (channel = 0; channel < volume->channels; channel++) -        linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); +        linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]);  } -static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { -    unsigned k; +static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { +    unsigned k, channel; +    float linear[PA_CHANNELS_MAX];      pa_assert(streams);      pa_assert(spec); +    pa_assert(volume); + +    calc_linear_float_volume(linear, volume);      for (k = 0; k < nstreams; k++) { -        unsigned channel;          for (channel = 0; channel < spec->channels; channel++) {              pa_mix_info *m = streams + k; -            m->linear[channel].f = pa_sw_volume_to_linear(m->volume.values[channel]); +            m->linear[channel].i = (int32_t) lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);          }      }  } -static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { -    unsigned channel; +static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { +    unsigned k, channel; +    float linear[PA_CHANNELS_MAX]; -    pa_assert(linear); +    pa_assert(streams); +    pa_assert(spec);      pa_assert(volume); -    for (channel = 0; channel < volume->channels; channel++) -        linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); +    calc_linear_float_volume(linear, volume); + +    for (k = 0; k < nstreams; k++) { + +        for (channel = 0; channel < spec->channels; channel++) { +            pa_mix_info *m = streams + k; +            m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]); +        } +    }  }  size_t pa_mix( @@ -160,7 +167,8 @@ size_t pa_mix(      pa_cvolume full_volume;      unsigned k; -    size_t d = 0; +    unsigned z; +    void *end;      pa_assert(streams);      pa_assert(data); @@ -170,45 +178,46 @@ size_t pa_mix(      if (!volume)          volume = pa_cvolume_reset(&full_volume, spec->channels); +    if (mute || pa_cvolume_is_muted(volume) || nstreams <= 0) { +        pa_silence_memory(data, length, spec); +        return length; +    } +      for (k = 0; k < nstreams; k++)          streams[k].ptr = (uint8_t*) pa_memblock_acquire(streams[k].chunk.memblock) + streams[k].chunk.index; +    for (z = 0; z < nstreams; z++) +        if (length > streams[z].chunk.length) +            length = streams[z].chunk.length; + +    end = (uint8_t*) data + length; +      switch (spec->format) {          case PA_SAMPLE_S16NE:{              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d += sizeof(int16_t)) { +            while (data < end) {                  int32_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      int32_t v, cv = m->linear[channel].i; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = *((int16_t*) m->ptr); -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = *((int16_t*) m->ptr); +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);                  }                  sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); -                sum = (sum * linear[channel]) / 0x10000;                  *((int16_t*) data) = (int16_t) sum;                  data = (uint8_t*) data + sizeof(int16_t); @@ -222,38 +231,28 @@ size_t pa_mix(          case PA_SAMPLE_S16RE:{              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d += sizeof(int16_t)) { +            while (data < end) {                  int32_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      int32_t v, cv = m->linear[channel].i; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = PA_INT16_SWAP(*((int16_t*) m->ptr)); -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = PA_INT16_SWAP(*((int16_t*) m->ptr)); +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);                  }                  sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); -                sum = (sum * linear[channel]) / 0x10000;                  *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);                  data = (uint8_t*) data + sizeof(int16_t); @@ -267,39 +266,29 @@ size_t pa_mix(          case PA_SAMPLE_S32NE:{              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d += sizeof(int32_t)) { +            while (data < end) {                  int64_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i; -                    int64_t v;                      int32_t cv = m->linear[channel].i; +                    int64_t v; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = *((int32_t*) m->ptr); -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = *((int32_t*) m->ptr); +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);                  }                  sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); -                sum = (sum * linear[channel]) / 0x10000;                  *((int32_t*) data) = (int32_t) sum;                  data = (uint8_t*) data + sizeof(int32_t); @@ -313,39 +302,29 @@ size_t pa_mix(          case PA_SAMPLE_S32RE:{              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d += sizeof(int32_t)) { +            while (data < end) {                  int64_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i; -                    int64_t v;                      int32_t cv = m->linear[channel].i; +                    int64_t v; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = PA_INT32_SWAP(*((int32_t*) m->ptr)); -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = PA_INT32_SWAP(*((int32_t*) m->ptr)); +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);                  }                  sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); -                sum = (sum * linear[channel]) / 0x10000;                  *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum);                  data = (uint8_t*) data + sizeof(int32_t); @@ -359,37 +338,27 @@ size_t pa_mix(          case PA_SAMPLE_U8: {              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d ++) { +            while (data < end) {                  int32_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      int32_t v, cv = m->linear[channel].i; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = (int32_t) *((uint8_t*) m->ptr) - 0x80; -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = (int32_t) *((uint8_t*) m->ptr) - 0x80; +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + 1;                  } -                sum = (sum * linear[channel]) / 0x10000;                  sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F);                  *((uint8_t*) data) = (uint8_t) (sum + 0x80); @@ -404,39 +373,29 @@ size_t pa_mix(          case PA_SAMPLE_ULAW: {              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d ++) { +            while (data < end) {                  int32_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      int32_t v, cv = m->linear[channel].i; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + 1;                  }                  sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); -                sum = (sum * linear[channel]) / 0x10000; -                *((uint8_t*) data) = (uint8_t) st_14linear2ulaw(sum >> 2); +                *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2);                  data = (uint8_t*) data + 1; @@ -449,39 +408,29 @@ size_t pa_mix(          case PA_SAMPLE_ALAW: {              unsigned channel = 0; -            int32_t linear[PA_CHANNELS_MAX]; -            calc_linear_integer_stream_volumes(streams, nstreams, spec); -            calc_linear_integer_volume(linear, volume); +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d ++) { +            while (data < end) {                  int32_t sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      int32_t v, cv = m->linear[channel].i; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); -                        v = (v * cv) / 0x10000; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); +                    v = (v * cv) / 0x10000;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + 1;                  }                  sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); -                sum = (sum * linear[channel]) / 0x10000; -                *((uint8_t*) data) = (uint8_t) st_13linear2alaw(sum >> 3); +                *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3);                  data = (uint8_t*) data + 1; @@ -494,37 +443,27 @@ size_t pa_mix(          case PA_SAMPLE_FLOAT32NE: {              unsigned channel = 0; -            float linear[PA_CHANNELS_MAX]; -            calc_linear_float_stream_volumes(streams, nstreams, spec); -            calc_linear_float_volume(linear, volume); +            calc_linear_float_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d += sizeof(float)) { +            while (data < end) {                  float sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      float v, cv = m->linear[channel].f; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        v = *((float*) m->ptr); -                        v *= cv; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = *((float*) m->ptr); +                    v *= cv;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + sizeof(float);                  } -                sum *= linear[channel];                  *((float*) data) = sum;                  data = (uint8_t*) data + sizeof(float); @@ -540,38 +479,27 @@ size_t pa_mix(              unsigned channel = 0;              float linear[PA_CHANNELS_MAX]; -            calc_linear_float_stream_volumes(streams, nstreams, spec); -            calc_linear_float_volume(linear, volume); +            calc_linear_float_stream_volumes(streams, nstreams, volume, spec); -            for (d = 0;; d += sizeof(float)) { +            while (data < end) {                  float sum = 0;                  unsigned i; -                if (PA_UNLIKELY(d >= length)) -                    goto finish; -                  for (i = 0; i < nstreams; i++) {                      pa_mix_info *m = streams + i;                      float v, cv = m->linear[channel].f; -                    if (PA_UNLIKELY(d >= m->chunk.length)) -                        goto finish; - -                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) -                        v = 0; -                    else { -                        uint32_t z = *(uint32_t*) m->ptr; -                        z = PA_UINT32_SWAP(z); -                        v = *((float*) &z); -                        v *= cv; -                    } +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; +                    v = PA_FLOAT32_SWAP(*(float*) m->ptr); +                    v *= cv;                      sum += v; +                      m->ptr = (uint8_t*) m->ptr + sizeof(float);                  } -                sum *= linear[channel]; -                *((uint32_t*) data) = PA_UINT32_SWAP(*(uint32_t*) &sum); +                *((float*) data) = PA_FLOAT32_SWAP(sum);                  data = (uint8_t*) data + sizeof(float); @@ -583,16 +511,14 @@ size_t pa_mix(          }          default: -            pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); +            pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));              pa_assert_not_reached();      } -finish: -      for (k = 0; k < nstreams; k++)          pa_memblock_release(streams[k].chunk.memblock); -    return d; +    return length;  } @@ -624,14 +550,15 @@ void pa_volume_memchunk(      switch (spec->format) {          case PA_SAMPLE_S16NE: { -            int16_t *d; -            size_t n; +            int16_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length/sizeof(int16_t); n > 0; d++, n--) { +            e = (int16_t*) ptr + c->length/sizeof(int16_t); + +            for (channel = 0, d = ptr; d < e; d++) {                  int32_t t;                  t = (int32_t)(*d); @@ -646,17 +573,18 @@ void pa_volume_memchunk(          }          case PA_SAMPLE_S16RE: { -            int16_t *d; -            size_t n; +            int16_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length/sizeof(int16_t); n > 0; d++, n--) { +            e = (int16_t*) ptr + c->length/sizeof(int16_t); + +            for (channel = 0, d = ptr; d < e; d++) {                  int32_t t; -                t = (int32_t)(PA_INT16_SWAP(*d)); +                t = (int32_t) PA_INT16_SWAP(*d);                  t = (t * linear[channel]) / 0x10000;                  t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);                  *d = PA_INT16_SWAP((int16_t) t); @@ -669,14 +597,15 @@ void pa_volume_memchunk(          }          case PA_SAMPLE_S32NE: { -            int32_t *d; -            size_t n; +            int32_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length/sizeof(int32_t); n > 0; d++, n--) { +            e = (int32_t*) ptr + c->length/sizeof(int32_t); + +            for (channel = 0, d = ptr; d < e; d++) {                  int64_t t;                  t = (int64_t)(*d); @@ -691,17 +620,18 @@ void pa_volume_memchunk(          }          case PA_SAMPLE_S32RE: { -            int32_t *d; -            size_t n; +            int32_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length/sizeof(int32_t); n > 0; d++, n--) { +            e = (int32_t*) ptr + c->length/sizeof(int32_t); + +            for (channel = 0, d = ptr; d < e; d++) {                  int64_t t; -                t = (int64_t)(PA_INT32_SWAP(*d)); +                t = (int64_t) PA_INT32_SWAP(*d);                  t = (t * linear[channel]) / 0x10000;                  t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);                  *d = PA_INT32_SWAP((int32_t) t); @@ -714,14 +644,15 @@ void pa_volume_memchunk(          }          case PA_SAMPLE_U8: { -            uint8_t *d; -            size_t n; +            uint8_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { +            e = (uint8_t*) ptr + c->length; + +            for (channel = 0, d = ptr; d < e; d++) {                  int32_t t;                  t = (int32_t) *d - 0x80; @@ -736,20 +667,21 @@ void pa_volume_memchunk(          }          case PA_SAMPLE_ULAW: { -            uint8_t *d; -            size_t n; +            uint8_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { +            e = (uint8_t*) ptr + c->length; + +            for (channel = 0, d = ptr; d < e; d++) {                  int32_t t;                  t = (int32_t) st_ulaw2linear16(*d);                  t = (t * linear[channel]) / 0x10000;                  t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); -                *d = (uint8_t) st_14linear2ulaw(t >> 2); +                *d = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);                  if (PA_UNLIKELY(++channel >= spec->channels))                      channel = 0; @@ -758,20 +690,21 @@ void pa_volume_memchunk(          }          case PA_SAMPLE_ALAW: { -            uint8_t *d; -            size_t n; +            uint8_t *d, *e;              unsigned channel;              int32_t linear[PA_CHANNELS_MAX];              calc_linear_integer_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { +            e = (uint8_t*) ptr + c->length; + +            for (channel = 0, d = ptr; d < e; d++) {                  int32_t t;                  t = (int32_t) st_alaw2linear16(*d);                  t = (t * linear[channel]) / 0x10000;                  t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); -                *d = (uint8_t) st_13linear2alaw(t >> 3); +                *d = (uint8_t) st_13linear2alaw((int16_t) t >> 3);                  if (PA_UNLIKELY(++channel >= spec->channels))                      channel = 0; @@ -786,8 +719,8 @@ void pa_volume_memchunk(              unsigned channel;              d = ptr; -            skip = spec->channels * sizeof(float); -            n = c->length/sizeof(float)/spec->channels; +            skip = (int) (spec->channels * sizeof(float)); +            n = (unsigned) (c->length/sizeof(float)/spec->channels);              for (channel = 0; channel < spec->channels; channel ++) {                  float v, *t; @@ -797,28 +730,26 @@ void pa_volume_memchunk(                  v = (float) pa_sw_volume_to_linear(volume->values[channel]);                  t = d + channel; -                oil_scalarmult_f32(t, skip, t, skip, &v, n); +                oil_scalarmult_f32(t, skip, t, skip, &v, (int) n);              }              break;          }          case PA_SAMPLE_FLOAT32RE: { -            uint32_t *d; -            size_t n; +            float *d, *e;              unsigned channel;              float linear[PA_CHANNELS_MAX];              calc_linear_float_volume(linear, volume); -            for (channel = 0, d = ptr, n = c->length/sizeof(float); n > 0; d++, n--) { +            e = (float*) ptr + c->length/sizeof(float); + +            for (channel = 0, d = ptr; d < e; d++) {                  float t; -                uint32_t z; -                z = PA_UINT32_SWAP(*d); -                t = *(float*) &z; +                t = PA_FLOAT32_SWAP(*d);                  t *= linear[channel]; -                z = *(uint32_t*) &t; -                *d = PA_UINT32_SWAP(z); +                *d = PA_FLOAT32_SWAP(t);                  if (PA_UNLIKELY(++channel >= spec->channels))                      channel = 0; @@ -846,7 +777,7 @@ size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {      return (l/fs) * fs;  } -int pa_frame_aligned(size_t l, const pa_sample_spec *ss) { +pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) {      size_t fs;      pa_assert(ss); @@ -877,7 +808,7 @@ void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, u          d = (uint8_t*) dst + c * ss;          for (j = 0; j < n; j ++) { -            oil_memcpy(d, s, ss); +            oil_memcpy(d, s, (int) ss);              s = (uint8_t*) s + ss;              d = (uint8_t*) d + fs;          } @@ -905,7 +836,7 @@ void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss,          d = dst[c];          for (j = 0; j < n; j ++) { -            oil_memcpy(d, s, ss); +            oil_memcpy(d, s, (int) ss);              s = (uint8_t*) s + fs;              d = (uint8_t*) d + ss;          } @@ -1008,7 +939,7 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo      if (format == PA_SAMPLE_FLOAT32NE) {          float minus_one = -1.0, plus_one = 1.0; -        oil_clip_f32(d, dstr, s, sstr, n, &minus_one, &plus_one); +        oil_clip_f32(d, (int) dstr, s, (int) sstr, (int) n, &minus_one, &plus_one);      } else {          pa_assert(format == PA_SAMPLE_FLOAT32RE); @@ -1017,7 +948,7 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo              float f;              f = PA_FLOAT32_SWAP(*s); -            f = PA_CLAMP_UNLIKELY(f, -1.0, 1.0); +            f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);              *d = PA_FLOAT32_SWAP(f);              s = (const float*) ((const uint8_t*) s + sstr); @@ -1025,3 +956,34 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo          }      }  } + +/* Similar to pa_bytes_to_usec() but rounds up, not down */ + +pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) { +    size_t fs; +    pa_usec_t usec; + +    pa_assert(spec); + +    fs = pa_frame_size(spec); +    length = (length + fs - 1) / fs; + +    usec = (pa_usec_t) length * PA_USEC_PER_SEC; + +    return (usec + spec->rate - 1) / spec->rate; +} + +/* Similar to pa_usec_to_bytes() but rounds up, not down */ + +size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) { +    uint64_t u; +    pa_assert(spec); + +    u = (uint64_t) t * (uint64_t) spec->rate; + +    u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC; + +    u *= pa_frame_size(spec); + +    return (size_t) u; +}  | 
