Introduce float and 24 bits packed input/output formats

This commit is contained in:
Antoine SOULIER
2022-06-01 11:56:53 +02:00
parent aa9eb7b234
commit f73a7468e9
4 changed files with 124 additions and 19 deletions

View File

@@ -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,
};

123
src/lc3.c
View File

@@ -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 --- */

View File

@@ -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,

View File

@@ -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++)