mirror of
https://github.com/google/liblc3.git
synced 2026-04-17 21:25:30 +00:00
Introduce float and 24 bits packed input/output formats
This commit is contained in:
@@ -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
123
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 --- */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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++)
|
||||
|
||||
Reference in New Issue
Block a user