diff --git a/include/lc3.h b/include/lc3.h index f590639..db16e46 100644 --- a/include/lc3.h +++ b/include/lc3.h @@ -151,14 +151,18 @@ extern "C" { /** * PCM Sample Format - * S16 Signed 16 bits, in 16 bits words (int16_t) - * S24 Signed 24 bits, using low three bytes of 32 bits words (int32_t). - * The high byte sign extends the sample value (bits 31..24 set to b23). + * S16 Signed 16 bits, in 16 bits words (int16_t) + * S24 Signed 24 bits, using low three bytes of 32 bits words (int32_t). + * The high byte sign extends (bits 31..24 set to b23). + * S24_3LE Signed 24 bits packed in 3 bytes little endian + * FLOAT Floating point 32 bits (float type), in range -1 to 1 */ enum lc3_pcm_format { LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24, + LC3_PCM_FORMAT_S24_3LE, + LC3_PCM_FORMAT_FLOAT, }; diff --git a/src/lc3.c b/src/lc3.c index 219e381..0e5066e 100644 --- a/src/lc3.c +++ b/src/lc3.c @@ -161,10 +161,8 @@ static void load_s16( float *xs = encoder->xs; int ns = LC3_NS(dt, sr); - for (int i = 0; i < ns; i++) { - int16_t in = pcm[i*stride]; - xt[i] = in, xs[i] = in; - } + for (int i = 0; i < ns; i++, pcm += stride) + xt[i] = *pcm, xs[i] = *pcm; } /** @@ -184,11 +182,59 @@ static void load_s24( float *xs = encoder->xs; int ns = LC3_NS(dt, sr); - for (int i = 0; i < ns; i++) { - int32_t in = pcm[i*stride]; + for (int i = 0; i < ns; i++, pcm += stride) { + xt[i] = *pcm >> 8; + xs[i] = ldexpf(*pcm, -8); + } +} - xt[i] = in >> 8; - xs[i] = ldexpf(in, -8); +/** + * Input PCM Samples from signed 24 bits packed + * encoder Encoder state + * pcm, stride Input PCM samples, and count between two consecutives + */ +static void load_s24_3le( + struct lc3_encoder *encoder, const void *_pcm, int stride) +{ + const uint8_t *pcm = _pcm; + + enum lc3_dt dt = encoder->dt; + enum lc3_srate sr = encoder->sr_pcm; + + int16_t *xt = encoder->xt; + float *xs = encoder->xs; + int ns = LC3_NS(dt, sr); + + for (int i = 0; i < ns; i++, pcm += 3*stride) { + int32_t in = ((uint32_t)pcm[0] << 8) | + ((uint32_t)pcm[1] << 16) | + ((uint32_t)pcm[2] << 24) ; + + xt[i] = in >> 16; + xs[i] = ldexpf(in, -16); + } +} + +/** + * Input PCM Samples from float 32 bits + * encoder Encoder state + * pcm, stride Input PCM samples, and count between two consecutives + */ +static void load_float( + struct lc3_encoder *encoder, const void *_pcm, int stride) +{ + const float *pcm = _pcm; + + enum lc3_dt dt = encoder->dt; + enum lc3_srate sr = encoder->sr_pcm; + + int16_t *xt = encoder->xt; + float *xs = encoder->xs; + int ns = LC3_NS(dt, sr); + + for (int i = 0; i < ns; i++, pcm += stride) { + xs[i] = ldexpf(*pcm, 15); + xt[i] = LC3_SAT16((int32_t)xs[i]); } } @@ -335,8 +381,10 @@ int lc3_encode(struct lc3_encoder *encoder, enum lc3_pcm_format fmt, const void *pcm, int stride, int nbytes, void *out) { static void (* const load[])(struct lc3_encoder *, const void *, int) = { - [LC3_PCM_FORMAT_S16] = load_s16, - [LC3_PCM_FORMAT_S24] = load_s24, + [LC3_PCM_FORMAT_S16 ] = load_s16, + [LC3_PCM_FORMAT_S24 ] = load_s24, + [LC3_PCM_FORMAT_S24_3LE] = load_s24_3le, + [LC3_PCM_FORMAT_FLOAT ] = load_float, }; /* --- Check parameters --- */ @@ -409,6 +457,55 @@ static void store_s24( } } +/** + * Output PCM Samples to signed 24 bits packed + * decoder Decoder state + * pcm, stride Output PCM samples, and count between two consecutives + */ +static void store_s24_3le( + struct lc3_decoder *decoder, void *_pcm, int stride) +{ + uint8_t *pcm = _pcm; + + enum lc3_dt dt = decoder->dt; + enum lc3_srate sr = decoder->sr_pcm; + + float *xs = decoder->xs; + int ns = LC3_NS(dt, sr); + + for ( ; ns > 0; ns--, xs++, pcm += 3*stride) { + int32_t s = *xs >= 0 ? (int32_t)(ldexpf(*xs, 8) + 0.5f) + : (int32_t)(ldexpf(*xs, 8) - 0.5f); + + s = LC3_SAT24(s); + pcm[0] = (s >> 0) & 0xff; + pcm[1] = (s >> 8) & 0xff; + pcm[2] = (s >> 16) & 0xff; + } +} + +/** + * Output PCM Samples to float 32 bits + * decoder Decoder state + * pcm, stride Output PCM samples, and count between two consecutives + */ +static void store_float( + struct lc3_decoder *decoder, void *_pcm, int stride) +{ + float *pcm = _pcm; + + enum lc3_dt dt = decoder->dt; + enum lc3_srate sr = decoder->sr_pcm; + + float *xs = decoder->xs; + int ns = LC3_NS(dt, sr); + + for ( ; ns > 0; ns--, xs++, pcm += stride) { + float s = ldexpf(*xs, -15); + *pcm = fminf(fmaxf(s, -1.f), 1.f); + } +} + /** * Decode bitstream * decoder Decoder state @@ -574,8 +671,10 @@ int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes, enum lc3_pcm_format fmt, void *pcm, int stride) { static void (* const store[])(struct lc3_decoder *, void *, int) = { - [LC3_PCM_FORMAT_S16] = store_s16, - [LC3_PCM_FORMAT_S24] = store_s24, + [LC3_PCM_FORMAT_S16 ] = store_s16, + [LC3_PCM_FORMAT_S24 ] = store_s24, + [LC3_PCM_FORMAT_S24_3LE] = store_s24_3le, + [LC3_PCM_FORMAT_FLOAT ] = store_float, }; /* --- Check parameters --- */ diff --git a/tools/dlc3.c b/tools/dlc3.c index b334898..07f0f21 100644 --- a/tools/dlc3.c +++ b/tools/dlc3.c @@ -176,7 +176,7 @@ int main(int argc, char *argv[]) error(EINVAL, "Samplerate %d Hz", srate_hz); int pcm_sbits = p.bitdepth; - int pcm_sbytes = 2 + 2*(pcm_sbits > 16); + int pcm_sbytes = pcm_sbits / 8; int pcm_srate_hz = !p.srate_hz ? srate_hz : p.srate_hz; int pcm_samples = !p.srate_hz ? nsamples : @@ -195,7 +195,7 @@ int main(int argc, char *argv[]) uint8_t in[nch * LC3_MAX_FRAME_BYTES]; int8_t alignas(int32_t) pcm[nch * frame_samples * pcm_sbytes]; enum lc3_pcm_format pcm_fmt = - pcm_sbits == 24 ? LC3_PCM_FORMAT_S24 : LC3_PCM_FORMAT_S16; + pcm_sbits == 24 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16; for (int ich = 0; ich < nch; ich++) dec[ich] = lc3_setup_decoder(frame_us, srate_hz, p.srate_hz, diff --git a/tools/elc3.c b/tools/elc3.c index b81c656..f9b3da2 100644 --- a/tools/elc3.c +++ b/tools/elc3.c @@ -177,7 +177,8 @@ int main(int argc, char *argv[]) if (pcm_sbits != 16 && pcm_sbits != 24) error(EINVAL, "Bitdepth %d", pcm_sbits); - if (pcm_sbytes != (pcm_sbits == 16 ? 2 : 4)) + if ((pcm_sbits == 16 && pcm_sbytes != 16/8) || + (pcm_sbits == 24 && pcm_sbytes != 24/8 && pcm_sbytes != 32/8)) error(EINVAL, "Sample storage on %d bytes", pcm_sbytes); if (nch < 1 || nch > 2) @@ -199,7 +200,8 @@ int main(int argc, char *argv[]) lc3_encoder_t enc[nch]; int8_t alignas(int32_t) pcm[nch * frame_samples * pcm_sbytes]; enum lc3_pcm_format pcm_fmt = - pcm_sbits == 24 ? LC3_PCM_FORMAT_S24 : LC3_PCM_FORMAT_S16; + pcm_sbytes == 32/8 ? LC3_PCM_FORMAT_S24 : + pcm_sbytes == 24/8 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16; uint8_t out[nch][frame_bytes]; for (int ich = 0; ich < nch; ich++)