mirror of
https://github.com/google/liblc3.git
synced 2026-04-26 00:54:50 +00:00
feature: Add High-Resolution LC3 plus mode
Duplicate interfaces for HR mode spec: Remove intermediate quantized table fix: legacy lc3_frame_bytes() and lc3_resolve_bitrate() Cosmetic: rename fast_xxx math function to lc3_xxx
This commit is contained in:
235
src/lc3.c
235
src/lc3.c
@@ -53,92 +53,118 @@ struct side_data {
|
||||
/**
|
||||
* Resolve frame duration in us
|
||||
* us Frame duration in us
|
||||
* hrmode High-resolution mode indication
|
||||
* return Frame duration identifier, or LC3_NUM_DT
|
||||
*/
|
||||
static enum lc3_dt resolve_dt(int us)
|
||||
static enum lc3_dt resolve_dt(int us, bool hrmode)
|
||||
{
|
||||
return us == 2500 ? LC3_DT_2M5 :
|
||||
us == 5000 ? LC3_DT_5M :
|
||||
us == 7500 ? LC3_DT_7M5 :
|
||||
us == 10000 ? LC3_DT_10M : LC3_NUM_DT;
|
||||
return LC3_PLUS && us == 2500 ? LC3_DT_2M5 :
|
||||
LC3_PLUS && us == 5000 ? LC3_DT_5M :
|
||||
!hrmode && us == 7500 ? LC3_DT_7M5 :
|
||||
us == 10000 ? LC3_DT_10M : LC3_NUM_DT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve samplerate in Hz
|
||||
* hz Samplerate in Hz
|
||||
* hrmode High-resolution mode indication
|
||||
* return Sample rate identifier, or LC3_NUM_SRATE
|
||||
*/
|
||||
static enum lc3_srate resolve_sr(int hz)
|
||||
static enum lc3_srate resolve_srate(int hz, bool hrmode)
|
||||
{
|
||||
return hz == 8000 ? LC3_SRATE_8K : hz == 16000 ? LC3_SRATE_16K :
|
||||
hz == 24000 ? LC3_SRATE_24K : hz == 32000 ? LC3_SRATE_32K :
|
||||
hz == 48000 ? LC3_SRATE_48K : LC3_NUM_SRATE;
|
||||
hrmode = LC3_PLUS_HR && hrmode;
|
||||
|
||||
return !hrmode && hz == 8000 ? LC3_SRATE_8K :
|
||||
!hrmode && hz == 16000 ? LC3_SRATE_16K :
|
||||
!hrmode && hz == 24000 ? LC3_SRATE_24K :
|
||||
!hrmode && hz == 32000 ? LC3_SRATE_32K :
|
||||
!hrmode && hz == 48000 ? LC3_SRATE_48K :
|
||||
hrmode && hz == 48000 ? LC3_SRATE_48K_HR :
|
||||
hrmode && hz == 96000 ? LC3_SRATE_96K_HR : LC3_NUM_SRATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of PCM samples in a frame
|
||||
*/
|
||||
int lc3_frame_samples(int dt_us, int sr_hz)
|
||||
int lc3_hr_frame_samples(bool hrmode, int dt_us, int sr_hz)
|
||||
{
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
enum lc3_dt dt = resolve_dt(dt_us, hrmode);
|
||||
enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
|
||||
return -1;
|
||||
|
||||
return LC3_NS(dt, sr);
|
||||
return lc3_ns(dt, sr);
|
||||
}
|
||||
|
||||
int lc3_frame_samples(int dt_us, int sr_hz)
|
||||
{
|
||||
return lc3_hr_frame_samples(false, dt_us, sr_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of frames, from bitrate
|
||||
*/
|
||||
int lc3_frame_bytes(int dt_us, int bitrate)
|
||||
int lc3_hr_frame_bytes(bool hrmode, int dt_us, int sr_hz, int bitrate)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT)
|
||||
enum lc3_dt dt = resolve_dt(dt_us, hrmode);
|
||||
enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
|
||||
return -1;
|
||||
|
||||
if (bitrate < LC3_MIN_BITRATE)
|
||||
return LC3_MIN_FRAME_BYTES;
|
||||
bitrate = LC3_CLIP(bitrate,
|
||||
lc3_hr_resolve_bitrate(hrmode, dt_us, sr_hz, 0),
|
||||
lc3_hr_resolve_bitrate(hrmode, dt_us, sr_hz, INT_MAX));
|
||||
|
||||
if (bitrate > LC3_MAX_BITRATE)
|
||||
return LC3_MAX_FRAME_BYTES;
|
||||
return (bitrate * (1 + dt)) / 3200;
|
||||
}
|
||||
|
||||
int nbytes = ((unsigned)bitrate * dt_us) / (1000*1000*8);
|
||||
|
||||
return LC3_CLIP(nbytes, LC3_MIN_FRAME_BYTES, LC3_MAX_FRAME_BYTES);
|
||||
int lc3_frame_bytes(int dt_us, int bitrate)
|
||||
{
|
||||
return lc3_hr_frame_bytes(false, dt_us, 8000, bitrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the bitrate, from the size of frames
|
||||
*/
|
||||
int lc3_resolve_bitrate(int dt_us, int nbytes)
|
||||
int lc3_hr_resolve_bitrate(bool hrmode, int dt_us, int sr_hz, int nbytes)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT)
|
||||
enum lc3_dt dt = resolve_dt(dt_us, hrmode);
|
||||
enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
|
||||
return -1;
|
||||
|
||||
if (nbytes < LC3_MIN_FRAME_BYTES)
|
||||
return LC3_MIN_BITRATE;
|
||||
nbytes = LC3_CLIP(nbytes,
|
||||
lc3_min_frame_bytes(dt, sr),
|
||||
lc3_max_frame_bytes(dt, sr));
|
||||
|
||||
if (nbytes > LC3_MAX_FRAME_BYTES)
|
||||
return LC3_MAX_BITRATE;
|
||||
return (nbytes * 3200) / (1 + dt);
|
||||
}
|
||||
|
||||
int bitrate = ((unsigned)nbytes * (1000*1000*8) + dt_us/2) / dt_us;
|
||||
|
||||
return LC3_CLIP(bitrate, LC3_MIN_BITRATE, LC3_MAX_BITRATE);
|
||||
int lc3_resolve_bitrate(int dt_us, int nbytes)
|
||||
{
|
||||
return lc3_hr_resolve_bitrate(false, dt_us, 8000, nbytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return algorithmic delay, as a number of samples
|
||||
*/
|
||||
int lc3_delay_samples(int dt_us, int sr_hz)
|
||||
int lc3_hr_delay_samples(bool hrmode, int dt_us, int sr_hz)
|
||||
{
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
enum lc3_dt dt = resolve_dt(dt_us, hrmode);
|
||||
enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
|
||||
return -1;
|
||||
|
||||
return (dt == LC3_DT_7M5 ? 8 : 5) * (LC3_SRATE_KHZ(sr) / 2);
|
||||
return 2 * lc3_nd(dt, sr) - lc3_ns(dt, sr);
|
||||
}
|
||||
|
||||
int lc3_delay_samples(int dt_us, int sr_hz)
|
||||
{
|
||||
return lc3_hr_delay_samples(false, dt_us, sr_hz);
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +187,7 @@ static void load_s16(
|
||||
|
||||
int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
|
||||
float *xs = encoder->x + encoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for (int i = 0; i < ns; i++, pcm += stride)
|
||||
xt[i] = *pcm, xs[i] = *pcm;
|
||||
@@ -182,7 +208,7 @@ static void load_s24(
|
||||
|
||||
int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
|
||||
float *xs = encoder->x + encoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for (int i = 0; i < ns; i++, pcm += stride) {
|
||||
xt[i] = *pcm >> 8;
|
||||
@@ -205,7 +231,7 @@ static void load_s24_3le(
|
||||
|
||||
int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
|
||||
float *xs = encoder->x + encoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for (int i = 0; i < ns; i++, pcm += 3*stride) {
|
||||
int32_t in = ((uint32_t)pcm[0] << 8) |
|
||||
@@ -232,7 +258,7 @@ static void load_float(
|
||||
|
||||
int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
|
||||
float *xs = encoder->x + encoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for (int i = 0; i < ns; i++, pcm += stride) {
|
||||
xs[i] = ldexpf(*pcm, 15);
|
||||
@@ -244,19 +270,20 @@ static void load_float(
|
||||
* Frame Analysis
|
||||
* encoder Encoder state
|
||||
* nbytes Size in bytes of the frame
|
||||
* side, xq Return frame data
|
||||
* side Return frame data
|
||||
*/
|
||||
static void analyze(struct lc3_encoder *encoder,
|
||||
int nbytes, struct side_data *side, uint16_t *xq)
|
||||
int nbytes, struct side_data *side)
|
||||
{
|
||||
enum lc3_dt dt = encoder->dt;
|
||||
enum lc3_srate sr = encoder->sr;
|
||||
enum lc3_srate sr_pcm = encoder->sr_pcm;
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nt = LC3_NT(sr_pcm);
|
||||
|
||||
int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
|
||||
float *xs = encoder->x + encoder->xs_off;
|
||||
int ns = lc3_ns(dt, sr_pcm);
|
||||
int nt = lc3_nt(sr_pcm);
|
||||
|
||||
float *xd = encoder->x + encoder->xd_off;
|
||||
float *xf = xs;
|
||||
|
||||
@@ -281,29 +308,30 @@ static void analyze(struct lc3_encoder *encoder,
|
||||
|
||||
side->bw = lc3_bwdet_run(dt, sr, e);
|
||||
|
||||
lc3_sns_analyze(dt, sr, e, att, &side->sns, xf, xf);
|
||||
lc3_sns_analyze(dt, sr, nbytes, e, att, &side->sns, xf, xf);
|
||||
|
||||
lc3_tns_analyze(dt, side->bw, nn_flag, nbytes, &side->tns, xf);
|
||||
|
||||
lc3_spec_analyze(dt, sr,
|
||||
nbytes, side->pitch_present, &side->tns,
|
||||
&encoder->spec, xf, xq, &side->spec);
|
||||
&encoder->spec, xf, &side->spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode bitstream
|
||||
* encoder Encoder state
|
||||
* side, xq The frame data
|
||||
* side The frame data
|
||||
* nbytes Target size of the frame (20 to 400)
|
||||
* buffer Output bitstream buffer of `nbytes` size
|
||||
*/
|
||||
static void encode(struct lc3_encoder *encoder,
|
||||
const struct side_data *side, uint16_t *xq, int nbytes, void *buffer)
|
||||
const struct side_data *side, int nbytes, void *buffer)
|
||||
{
|
||||
enum lc3_dt dt = encoder->dt;
|
||||
enum lc3_srate sr = encoder->sr;
|
||||
enum lc3_bandwidth bw = side->bw;
|
||||
|
||||
float *xf = encoder->x + encoder->xs_off;
|
||||
enum lc3_bandwidth bw = side->bw;
|
||||
|
||||
lc3_bits_t bits;
|
||||
|
||||
@@ -322,8 +350,7 @@ static void encode(struct lc3_encoder *encoder,
|
||||
if (side->pitch_present)
|
||||
lc3_ltpf_put_data(&bits, &side->ltpf);
|
||||
|
||||
lc3_spec_encode(&bits,
|
||||
dt, sr, bw, nbytes, xq, &side->spec, xf);
|
||||
lc3_spec_encode(&bits, dt, sr, bw, nbytes, &side->spec, xf);
|
||||
|
||||
lc3_flush_bits(&bits);
|
||||
}
|
||||
@@ -331,35 +358,40 @@ static void encode(struct lc3_encoder *encoder,
|
||||
/**
|
||||
* Return size needed for an encoder
|
||||
*/
|
||||
unsigned lc3_encoder_size(int dt_us, int sr_hz)
|
||||
unsigned lc3_hr_encoder_size(bool hrmode, int dt_us, int sr_hz)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT ||
|
||||
resolve_sr(sr_hz) >= LC3_NUM_SRATE)
|
||||
if (resolve_dt(dt_us, hrmode) >= LC3_NUM_DT ||
|
||||
resolve_srate(sr_hz, hrmode) >= LC3_NUM_SRATE)
|
||||
return 0;
|
||||
|
||||
return sizeof(struct lc3_encoder) +
|
||||
(LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz)-1) * sizeof(float);
|
||||
}
|
||||
|
||||
unsigned lc3_encoder_size(int dt_us, int sr_hz)
|
||||
{
|
||||
return lc3_hr_encoder_size(false, dt_us, sr_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup encoder
|
||||
*/
|
||||
struct lc3_encoder *lc3_setup_encoder(
|
||||
struct lc3_encoder *lc3_hr_setup_encoder(bool hrmode,
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
|
||||
{
|
||||
if (sr_pcm_hz <= 0)
|
||||
sr_pcm_hz = sr_hz;
|
||||
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz);
|
||||
enum lc3_dt dt = resolve_dt(dt_us, hrmode);
|
||||
enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
|
||||
enum lc3_srate sr_pcm = resolve_srate(sr_pcm_hz, hrmode);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
|
||||
return NULL;
|
||||
|
||||
struct lc3_encoder *encoder = mem;
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nt = LC3_NT(sr_pcm);
|
||||
int ns = lc3_ns(dt, sr_pcm);
|
||||
int nt = lc3_nt(sr_pcm);
|
||||
|
||||
*encoder = (struct lc3_encoder){
|
||||
.dt = dt, .sr = sr,
|
||||
@@ -376,6 +408,12 @@ struct lc3_encoder *lc3_setup_encoder(
|
||||
return encoder;
|
||||
}
|
||||
|
||||
struct lc3_encoder *lc3_setup_encoder(
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
|
||||
{
|
||||
return lc3_hr_setup_encoder(false, dt_us, sr_hz, sr_pcm_hz, mem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a frame
|
||||
*/
|
||||
@@ -391,20 +429,19 @@ int lc3_encode(struct lc3_encoder *encoder, enum lc3_pcm_format fmt,
|
||||
|
||||
/* --- Check parameters --- */
|
||||
|
||||
if (!encoder || nbytes < LC3_MIN_FRAME_BYTES
|
||||
|| nbytes > LC3_MAX_FRAME_BYTES)
|
||||
if (!encoder || nbytes < lc3_min_frame_bytes(encoder->dt, encoder->sr)
|
||||
|| nbytes > lc3_max_frame_bytes(encoder->dt, encoder->sr))
|
||||
return -1;
|
||||
|
||||
/* --- Processing --- */
|
||||
|
||||
struct side_data side;
|
||||
uint16_t xq[LC3_MAX_NE];
|
||||
|
||||
load[fmt](encoder, pcm, stride);
|
||||
|
||||
analyze(encoder, nbytes, &side, xq);
|
||||
analyze(encoder, nbytes, &side);
|
||||
|
||||
encode(encoder, &side, xq, nbytes, out);
|
||||
encode(encoder, &side, nbytes, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -428,7 +465,7 @@ static void store_s16(
|
||||
enum lc3_srate sr = decoder->sr_pcm;
|
||||
|
||||
float *xs = decoder->x + decoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for ( ; ns > 0; ns--, xs++, pcm += stride) {
|
||||
int32_t s = *xs >= 0 ? (int)(*xs + 0.5f) : (int)(*xs - 0.5f);
|
||||
@@ -450,7 +487,7 @@ static void store_s24(
|
||||
enum lc3_srate sr = decoder->sr_pcm;
|
||||
|
||||
float *xs = decoder->x + decoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for ( ; ns > 0; ns--, xs++, pcm += stride) {
|
||||
int32_t s = *xs >= 0 ? (int32_t)(ldexpf(*xs, 8) + 0.5f)
|
||||
@@ -473,7 +510,7 @@ static void store_s24_3le(
|
||||
enum lc3_srate sr = decoder->sr_pcm;
|
||||
|
||||
float *xs = decoder->x + decoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
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)
|
||||
@@ -500,7 +537,7 @@ static void store_float(
|
||||
enum lc3_srate sr = decoder->sr_pcm;
|
||||
|
||||
float *xs = decoder->x + decoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
for ( ; ns > 0; ns--, xs++, pcm += stride) {
|
||||
float s = ldexpf(*xs, -15);
|
||||
@@ -522,8 +559,8 @@ static int decode(struct lc3_decoder *decoder,
|
||||
enum lc3_srate sr = decoder->sr;
|
||||
|
||||
float *xf = decoder->x + decoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
lc3_bits_t bits;
|
||||
int ret = 0;
|
||||
@@ -545,7 +582,7 @@ static int decode(struct lc3_decoder *decoder,
|
||||
return ret;
|
||||
|
||||
if (side->pitch_present)
|
||||
lc3_ltpf_get_data(&bits, &side->ltpf);
|
||||
lc3_ltpf_get_data(&bits, &side->ltpf);
|
||||
|
||||
if ((ret = lc3_spec_decode(&bits, dt, sr,
|
||||
side->bw, nbytes, &side->spec, xf)) < 0)
|
||||
@@ -570,8 +607,8 @@ static void synthesize(struct lc3_decoder *decoder,
|
||||
enum lc3_srate sr_pcm = decoder->sr_pcm;
|
||||
|
||||
float *xf = decoder->x + decoder->xs_off;
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
int ns = lc3_ns(dt, sr_pcm);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
float *xg = decoder->x + decoder->xg_off;
|
||||
float *xs = xf;
|
||||
@@ -598,8 +635,9 @@ static void synthesize(struct lc3_decoder *decoder,
|
||||
lc3_mdct_inverse(dt, sr_pcm, sr, xf, xd, xs);
|
||||
}
|
||||
|
||||
lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf,
|
||||
side && side->pitch_present ? &side->ltpf : NULL, xh, xs);
|
||||
if (!lc3_hr(sr))
|
||||
lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf,
|
||||
side && side->pitch_present ? &side->ltpf : NULL, xh, xs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -610,55 +648,60 @@ static void complete(struct lc3_decoder *decoder)
|
||||
{
|
||||
enum lc3_dt dt = decoder->dt;
|
||||
enum lc3_srate sr_pcm = decoder->sr_pcm;
|
||||
int nh = LC3_NH(dt, sr_pcm);
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nh = lc3_nh(dt, sr_pcm);
|
||||
int ns = lc3_ns(dt, sr_pcm);
|
||||
|
||||
decoder->xs_off = decoder->xs_off - decoder->xh_off < nh - ns ?
|
||||
decoder->xs_off = decoder->xs_off - decoder->xh_off < nh ?
|
||||
decoder->xs_off + ns : decoder->xh_off;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size needed for a decoder
|
||||
*/
|
||||
unsigned lc3_decoder_size(int dt_us, int sr_hz)
|
||||
unsigned lc3_hr_decoder_size(bool hrmode, int dt_us, int sr_hz)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT ||
|
||||
resolve_sr(sr_hz) >= LC3_NUM_SRATE)
|
||||
if (resolve_dt(dt_us, hrmode) >= LC3_NUM_DT ||
|
||||
resolve_srate(sr_hz, hrmode) >= LC3_NUM_SRATE)
|
||||
return 0;
|
||||
|
||||
return sizeof(struct lc3_decoder) +
|
||||
(LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz)-1) * sizeof(float);
|
||||
}
|
||||
|
||||
unsigned lc3_decoder_size(int dt_us, int sr_hz)
|
||||
{
|
||||
return lc3_hr_decoder_size(false, dt_us, sr_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup decoder
|
||||
*/
|
||||
struct lc3_decoder *lc3_setup_decoder(
|
||||
struct lc3_decoder *lc3_hr_setup_decoder(bool hrmode,
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
|
||||
{
|
||||
if (sr_pcm_hz <= 0)
|
||||
sr_pcm_hz = sr_hz;
|
||||
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz);
|
||||
enum lc3_dt dt = resolve_dt(dt_us, hrmode);
|
||||
enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
|
||||
enum lc3_srate sr_pcm = resolve_srate(sr_pcm_hz, hrmode);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
|
||||
return NULL;
|
||||
|
||||
struct lc3_decoder *decoder = mem;
|
||||
int nh = LC3_NH(dt, sr_pcm);
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nd = LC3_ND(dt, sr_pcm);
|
||||
int nh = lc3_nh(dt, sr_pcm);
|
||||
int ns = lc3_ns(dt, sr_pcm);
|
||||
int nd = lc3_nd(dt, sr_pcm);
|
||||
|
||||
*decoder = (struct lc3_decoder){
|
||||
.dt = dt, .sr = sr,
|
||||
.sr_pcm = sr_pcm,
|
||||
|
||||
.xh_off = 0,
|
||||
.xs_off = nh - ns,
|
||||
.xd_off = nh,
|
||||
.xg_off = nh + nd,
|
||||
.xs_off = nh,
|
||||
.xd_off = nh + ns,
|
||||
.xg_off = nh + ns + nd,
|
||||
};
|
||||
|
||||
lc3_plc_reset(&decoder->plc);
|
||||
@@ -669,6 +712,12 @@ struct lc3_decoder *lc3_setup_decoder(
|
||||
return decoder;
|
||||
}
|
||||
|
||||
struct lc3_decoder *lc3_setup_decoder(
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
|
||||
{
|
||||
return lc3_hr_setup_decoder(false, dt_us, sr_hz, sr_pcm_hz, mem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a frame
|
||||
*/
|
||||
@@ -687,8 +736,8 @@ int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes,
|
||||
if (!decoder)
|
||||
return -1;
|
||||
|
||||
if (in && (nbytes < LC3_MIN_FRAME_BYTES ||
|
||||
nbytes > LC3_MAX_FRAME_BYTES ))
|
||||
if (in && (nbytes < lc3_min_frame_bytes(decoder->dt, decoder->sr) ||
|
||||
nbytes > lc3_max_frame_bytes(decoder->dt, decoder->sr) ))
|
||||
return -1;
|
||||
|
||||
/* --- Processing --- */
|
||||
|
||||
Reference in New Issue
Block a user