diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-01-16 03:15:39 +0100 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-01-16 03:15:39 +0100 | 
| commit | 6dc76d11583979ba73dbe4bbf54f52fc1af901e2 (patch) | |
| tree | e8f1825194108d0dc8444a4e7d35c1735141f30f | |
| parent | 9955398fdafc58f23a86fc05f4832b5846b3b040 (diff) | |
add support for 24bit packed samples
| -rw-r--r-- | src/modules/alsa/alsa-util.c | 8 | ||||
| -rw-r--r-- | src/modules/oss/oss-util.c | 2 | ||||
| -rw-r--r-- | src/pulse/sample.c | 16 | ||||
| -rw-r--r-- | src/pulse/sample.h | 26 | ||||
| -rw-r--r-- | src/pulse/stream.c | 1 | ||||
| -rw-r--r-- | src/pulsecore/endianmacros.h | 38 | ||||
| -rw-r--r-- | src/pulsecore/envelope.c | 1 | ||||
| -rw-r--r-- | src/pulsecore/protocol-native.c | 7 | ||||
| -rw-r--r-- | src/pulsecore/resampler.c | 4 | ||||
| -rw-r--r-- | src/pulsecore/sample-util.c | 123 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16be.c | 16 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16be.h | 20 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16le.c | 112 | ||||
| -rw-r--r-- | src/pulsecore/sconv-s16le.h | 20 | ||||
| -rw-r--r-- | src/pulsecore/sconv.c | 8 | 
15 files changed, 370 insertions, 32 deletions
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 871471f1..7616ad1d 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -232,6 +232,8 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s          [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,          [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,          [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE, +        [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE, +        [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,      };      static const pa_sample_format_t try_order[] = { @@ -239,6 +241,8 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s          PA_SAMPLE_FLOAT32RE,          PA_SAMPLE_S32NE,          PA_SAMPLE_S32RE, +        PA_SAMPLE_S24NE, +        PA_SAMPLE_S24RE,          PA_SAMPLE_S16NE,          PA_SAMPLE_S16RE,          PA_SAMPLE_ALAW, @@ -259,6 +263,10 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s          *f = PA_SAMPLE_FLOAT32LE;      else if (*f == PA_SAMPLE_FLOAT32LE)          *f = PA_SAMPLE_FLOAT32BE; +    else if (*f == PA_SAMPLE_S24BE) +        *f = PA_SAMPLE_S24LE; +    else if (*f == PA_SAMPLE_S24LE) +        *f = PA_SAMPLE_S24BE;      else if (*f == PA_SAMPLE_S16BE)          *f = PA_SAMPLE_S16LE;      else if (*f == PA_SAMPLE_S16LE) diff --git a/src/modules/oss/oss-util.c b/src/modules/oss/oss-util.c index f766030d..fbe930cd 100644 --- a/src/modules/oss/oss-util.c +++ b/src/modules/oss/oss-util.c @@ -164,6 +164,8 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) {          [PA_SAMPLE_FLOAT32BE] = AFMT_QUERY, /* not supported */          [PA_SAMPLE_S32LE] = AFMT_QUERY, /* not supported */          [PA_SAMPLE_S32BE] = AFMT_QUERY, /* not supported */ +        [PA_SAMPLE_S24LE] = AFMT_QUERY, /* not supported */ +        [PA_SAMPLE_S24BE] = AFMT_QUERY, /* not supported */      };      pa_assert(fd >= 0); diff --git a/src/pulse/sample.c b/src/pulse/sample.c index 29501595..8228a9bb 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -48,6 +48,8 @@ size_t pa_sample_size(const pa_sample_spec *spec) {          [PA_SAMPLE_FLOAT32BE] = 4,          [PA_SAMPLE_S32LE] = 4,          [PA_SAMPLE_S32BE] = 4, +        [PA_SAMPLE_S24LE] = 3, +        [PA_SAMPLE_S24BE] = 3      };      pa_assert(spec); @@ -125,6 +127,8 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) {          [PA_SAMPLE_FLOAT32BE] = "float32be",          [PA_SAMPLE_S32LE] = "s32le",          [PA_SAMPLE_S32BE] = "s32be", +        [PA_SAMPLE_S24LE] = "s24le", +        [PA_SAMPLE_S24BE] = "s24be",      };      if (f < 0 || f >= PA_SAMPLE_MAX) @@ -194,8 +198,16 @@ pa_sample_format_t pa_parse_sample_format(const char *format) {          return PA_SAMPLE_S32BE;      else if (strcasecmp(format, "s32ne") == 0 || strcasecmp(format, "s32") == 0 || strcasecmp(format, "32") == 0)          return PA_SAMPLE_S32NE; -    else if (strcasecmp(format, "s32re") == 0) -        return PA_SAMPLE_S32RE; +    else if (strcasecmp(format, "s24re") == 0) +        return PA_SAMPLE_S24RE; +    else if (strcasecmp(format, "s24le") == 0) +        return PA_SAMPLE_S24LE; +    else if (strcasecmp(format, "s24be") == 0) +        return PA_SAMPLE_S24BE; +    else if (strcasecmp(format, "s24ne") == 0 || strcasecmp(format, "s24") == 0 || strcasecmp(format, "24") == 0) +        return PA_SAMPLE_S24NE; +    else if (strcasecmp(format, "s24re") == 0) +        return PA_SAMPLE_S24RE;      return -1;  } diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 3c7dd0e7..8d09d32e 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -51,6 +51,8 @@   * \li PA_SAMPLE_ULAW - 8 bit mu-Law.   * \li PA_SAMPLE_S32LE - Signed 32 bit integer PCM, little endian.   * \li PA_SAMPLE_S32BE - Signed 32 bit integer PCM, big endian. + * \li PA_SAMPLE_242LE - Signed 24 bit integer PCM packed, little endian. + * \li PA_SAMPLE_242BE - Signed 24 bit integer PCM packed, big endian.   *   * The floating point sample formats have the range from -1.0 to 1.0.   * @@ -145,7 +147,13 @@ typedef enum pa_sample_format {      /**< Signed 32 Bit PCM, little endian (PC) */      PA_SAMPLE_S32BE, -    /**< Signed 32 Bit PCM, big endian (PC) */ +    /**< Signed 32 Bit PCM, big endian */ + +    PA_SAMPLE_S24LE, +    /**< Signed 24 Bit PCM packed, little endian (PC) */ + +    PA_SAMPLE_S24BE, +    /**< Signed 24 Bit PCM packed, big endian */      PA_SAMPLE_MAX,      /**< Upper limit of valid sample types */ @@ -161,12 +169,16 @@ typedef enum pa_sample_format {  #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE  /** Signed 32 Bit PCM, native endian */  #define PA_SAMPLE_S32NE PA_SAMPLE_S32BE +/** Signed 24 Bit PCM packed, native endian */ +#define PA_SAMPLE_S24NE PA_SAMPLE_S24BE  /** Signed 16 Bit PCM reverse endian */  #define PA_SAMPLE_S16RE PA_SAMPLE_S16LE  /** 32 Bit IEEE floating point, reverse endian */  #define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32LE -/** Signed 32 Bit PCM reverse endian */ +/** Signed 32 Bit PCM, reverse endian */  #define PA_SAMPLE_S32RE PA_SAMPLE_S32LE +/** Signed 24 Bit PCM, packed reverse endian */ +#define PA_SAMPLE_S24RE PA_SAMPLE_242LE  #else  /** Signed 16 Bit PCM, native endian */  #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE @@ -174,12 +186,16 @@ typedef enum pa_sample_format {  #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE  /** Signed 32 Bit PCM, native endian */  #define PA_SAMPLE_S32NE PA_SAMPLE_S32LE -/** Signed 16 Bit PCM reverse endian */ +/** Signed 24 Bit PCM packed, native endian */ +#define PA_SAMPLE_S24NE PA_SAMPLE_S24LE +/** Signed 16 Bit PCM, reverse endian */  #define PA_SAMPLE_S16RE PA_SAMPLE_S16BE  /** 32 Bit IEEE floating point, reverse endian */  #define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32BE -/** Signed 32 Bit PCM reverse endian */ +/** Signed 32 Bit PCM, reverse endian */  #define PA_SAMPLE_S32RE PA_SAMPLE_S32BE +/** Signed 24 Bit PCM packed, reverse endian */ +#define PA_SAMPLE_S24RE PA_SAMPLE_S24BE  #endif  /** A Shortcut for PA_SAMPLE_FLOAT32NE */ @@ -196,6 +212,8 @@ typedef enum pa_sample_format {  #define PA_SAMPLE_FLOAT32BE PA_SAMPLE_FLOAT32BE  #define PA_SAMPLE_S32LE PA_SAMPLE_S32LE  #define PA_SAMPLE_S32BE PA_SAMPLE_S32BE +#define PA_SAMPLE_S24LE PA_SAMPLE_S24LE +#define PA_SAMPLE_S24BE PA_SAMPLE_S24BE  /** \endcond */  /** A sample format and attribute specification */ diff --git a/src/pulse/stream.c b/src/pulse/stream.c index c0ae4ac2..2a958e04 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -87,6 +87,7 @@ pa_stream *pa_stream_new_with_proplist(      PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);      PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE && ss->format != PA_SAMPLE_S32BE), PA_ERR_NOTSUPPORTED); +    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15 || (ss->format != PA_SAMPLE_S24LE && ss->format != PA_SAMPLE_S24BE), PA_ERR_NOTSUPPORTED);      PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);      PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID); diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h index 85bebd68..eea1c743 100644 --- a/src/pulsecore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -45,6 +45,32 @@  #define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) (x) >> 24) | ((uint32_t) (x) << 24) | (((uint32_t) (x) & 0xFF00) << 8) | ((((uint32_t) (x)) >> 8) & 0xFF00) ) )  #endif +static inline uint32_t PA_READ24LE(const uint8_t *p) { +    return +        ((uint32_t) p[0] << 16) | +        ((uint32_t) p[1] << 8) | +        ((uint32_t) p[2]); +} + +static inline uint32_t PA_READ24BE(const uint8_t *p) { +    return +        ((uint32_t) p[2] << 16) | +        ((uint32_t) p[1] << 8) | +        ((uint32_t) p[0]); +} + +static inline void PA_WRITE24LE(uint8_t *p, uint32_t u) { +    p[0] = (uint8_t) (u >> 16); +    p[1] = (uint8_t) (u >> 8); +    p[2] = (uint8_t) u; +} + +static inline void PA_WRITE24BE(uint8_t *p, uint32_t u) { +    p[2] = (uint8_t) (u >> 16); +    p[1] = (uint8_t) (u >> 8); +    p[0] = (uint8_t) u; +} +  static inline float PA_FLOAT32_SWAP(float x) {      union {          float f; @@ -91,6 +117,12 @@ static inline float PA_FLOAT32_SWAP(float x) {   #define PA_FLOAT32_TO_LE(x) PA_FLOAT32_SWAP(x)   #define PA_FLOAT32_TO_BE(x) ((float) (x)) + + #define PA_READ24NE(x) PA_READ24BE(x) + #define PA_WRITE24NE(x,y) PA_WRITE24BE((x),(y)) + + #define PA_READ24RE(x) PA_READ24LE(x) + #define PA_WRITE24RE(x,y) PA_WRITE24LE((x),(y))  #else   #define PA_INT16_FROM_LE(x) ((int16_t)(x))   #define PA_INT16_FROM_BE(x) PA_INT16_SWAP(x) @@ -118,6 +150,12 @@ static inline float PA_FLOAT32_SWAP(float x) {   #define PA_FLOAT32_TO_LE(x) ((float) (x))   #define PA_FLOAT32_TO_BE(x) PA_FLOAT32_SWAP(x) + + #define PA_READ24NE(x) PA_READ24LE(x) + #define PA_WRITE24NE(x,y) PA_WRITE24LE((x),(y)) + + #define PA_READ24RE(x) PA_READ24BE(x) + #define PA_WRITE24RE(x,y) PA_WRITE24BE((x),(y))  #endif  #endif diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c index 7f2252e9..f872d347 100644 --- a/src/pulsecore/envelope.c +++ b/src/pulsecore/envelope.c @@ -600,7 +600,6 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {          switch (e->sample_spec.format) { -              case PA_SAMPLE_U8: {                  uint8_t *t; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index af013da3..b1ef64f2 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2640,6 +2640,13 @@ static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, co          if (fixed->format == PA_SAMPLE_S32BE)              fixed->format = PA_SAMPLE_FLOAT32BE;      } + +    if (c->version < 15) { +        if (fixed->format == PA_SAMPLE_S24LE) +            fixed->format = PA_SAMPLE_FLOAT32LE; +        if (fixed->format == PA_SAMPLE_S24BE) +            fixed->format = PA_SAMPLE_FLOAT32BE; +    }  }  static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) { diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index f0515ebe..67c37581 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -257,8 +257,10 @@ pa_resampler* pa_resampler_new(              if (a->format == PA_SAMPLE_S32NE || a->format == PA_SAMPLE_S32RE ||                  a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE || +                a->format == PA_SAMPLE_S24NE || a->format == PA_SAMPLE_S24RE ||                  b->format == PA_SAMPLE_S32NE || b->format == PA_SAMPLE_S32RE || -                b->format == PA_SAMPLE_FLOAT32NE || b->format == PA_SAMPLE_FLOAT32RE) +                b->format == PA_SAMPLE_FLOAT32NE || b->format == PA_SAMPLE_FLOAT32RE || +                b->format == PA_SAMPLE_S24NE || b->format == PA_SAMPLE_S24RE)                  r->work_format = PA_SAMPLE_FLOAT32NE;              else                  r->work_format = PA_SAMPLE_S16NE; diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 3be08efd..533181b8 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -83,6 +83,8 @@ static uint8_t silence_byte(pa_sample_format_t format) {          case PA_SAMPLE_S32BE:          case PA_SAMPLE_FLOAT32LE:          case PA_SAMPLE_FLOAT32BE: +        case PA_SAMPLE_S24LE: +        case PA_SAMPLE_S24BE:              return 0;          case PA_SAMPLE_ALAW:              return 0xd5; @@ -340,6 +342,78 @@ size_t pa_mix(              break;          } +        case PA_SAMPLE_S24NE: { +            unsigned channel = 0; + +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); + +            while (data < end) { +                int64_t sum = 0; +                unsigned i; + +                for (i = 0; i < nstreams; i++) { +                    pa_mix_info *m = streams + i; +                    int32_t cv = m->linear[channel].i; +                    int64_t v; + +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; + +                    v = (int32_t) (PA_READ24NE(m->ptr) << 8); +                    v = (v * cv) / 0x10000; +                    sum += v; + +                    m->ptr = (uint8_t*) m->ptr + 3; +                } + +                sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); +                PA_WRITE24NE(data, ((uint32_t) sum) >> 8); + +                data = (uint8_t*) data + 3; + +                if (PA_UNLIKELY(++channel >= spec->channels)) +                    channel = 0; +            } + +            break; +        } + +        case PA_SAMPLE_S24RE: { +            unsigned channel = 0; + +            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); + +            while (data < end) { +                int64_t sum = 0; +                unsigned i; + +                for (i = 0; i < nstreams; i++) { +                    pa_mix_info *m = streams + i; +                    int32_t cv = m->linear[channel].i; +                    int64_t v; + +                    if (PA_UNLIKELY(cv <= 0)) +                        continue; + +                    v = (int32_t) (PA_READ24RE(m->ptr) << 8); +                    v = (v * cv) / 0x10000; +                    sum += v; + +                    m->ptr = (uint8_t*) m->ptr + 3; +                } + +                sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); +                PA_WRITE24RE(data, ((uint32_t) sum) >> 8); + +                data = (uint8_t*) data + 3; + +                if (PA_UNLIKELY(++channel >= spec->channels)) +                    channel = 0; +            } + +            break; +        } +          case PA_SAMPLE_U8: {              unsigned channel = 0; @@ -642,7 +716,52 @@ void pa_volume_memchunk(                  if (PA_UNLIKELY(++channel >= spec->channels))                      channel = 0;              } +            break; +        } + +        case PA_SAMPLE_S24NE: { +            uint8_t *d, *e; +            unsigned channel; +            int32_t linear[PA_CHANNELS_MAX]; + +            calc_linear_integer_volume(linear, volume); + +            e = (uint8_t*) ptr + c->length/3; + +            for (channel = 0, d = ptr; d < e; d++) { +                int64_t t; +                t = (int64_t)((int32_t) (PA_READ24NE(d) << 8)); +                t = (t * linear[channel]) / 0x10000; +                t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                PA_WRITE24NE(d, ((uint32_t) (int32_t) t) >> 8); + +                if (PA_UNLIKELY(++channel >= spec->channels)) +                    channel = 0; +            } +            break; +        } + +        case PA_SAMPLE_S24RE: { +            uint8_t *d, *e; +            unsigned channel; +            int32_t linear[PA_CHANNELS_MAX]; + +            calc_linear_integer_volume(linear, volume); + +            e = (uint8_t*) ptr + c->length/3; + +            for (channel = 0, d = ptr; d < e; d++) { +                int64_t t; + +                t = (int64_t)((int32_t) (PA_READ24RE(d) << 8)); +                t = (t * linear[channel]) / 0x10000; +                t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                PA_WRITE24RE(d, ((uint32_t) (int32_t) t) >> 8); + +                if (PA_UNLIKELY(++channel >= spec->channels)) +                    channel = 0; +            }              break;          } @@ -900,12 +1019,16 @@ pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool,              case PA_SAMPLE_S16BE:              case PA_SAMPLE_S32LE:              case PA_SAMPLE_S32BE: +            case PA_SAMPLE_S24LE: +            case PA_SAMPLE_S24BE:              case PA_SAMPLE_FLOAT32LE:              case PA_SAMPLE_FLOAT32BE:                  cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);                  cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);                  cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);                  cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b); +                cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b); +                cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b);                  cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);                  cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);                  break; diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c index e7e1449a..d6137d39 100644 --- a/src/pulsecore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -31,24 +31,34 @@  #define INT32_FROM PA_INT32_FROM_BE  #define INT32_TO PA_INT32_TO_BE +#define READ24 PA_READ24BE +#define WRITE24 PA_WRITE24BE +  #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  #define pa_sconv_s32le_to_float32ne pa_sconv_s32be_to_float32ne  #define pa_sconv_s32le_from_float32ne pa_sconv_s32be_from_float32ne -  #define pa_sconv_s32le_to_float32re pa_sconv_s32be_to_float32re  #define pa_sconv_s32le_from_float32re pa_sconv_s32be_from_float32re +#define pa_sconv_s24le_to_float32ne pa_sconv_s24be_to_float32ne +#define pa_sconv_s24le_from_float32ne pa_sconv_s24be_from_float32ne +#define pa_sconv_s24le_to_float32re pa_sconv_s24be_to_float32re +#define pa_sconv_s24le_from_float32re pa_sconv_s24be_from_float32re +  #define pa_sconv_s32le_to_s16ne pa_sconv_s32be_to_s16ne  #define pa_sconv_s32le_from_s16ne pa_sconv_s32be_from_s16ne -  #define pa_sconv_s32le_to_s16re pa_sconv_s32be_to_s16re  #define pa_sconv_s32le_from_s16re pa_sconv_s32be_from_s16re +#define pa_sconv_s24le_to_s16ne pa_sconv_s24be_to_s16ne +#define pa_sconv_s24le_from_s16ne pa_sconv_s24be_from_s16ne +#define pa_sconv_s24le_to_s16re pa_sconv_s24be_to_s16re +#define pa_sconv_s24le_from_s16re pa_sconv_s24be_from_s16re +  #ifdef WORDS_BIGENDIAN  #define SWAP_WORDS 0  #else diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h index 60580815..1b88fd45 100644 --- a/src/pulsecore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -34,26 +34,26 @@ void pa_sconv_s32be_from_float32ne(unsigned n, const float *a, int32_t *b);  void pa_sconv_s32be_to_float32re(unsigned n, const int32_t *a, float *b);  void pa_sconv_s32be_from_float32re(unsigned n, const float *a, int32_t *b); +void pa_sconv_s24be_to_float32ne(unsigned n, const uint8_t *a, float *b); +void pa_sconv_s24be_from_float32ne(unsigned n, const float *a, uint8_t *b); +void pa_sconv_s24be_to_float32re(unsigned n, const uint8_t *a, float *b); +void pa_sconv_s24be_from_float32re(unsigned n, const float *a, uint8_t *b); +  void pa_sconv_s32be_to_s16ne(unsigned n, const int32_t *a, int16_t *b);  void pa_sconv_s32be_from_s16ne(unsigned n, const int16_t *a, int32_t *b);  void pa_sconv_s32be_to_s16re(unsigned n, const int32_t *a, int16_t *b);  void pa_sconv_s32be_from_s16re(unsigned n, const int16_t *a, int32_t *b); +void pa_sconv_s24be_to_s16ne(unsigned n, const uint8_t *a, int16_t *b); +void pa_sconv_s24be_from_s16ne(unsigned n, const int16_t *a, uint8_t *b); +void pa_sconv_s24be_to_s16re(unsigned n, const uint8_t *a, int16_t *b); +void pa_sconv_s24be_from_s16re(unsigned n, const int16_t *a, uint8_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 - -#define pa_sconv_float32be_to_s32ne pa_sconv_s32be_from_float32ne -#define pa_sconv_float32be_from_s32ne pa_sconv_s32be_to_float32ne -#define pa_sconv_float32le_to_s32ne pa_sconv_s32be_from_float32re -#define pa_sconv_float32le_from_s32ne pa_sconv_s32be_to_float32re - -#define pa_sconv_s16be_to_s32ne pa_sconv_s32be_from_s16ne -#define pa_sconv_s16be_from_s32ne pa_sconv_s32be_to_s16ne -#define pa_sconv_s16le_to_s32ne pa_sconv_s32be_from_s16re -#define pa_sconv_s16le_from_s32ne pa_sconv_s32be_to_s16re  #endif  #endif diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 159c4655..37ebc983 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -23,7 +23,7 @@  #include <config.h>  #endif -/* Despite the name of this file we implement S32 handling here, too. */ +/* Despite the name of this file we implement S32 and S24 handling here, too. */  #include <inttypes.h>  #include <stdio.h> @@ -54,6 +54,14 @@  #define INT32_TO PA_INT32_TO_LE  #endif +#ifndef READ24 +#define READ24 PA_READ24LE +#endif + +#ifndef WRITE24 +#define WRITE24 PA_WRITE24LE +#endif +  #ifndef SWAP_WORDS  #ifdef WORDS_BIGENDIAN  #define SWAP_WORDS 1 @@ -243,3 +251,105 @@ void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b) {          b++;      }  } + +void pa_sconv_s24le_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        *b = (int16_t) (READ24(a) >> 8); +        a += 3; +        b++; +    } +} + +void pa_sconv_s24le_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        WRITE24(b, ((uint32_t) *a) << 8); +        a++; +        b += 3; +    } +} + +void pa_sconv_s24le_to_s16re(unsigned n, const uint8_t *a, int16_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        int16_t s = (int16_t) (READ24(a) >> 8); +        *b = PA_INT16_SWAP(s); +        a += 3; +        b++; +    } +} + +void pa_sconv_s24le_from_s16re(unsigned n, const int16_t *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        uint32_t s = ((uint32_t) PA_INT16_SWAP(*a)) << 8; +        WRITE24(b, s); +        a++; +        b += 3; +    } +} + +void pa_sconv_s24le_to_float32ne(unsigned n, const uint8_t *a, float *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        int32_t s = READ24(a) << 8; +        *b = ((float) s) / 0x7FFFFFFF; +        a += 3; +        b ++; +    } +} + +void pa_sconv_s24le_from_float32ne(unsigned n, const float *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        int32_t s; +        float v = *a; +        v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); +        s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF); +        WRITE24(b, ((uint32_t) s) >> 8); +        a++; +        b+=3; +    } +} + +void pa_sconv_s24le_to_float32re(unsigned n, const uint8_t *a, float *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        int32_t s = READ24(a) << 8; +        float k = ((float) s) / 0x7FFFFFFF; +        *b = PA_FLOAT32_SWAP(k); +        a += 3; +        b ++; +    } +} + +void pa_sconv_s24le_from_float32re(unsigned n, const float *a, uint8_t *b) { +    pa_assert(a); +    pa_assert(b); + +    for (; n > 0; n--) { +        int32_t s; +        float v = *a; +        v = PA_FLOAT32_SWAP(v); +        v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); +        s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF); +        WRITE24(b, ((uint32_t) s) >> 8); +        a++; +        b+=3; +    } +} diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h index 8d4c87c3..b853515c 100644 --- a/src/pulsecore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -34,26 +34,26 @@ void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b);  void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b);  void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b); +void pa_sconv_s24le_to_float32ne(unsigned n, const uint8_t *a, float *b); +void pa_sconv_s24le_from_float32ne(unsigned n, const float *a, uint8_t *b); +void pa_sconv_s24le_to_float32re(unsigned n, const uint8_t *a, float *b); +void pa_sconv_s24le_from_float32re(unsigned n, const float *a, uint8_t *b); +  void pa_sconv_s32le_to_s16ne(unsigned n, const int32_t *a, int16_t *b);  void pa_sconv_s32le_from_s16ne(unsigned n, const int16_t *a, int32_t *b);  void pa_sconv_s32le_to_s16re(unsigned n, const int32_t *a, int16_t *b);  void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b); +void pa_sconv_s24le_to_s16ne(unsigned n, const uint8_t *a, int16_t *b); +void pa_sconv_s24le_from_s16ne(unsigned n, const int16_t *a, uint8_t *b); +void pa_sconv_s24le_to_s16re(unsigned n, const uint8_t *a, int16_t *b); +void pa_sconv_s24le_from_s16re(unsigned n, const int16_t *a, uint8_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 - -#define pa_sconv_float32be_to_s32ne pa_sconv_s32le_from_float32re -#define pa_sconv_float32be_from_s32ne pa_sconv_s32le_to_float32re -#define pa_sconv_float32le_to_s32ne pa_sconv_s32le_from_float32ne -#define pa_sconv_float32le_from_s32ne pa_sconv_s32le_to_float32ne - -#define pa_sconv_s16be_to_s32ne pa_sconv_s32le_from_s16re -#define pa_sconv_s16be_from_s32ne pa_sconv_s32le_to_s16re -#define pa_sconv_s16le_to_s32ne pa_sconv_s32le_from_s16ne -#define pa_sconv_s16le_from_s32ne pa_sconv_s32le_to_s16ne  #endif  #endif diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 6c4d420e..13700c12 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -198,6 +198,8 @@ pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) {          [PA_SAMPLE_S16BE]     = (pa_convert_func_t) pa_sconv_s16be_to_float32ne,          [PA_SAMPLE_S32LE]     = (pa_convert_func_t) pa_sconv_s32le_to_float32ne,          [PA_SAMPLE_S32BE]     = (pa_convert_func_t) pa_sconv_s32be_to_float32ne, +        [PA_SAMPLE_S24LE]     = (pa_convert_func_t) pa_sconv_s24le_to_float32ne, +        [PA_SAMPLE_S24BE]     = (pa_convert_func_t) pa_sconv_s24be_to_float32ne,          [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne,          [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne,      }; @@ -216,6 +218,8 @@ pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) {          [PA_SAMPLE_S16BE]     = (pa_convert_func_t) pa_sconv_s16be_from_float32ne,          [PA_SAMPLE_S32LE]     = (pa_convert_func_t) pa_sconv_s32le_from_float32ne,          [PA_SAMPLE_S32BE]     = (pa_convert_func_t) pa_sconv_s32be_from_float32ne, +        [PA_SAMPLE_S24LE]     = (pa_convert_func_t) pa_sconv_s24le_from_float32ne, +        [PA_SAMPLE_S24BE]     = (pa_convert_func_t) pa_sconv_s24be_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, @@ -238,6 +242,8 @@ pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) {          [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_to_s16ne,          [PA_SAMPLE_S32BE]     = (pa_convert_func_t) pa_sconv_s32be_to_s16ne,          [PA_SAMPLE_S32LE]     = (pa_convert_func_t) pa_sconv_s32le_to_s16ne, +        [PA_SAMPLE_S24BE]     = (pa_convert_func_t) pa_sconv_s24be_to_s16ne, +        [PA_SAMPLE_S24LE]     = (pa_convert_func_t) pa_sconv_s24le_to_s16ne,          [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_to_s16ne,          [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_to_s16ne      }; @@ -258,6 +264,8 @@ pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) {          [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_from_s16ne,          [PA_SAMPLE_S32BE]     = (pa_convert_func_t) pa_sconv_s32be_from_s16ne,          [PA_SAMPLE_S32LE]     = (pa_convert_func_t) pa_sconv_s32le_from_s16ne, +        [PA_SAMPLE_S24BE]     = (pa_convert_func_t) pa_sconv_s24be_from_s16ne, +        [PA_SAMPLE_S24LE]     = (pa_convert_func_t) pa_sconv_s24le_from_s16ne,          [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_from_s16ne,          [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_from_s16ne,      };  | 
