mirror of
https://github.com/google/liblc3.git
synced 2026-05-05 04:38:00 +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:
@@ -32,7 +32,7 @@ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr,
|
||||
[LC3_DT_10M - LC3_DT_7M5] = { { 81, INT_MAX }, { 100, INT_MAX } },
|
||||
};
|
||||
|
||||
if (dt < LC3_DT_7M5 || sr < LC3_SRATE_32K ||
|
||||
if (dt < LC3_DT_7M5 || sr < LC3_SRATE_32K || lc3_hr(sr) ||
|
||||
nbytes < nbytes_ranges[dt - LC3_DT_7M5][sr - LC3_SRATE_32K][0] ||
|
||||
nbytes > nbytes_ranges[dt - LC3_DT_7M5][sr - LC3_SRATE_32K][1] )
|
||||
return 0;
|
||||
|
||||
30
src/bwdet.c
30
src/bwdet.c
@@ -29,48 +29,46 @@ enum lc3_bandwidth lc3_bwdet_run(
|
||||
|
||||
struct region { int is : 8; int ie : 8; };
|
||||
|
||||
#if !LC3_NPLUS
|
||||
#if LC3_PLUS
|
||||
|
||||
static const struct region bws_table_2m5[][LC3_NUM_BANDWIDTH-1] = {
|
||||
static const struct region bws_table_2m5[][LC3_BANDWIDTH_SWB+1] = {
|
||||
{ { 24, 34+1 } },
|
||||
{ { 24, 32+1 }, { 35, 39+1 } },
|
||||
{ { 24, 31+1 }, { 33, 38+1 }, { 39, 42+1 } },
|
||||
{ { 22, 29+1 }, { 31, 35+1 }, { 37, 40+1 }, { 41, 43+1 } },
|
||||
};
|
||||
|
||||
static const struct region bws_table_5m[][LC3_NUM_BANDWIDTH-1] = {
|
||||
static const struct region bws_table_5m[][LC3_BANDWIDTH_SWB+1] = {
|
||||
{ { 39, 49+1 } },
|
||||
{ { 35, 44+1 }, { 47, 51+1 } },
|
||||
{ { 34, 42+1 }, { 44, 49+1 }, { 50, 53+1 } },
|
||||
{ { 32, 40+1 }, { 42, 46+1 }, { 48, 51+1 }, { 52, 54+1 } },
|
||||
};
|
||||
|
||||
#endif /* !LC3_NPLUS */
|
||||
#endif /* LC3_PLUS */
|
||||
|
||||
static const struct region bws_table_7m5[][LC3_NUM_BANDWIDTH-1] = {
|
||||
static const struct region bws_table_7m5[][LC3_BANDWIDTH_SWB+1] = {
|
||||
{ { 51, 63+1 } },
|
||||
{ { 45, 55+1 }, { 58, 63+1 } },
|
||||
{ { 42, 51+1 }, { 53, 58+1 }, { 60, 63+1 } },
|
||||
{ { 40, 48+1 }, { 51, 55+1 }, { 57, 60+1 }, { 61, 63+1 } },
|
||||
};
|
||||
|
||||
static const struct region bws_table_10m[][LC3_NUM_BANDWIDTH-1] = {
|
||||
static const struct region bws_table_10m[][LC3_BANDWIDTH_SWB+1] = {
|
||||
{ { 53, 63+1 } },
|
||||
{ { 47, 56+1 }, { 59, 63+1 } },
|
||||
{ { 44, 52+1 }, { 54, 59+1 }, { 60, 63+1 } },
|
||||
{ { 41, 49+1 }, { 51, 55+1 }, { 57, 60+1 }, { 61, 63+1 } },
|
||||
};
|
||||
|
||||
static const struct region (*bws_table[])[LC3_NUM_BANDWIDTH-1] = {
|
||||
#if !LC3_NPLUS
|
||||
[LC3_DT_2M5] = bws_table_2m5,
|
||||
[LC3_DT_5M ] = bws_table_5m,
|
||||
#endif /* !LC3_NPLUS */
|
||||
static const struct region (*bws_table[])[LC3_BANDWIDTH_SWB+1] = {
|
||||
[LC3_DT_2M5] = LC3_IF_PLUS(bws_table_2m5, NULL),
|
||||
[LC3_DT_5M ] = LC3_IF_PLUS(bws_table_5m , NULL),
|
||||
[LC3_DT_7M5] = bws_table_7m5,
|
||||
[LC3_DT_10M] = bws_table_10m,
|
||||
};
|
||||
|
||||
static const int l_table[LC3_NUM_DT][LC3_NUM_BANDWIDTH-1] = {
|
||||
static const int l_table[LC3_NUM_DT][LC3_BANDWIDTH_SWB+1] = {
|
||||
[LC3_DT_2M5] = { 4, 4, 3, 1 },
|
||||
[LC3_DT_5M ] = { 4, 4, 3, 1 },
|
||||
[LC3_DT_7M5] = { 4, 4, 3, 2 },
|
||||
@@ -83,7 +81,7 @@ enum lc3_bandwidth lc3_bwdet_run(
|
||||
enum lc3_bandwidth bw0 = LC3_BANDWIDTH_NB;
|
||||
enum lc3_bandwidth bwn = (enum lc3_bandwidth)sr;
|
||||
|
||||
if (bwn <= bw0)
|
||||
if (bwn <= bw0 || lc3_hr(sr))
|
||||
return bwn;
|
||||
|
||||
const struct region *bwr = bws_table[dt][bwn-1];
|
||||
@@ -126,7 +124,7 @@ enum lc3_bandwidth lc3_bwdet_run(
|
||||
*/
|
||||
int lc3_bwdet_get_nbits(enum lc3_srate sr)
|
||||
{
|
||||
return (sr > 0) + (sr > 1) + (sr > 3);
|
||||
return lc3_hr(sr) ? 0 : (sr > 0) + (sr > 1) + (sr > 3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,6 +147,8 @@ int lc3_bwdet_get_bw(lc3_bits_t *bits,
|
||||
enum lc3_bandwidth max_bw = (enum lc3_bandwidth)sr;
|
||||
int nbits_bw = lc3_bwdet_get_nbits(sr);
|
||||
|
||||
*bw = nbits_bw > 0 ? lc3_get_bits(bits, nbits_bw) : LC3_BANDWIDTH_NB;
|
||||
*bw = nbits_bw <= 0 ? max_bw :
|
||||
(enum lc3_bandwidth)lc3_get_bits(bits, nbits_bw);
|
||||
|
||||
return *bw > max_bw ? (*bw = max_bw), -1 : 0;
|
||||
}
|
||||
|
||||
77
src/common.h
77
src/common.h
@@ -31,6 +31,31 @@
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Acivation flags for LC3-Plus and LC3-Plus HR features
|
||||
*/
|
||||
|
||||
#ifndef LC3_PLUS
|
||||
#define LC3_PLUS 1
|
||||
#endif
|
||||
|
||||
#ifndef LC3_PLUS_HR
|
||||
#define LC3_PLUS_HR 1
|
||||
#endif
|
||||
|
||||
#if LC3_PLUS
|
||||
#define LC3_IF_PLUS(a, b) (a)
|
||||
#else
|
||||
#define LC3_IF_PLUS(a, b) (b)
|
||||
#endif
|
||||
|
||||
#if LC3_PLUS_HR
|
||||
#define LC3_IF_PLUS_HR(a, b) (a)
|
||||
#else
|
||||
#define LC3_IF_PLUS_HR(a, b) (b)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Hot Function attribute
|
||||
* Selectively disable sanitizer
|
||||
@@ -49,6 +74,7 @@
|
||||
#endif /* __clang__ */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Macros
|
||||
* MIN/MAX Minimum and maximum between 2 values
|
||||
@@ -79,51 +105,11 @@
|
||||
|
||||
|
||||
/**
|
||||
* Convert `dt` in us and `sr` in KHz
|
||||
* Return `true` when high-resolution mode
|
||||
*/
|
||||
|
||||
#define LC3_DT_US(dt) \
|
||||
( (1 + (dt)) * 2500 )
|
||||
|
||||
#define LC3_SRATE_KHZ(sr) \
|
||||
( (1 + (sr) + ((sr) == LC3_SRATE_48K)) * 8 )
|
||||
|
||||
|
||||
/**
|
||||
* Return number of samples, delayed samples and
|
||||
* encoded spectrum coefficients within a frame
|
||||
*
|
||||
* - The number of MDCT delayed samples is the sum of half a frame and
|
||||
* an ovelap of future by 1.25 ms (2.5ms, 5ms and 10ms frame durations)
|
||||
* or 2 ms (7.5ms frame duration).
|
||||
*
|
||||
* - For encoding, keep 1.25 ms of temporal previous samples
|
||||
* - For decoding, keep 18 ms of history, aligned on frames, and a frame
|
||||
*/
|
||||
|
||||
#define LC3_NS(dt, sr) \
|
||||
( 20 * (1 + (dt)) * (1 + (sr) + ((sr) == LC3_SRATE_48K)) )
|
||||
|
||||
#define LC3_NE(dt, sr) \
|
||||
( 20 * (1 + (dt)) * (1 + (sr)) )
|
||||
|
||||
#define LC3_MAX_NS \
|
||||
LC3_NS(LC3_DT_10M, LC3_SRATE_48K)
|
||||
|
||||
#define LC3_MAX_NE \
|
||||
LC3_NE(LC3_DT_10M, LC3_SRATE_48K)
|
||||
|
||||
#define LC3_ND(dt, sr) \
|
||||
( LC3_NS(dt, sr) / 2 + \
|
||||
(5 + 3*((dt) == LC3_DT_7M5)) * LC3_SRATE_KHZ(sr) / 4 )
|
||||
|
||||
#define LC3_NT(sr_hz) \
|
||||
( (5 * LC3_SRATE_KHZ(sr)) / 4 )
|
||||
|
||||
#define LC3_NH(dt, sr) \
|
||||
( ((dt == LC3_DT_2M5 ? 8 : \
|
||||
dt == LC3_DT_5M ? 4 : \
|
||||
dt == LC3_DT_7M5 ? 3 : 2) + 1) * LC3_NS(dt, sr) )
|
||||
static inline bool lc3_hr(enum lc3_srate sr) {
|
||||
return LC3_PLUS_HR && (sr >= LC3_SRATE_48K_HR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -137,6 +123,9 @@ enum lc3_bandwidth {
|
||||
LC3_BANDWIDTH_SWB = LC3_SRATE_32K,
|
||||
LC3_BANDWIDTH_FB = LC3_SRATE_48K,
|
||||
|
||||
LC3_BANDWIDTH_FB_HR = LC3_SRATE_48K_HR,
|
||||
LC3_BANDWIDTH_UB_HR = LC3_SRATE_96K_HR,
|
||||
|
||||
LC3_NUM_BANDWIDTH,
|
||||
};
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
bool lc3_energy_compute(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *e)
|
||||
{
|
||||
/* Mean the square of coefficients within each band */
|
||||
|
||||
int nb = lc3_num_bands[dt][sr];
|
||||
const uint16_t *lim = lc3_band_lim[dt][sr];
|
||||
const int *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
/* Mean the square of coefficients within each band */
|
||||
|
||||
float e_sum[2] = { 0, 0 };
|
||||
int iband_h = nb - (const int []){
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
* x Operand, range -8 to 8
|
||||
* return 2^x approximation (max relative error ~ 7e-6)
|
||||
*/
|
||||
static inline float fast_exp2f(float x)
|
||||
static inline float lc3_exp2f(float x)
|
||||
{
|
||||
float y;
|
||||
|
||||
@@ -59,7 +59,7 @@ static inline float fast_exp2f(float x)
|
||||
* x Operand, greater than 0
|
||||
* return log2(x) approximation (max absolute error ~ 1e-4)
|
||||
*/
|
||||
static inline float fast_log2f(float x)
|
||||
static inline float lc3_log2f(float x)
|
||||
{
|
||||
float y;
|
||||
int e;
|
||||
@@ -87,9 +87,9 @@ static inline float fast_log2f(float x)
|
||||
* x Operand, greater than 0
|
||||
* return log10(x) approximation (max absolute error ~ 1e-4)
|
||||
*/
|
||||
static inline float fast_log10f(float x)
|
||||
static inline float lc3_log10f(float x)
|
||||
{
|
||||
return log10f(2) * fast_log2f(x);
|
||||
return log10f(2) * lc3_log2f(x);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ static inline float fast_log10f(float x)
|
||||
* - The 0 value is accepted and return the minimum value ~ -191dB
|
||||
* - This function assumed that float 32 bits is coded IEEE 754
|
||||
*/
|
||||
static inline int32_t fast_db_q16(float x)
|
||||
static inline int32_t lc3_db_q16(float x)
|
||||
{
|
||||
/* --- Table in Q15 --- */
|
||||
|
||||
|
||||
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 --- */
|
||||
|
||||
86
src/ltpf.c
86
src/ltpf.c
@@ -144,6 +144,36 @@ static const int16_t h_48k_12k8_q15[4*60] = {
|
||||
};
|
||||
#endif /* resample_48k_12k8 */
|
||||
|
||||
#ifndef resample_96k_12k8
|
||||
static const int16_t h_96k_12k8_q15[2*120] = {
|
||||
-3, -7, -10, -13, -13, -10, -4, 5, 15, 26,
|
||||
33, 36, 31, 19, 0, -23, -47, -66, -76, -73,
|
||||
-54, -21, 23, 70, 111, 139, 143, 121, 72, 0,
|
||||
-84, -165, -227, -256, -240, -175, -67, 72, 219, 349,
|
||||
433, 448, 379, 225, 0, -268, -536, -755, -874, -848,
|
||||
-648, -260, 301, 1000, 1780, 2569, 3290, 3869, 4243, 4372,
|
||||
4243, 3869, 3290, 2569, 1780, 1000, 301, -260, -648, -848,
|
||||
-874, -755, -536, -268, 0, 225, 379, 448, 433, 349,
|
||||
219, 72, -67, -175, -240, -256, -227, -165, -84, 0,
|
||||
72, 121, 143, 139, 111, 70, 23, -21, -54, -73,
|
||||
-76, -66, -47, -23, 0, 19, 31, 36, 33, 26,
|
||||
15, 5, -4, -10, -13, -13, -10, -7, -3, 0,
|
||||
|
||||
-1, -5, -8, -12, -13, -12, -8, 0, 10, 21,
|
||||
30, 35, 34, 26, 10, -11, -35, -58, -73, -76,
|
||||
-65, -39, 0, 46, 92, 127, 144, 136, 100, 38,
|
||||
-41, -125, -199, -246, -254, -214, -126, 0, 146, 288,
|
||||
398, 450, 424, 312, 120, -131, -405, -655, -830, -881,
|
||||
-771, -477, 0, 636, 1384, 2178, 2943, 3601, 4084, 4340,
|
||||
4340, 4084, 3601, 2943, 2178, 1384, 636, 0, -477, -771,
|
||||
-881, -830, -655, -405, -131, 120, 312, 424, 450, 398,
|
||||
288, 146, 0, -126, -214, -254, -246, -199, -125, -41,
|
||||
38, 100, 136, 144, 127, 92, 46, 0, -39, -65,
|
||||
-76, -73, -58, -35, -11, 10, 26, 34, 35, 30,
|
||||
21, 10, 0, -8, -12, -13, -12, -8, -5, -1,
|
||||
};
|
||||
#endif /* resample_96k_12k8 */
|
||||
|
||||
|
||||
/**
|
||||
* High-pass 50Hz filtering, at 12.8 KHz samplerate
|
||||
@@ -223,7 +253,8 @@ LC3_HOT static inline void resample_x64k_12k8(const int p, const int16_t *h,
|
||||
* The number of previous samples `d` accessed on `x` is :
|
||||
* d: { 30, 60 } - 1 for resampling factors 8 and 4.
|
||||
*/
|
||||
#if !defined(resample_24k_12k8) || !defined(resample_48k_12k8)
|
||||
#if !defined(resample_24k_12k8) || !defined(resample_48k_12k8) \
|
||||
|| !defined(resample_96k_12k8)
|
||||
LC3_HOT static inline void resample_x192k_12k8(const int p, const int16_t *h,
|
||||
struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
|
||||
{
|
||||
@@ -340,6 +371,22 @@ LC3_HOT static void resample_48k_12k8(
|
||||
}
|
||||
#endif /* resample_48k_12k8 */
|
||||
|
||||
/**
|
||||
* Resample from 96 Khz to 12.8 KHz
|
||||
* hp50 High-Pass biquad filter state
|
||||
* x [-120..-1] Previous, [0..ns-1] Current samples, in fixed Q15
|
||||
* y, n [0..n-1] Output `n` processed samples, in fixed Q14
|
||||
*
|
||||
* The `x` vector is aligned on 32 bits
|
||||
*/
|
||||
#ifndef resample_96k_12k8
|
||||
LC3_HOT static void resample_96k_12k8(
|
||||
struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
|
||||
{
|
||||
resample_x192k_12k8(2, h_96k_12k8_q15, hp50, x, y, n);
|
||||
}
|
||||
#endif /* resample_96k_12k8 */
|
||||
|
||||
/**
|
||||
* Resample to 6.4 KHz
|
||||
* x [-3..-1] Previous, [0..n-1] Current samples
|
||||
@@ -366,11 +413,13 @@ LC3_HOT static void resample_6k4(const int16_t *x, int16_t *y, int n)
|
||||
static void (* const resample_12k8[])
|
||||
(struct lc3_ltpf_hp50_state *, const int16_t *, int16_t *, int ) =
|
||||
{
|
||||
[LC3_SRATE_8K ] = resample_8k_12k8,
|
||||
[LC3_SRATE_16K] = resample_16k_12k8,
|
||||
[LC3_SRATE_24K] = resample_24k_12k8,
|
||||
[LC3_SRATE_32K] = resample_32k_12k8,
|
||||
[LC3_SRATE_48K] = resample_48k_12k8,
|
||||
[LC3_SRATE_8K ] = resample_8k_12k8,
|
||||
[LC3_SRATE_16K ] = resample_16k_12k8,
|
||||
[LC3_SRATE_24K ] = resample_24k_12k8,
|
||||
[LC3_SRATE_32K ] = resample_32k_12k8,
|
||||
[LC3_SRATE_48K ] = resample_48k_12k8,
|
||||
[LC3_SRATE_48K_HR] = resample_48k_12k8,
|
||||
[LC3_SRATE_96K_HR] = resample_96k_12k8,
|
||||
};
|
||||
|
||||
|
||||
@@ -670,11 +719,11 @@ bool lc3_ltpf_analyse(
|
||||
LC3_MAX(pitch, ltpf->pitch) - LC3_MIN(pitch, ltpf->pitch);
|
||||
float nc_diff = nc - ltpf->nc[0];
|
||||
|
||||
data->active = pitch_present &&
|
||||
data->active = !lc3_hr(sr) && pitch_present &&
|
||||
((nc > 0.9f) || (nc > 0.84f && pitch_diff < 8 && nc_diff > -0.1f));
|
||||
|
||||
} else {
|
||||
data->active = pitch_present &&
|
||||
data->active = !lc3_hr(sr) && pitch_present &&
|
||||
( (dt == LC3_DT_10M || ltpf->nc[1] > 0.94f) &&
|
||||
(ltpf->nc[0] > 0.94f && nc > 0.94f) );
|
||||
}
|
||||
@@ -696,11 +745,8 @@ bool lc3_ltpf_analyse(
|
||||
* Width of synthesis filter
|
||||
*/
|
||||
|
||||
#define FILTER_WIDTH(sr) \
|
||||
LC3_MAX(4, LC3_SRATE_KHZ(sr) / 4)
|
||||
|
||||
#define MAX_FILTER_WIDTH \
|
||||
FILTER_WIDTH(LC3_NUM_SRATE)
|
||||
(LC3_MAX_SRATE_HZ / 4000)
|
||||
|
||||
|
||||
/**
|
||||
@@ -810,8 +856,7 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data,
|
||||
const float *xh, float *x)
|
||||
{
|
||||
int nh = LC3_NH(dt, sr);
|
||||
int dt_us = LC3_DT_US(dt);
|
||||
int nh = lc3_ns(dt, sr) + lc3_nh(dt, sr);
|
||||
|
||||
/* --- Filter parameters --- */
|
||||
|
||||
@@ -821,18 +866,18 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
p_idx >= 380 ? (((p_idx >> 1) - 63) << 2) + (((p_idx & 1)) << 1) :
|
||||
(((p_idx >> 2) + 32) << 2) + (((p_idx & 3)) << 0) ;
|
||||
|
||||
pitch = (pitch * LC3_SRATE_KHZ(sr) * 10 + 64) / 128;
|
||||
pitch = (pitch * lc3_ns(LC3_DT_10M, sr) + 64) / 128;
|
||||
|
||||
int nbits = (nbytes*8 * 10000 + (dt_us/2)) / dt_us;
|
||||
int nbits = (nbytes*8 * (1 + LC3_DT_10M)) / (1 + dt);
|
||||
if (dt == LC3_DT_2M5)
|
||||
nbits = (6 * nbits + 5) / 10;
|
||||
if (dt == LC3_DT_5M)
|
||||
nbits -= 160;
|
||||
|
||||
int g_idx = LC3_MAX(nbits / 80, 3 + (int)sr) - (3 + sr);
|
||||
int g_idx = LC3_MAX(nbits / 80, (int)(3 + sr)) - (3 + sr);
|
||||
bool active = data && data->active && g_idx < 4;
|
||||
|
||||
int w = FILTER_WIDTH(sr);
|
||||
int w = LC3_MAX(4, lc3_ns_4m[sr] >> 4);
|
||||
float c[2 * MAX_FILTER_WIDTH];
|
||||
|
||||
for (int i = 0; i < w; i++) {
|
||||
@@ -843,7 +888,7 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
|
||||
/* --- Transition handling --- */
|
||||
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
int nt = ns / (1 + dt);
|
||||
float x0[2][MAX_FILTER_WIDTH];
|
||||
|
||||
@@ -911,7 +956,8 @@ void lc3_ltpf_put_data(lc3_bits_t *bits,
|
||||
/**
|
||||
* Get bitstream data
|
||||
*/
|
||||
void lc3_ltpf_get_data(lc3_bits_t *bits, struct lc3_ltpf_data *data)
|
||||
void lc3_ltpf_get_data(lc3_bits_t *bits,
|
||||
struct lc3_ltpf_data *data)
|
||||
{
|
||||
data->active = lc3_get_bit(bits);
|
||||
data->pitch_index = lc3_get_bits(bits, 9);
|
||||
|
||||
44
src/mdct.c
44
src/mdct.c
@@ -160,7 +160,7 @@ LC3_HOT static inline void fft_bf2(
|
||||
/**
|
||||
* Perform FFT
|
||||
* x, y0, y1 Input, and 2 scratch buffers of size `n`
|
||||
* n Number of points 30, 40, 60, 80, 90, 120, 160, 180, 240
|
||||
* n Number of points 30, 40, 60, 80, 90, 120, 160, 180, 240, 480
|
||||
* return The buffer `y0` or `y1` that hold the result
|
||||
*
|
||||
* Input `x` can be the same as the `y0` second scratch buffer
|
||||
@@ -175,9 +175,9 @@ static struct lc3_complex *fft(const struct lc3_complex *x, int n,
|
||||
*
|
||||
* n = 5^1 * 3^n3 * 2^n2
|
||||
*
|
||||
* for n = 10, 20, 40, 80, 160 n3 = 0, n2 = [1..5]
|
||||
* n = 30, 60, 120, 240 n3 = 1, n2 = [1..4]
|
||||
* n = 90, 180 n3 = 2, n2 = [1..2]
|
||||
* for n = 10, 20, 40, 80, 160 n3 = 0, n2 = [1..5]
|
||||
* n = 30, 60, 120, 240, 480 n3 = 1, n2 = [1..5]
|
||||
* n = 90, 180 n3 = 2, n2 = [1..2]
|
||||
*
|
||||
* Note that the expression `n & (n-1) == 0` is equivalent
|
||||
* to the check that `n` is a power of 2. */
|
||||
@@ -200,16 +200,18 @@ static struct lc3_complex *fft(const struct lc3_complex *x, int n,
|
||||
|
||||
/**
|
||||
* Windowing of samples before MDCT
|
||||
* dt, sr Duration and samplerate (size of the transform)
|
||||
* dt, sr Duration and samplerate
|
||||
* x, y Input current and delayed samples
|
||||
* y, d Output windowed samples, and delayed ones
|
||||
*/
|
||||
LC3_HOT static void mdct_window(enum lc3_dt dt, enum lc3_srate sr,
|
||||
LC3_HOT static void mdct_window(
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *x, float *d, float *y)
|
||||
{
|
||||
int ns = LC3_NS(dt, sr), nd = LC3_ND(dt, sr);
|
||||
const float *win = lc3_mdct_win[dt][sr];
|
||||
int ns = lc3_ns(dt, sr), nd = lc3_nd(dt, sr);
|
||||
|
||||
const float *w0 = lc3_mdct_win[dt][sr], *w1 = w0 + ns;
|
||||
const float *w0 = win, *w1 = w0 + ns;
|
||||
const float *w2 = w1, *w3 = w2 + nd;
|
||||
|
||||
const float *x0 = x + ns-nd, *x1 = x0;
|
||||
@@ -362,7 +364,8 @@ LC3_HOT static void imdct_post_fft(const struct lc3_mdct_rot_def *def,
|
||||
* x, d Middle half of IMDCT coefficients and delayed samples
|
||||
* y, d Output samples and delayed ones
|
||||
*/
|
||||
LC3_HOT static void imdct_window(enum lc3_dt dt, enum lc3_srate sr,
|
||||
LC3_HOT static void imdct_window(
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *x, float *d, float *y)
|
||||
{
|
||||
/* The full MDCT coefficients is given by symmetry :
|
||||
@@ -371,8 +374,9 @@ LC3_HOT static void imdct_window(enum lc3_dt dt, enum lc3_srate sr,
|
||||
* T[ n/2 .. 3n/4-1] = half[n/4 .. n/2-1]
|
||||
* T[3n/4 .. n-1] = half[n/2-1 .. n/4 ] */
|
||||
|
||||
int n4 = LC3_NS(dt, sr) >> 1, nd = LC3_ND(dt, sr);
|
||||
const float *w2 = lc3_mdct_win[dt][sr], *w0 = w2 + 3*n4, *w1 = w0;
|
||||
const float *win = lc3_mdct_win[dt][sr];
|
||||
int n4 = lc3_ns(dt, sr) >> 1, nd = lc3_nd(dt, sr);
|
||||
const float *w2 = win, *w0 = w2 + 3*n4, *w1 = w0;
|
||||
|
||||
const float *x0 = d + nd-n4, *x1 = x0;
|
||||
float *y0 = y + nd-n4, *y1 = y0, *y2 = d + nd, *y3 = d;
|
||||
@@ -423,12 +427,13 @@ LC3_HOT static void rescale(float *x, int n, float f)
|
||||
/**
|
||||
* Forward MDCT transformation
|
||||
*/
|
||||
void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_dst, const float *x, float *d, float *y)
|
||||
void lc3_mdct_forward(
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_srate sr_dst,
|
||||
const float *x, float *d, float *y)
|
||||
{
|
||||
const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
|
||||
int ns_dst = LC3_NS(dt, sr_dst);
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns_dst = lc3_ns(dt, sr_dst);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
struct lc3_complex buffer[LC3_MAX_NS / 2];
|
||||
struct lc3_complex *z = (struct lc3_complex *)y;
|
||||
@@ -447,12 +452,13 @@ void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
|
||||
/**
|
||||
* Inverse MDCT transformation
|
||||
*/
|
||||
void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_src, const float *x, float *d, float *y)
|
||||
void lc3_mdct_inverse(
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_srate sr_src,
|
||||
const float *x, float *d, float *y)
|
||||
{
|
||||
const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
|
||||
int ns_src = LC3_NS(dt, sr_src);
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ns_src = lc3_ns(dt, sr_src);
|
||||
int ns = lc3_ns(dt, sr);
|
||||
|
||||
struct lc3_complex buffer[LC3_MAX_NS / 2];
|
||||
struct lc3_complex *z = (struct lc3_complex *)y;
|
||||
|
||||
10
src/mdct.h
10
src/mdct.h
@@ -31,8 +31,9 @@
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_dst, const float *x, float *d, float *y);
|
||||
void lc3_mdct_forward(
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_srate sr_dst,
|
||||
const float *x, float *d, float *y);
|
||||
|
||||
/**
|
||||
* Inverse MDCT transformation
|
||||
@@ -43,8 +44,9 @@ void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_src, const float *x, float *d, float *y);
|
||||
void lc3_mdct_inverse(
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_srate sr_src,
|
||||
const float *x, float *d, float *y);
|
||||
|
||||
|
||||
#endif /* __LC3_MDCT_H */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "plc.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,7 @@ void lc3_plc_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
{
|
||||
uint16_t seed = plc->seed;
|
||||
float alpha = plc->alpha;
|
||||
int ne = LC3_NE(dt, sr);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
alpha *= (plc->count < 4 ? 1.0f :
|
||||
plc->count < 8 ? 0.9f : 0.85f);
|
||||
|
||||
226
src/sns.c
226
src/sns.c
@@ -146,108 +146,139 @@ LC3_HOT static void dct16_inverse(const float *x, float *y)
|
||||
/**
|
||||
* Scale factors
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* nbytes Size in bytes of the frame
|
||||
* eb Energy estimation per bands
|
||||
* att 1: Attack detected 0: Otherwise
|
||||
* scf Output 16 scale factors
|
||||
*/
|
||||
LC3_HOT static void compute_scale_factors(
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const float *eb, bool att, float *scf)
|
||||
{
|
||||
/* Pre-emphasis gain table :
|
||||
* Ge[b] = 10 ^ (b * g_tilt) / 630 , b = [0..63] */
|
||||
|
||||
static const float ge_table[LC3_NUM_SRATE][LC3_MAX_BANDS] = {
|
||||
static const float ge_14[LC3_MAX_BANDS] = { /* g_tilt = 14 */
|
||||
1.00000000e+00, 1.05250029e+00, 1.10775685e+00, 1.16591440e+00,
|
||||
1.22712524e+00, 1.29154967e+00, 1.35935639e+00, 1.43072299e+00,
|
||||
1.50583635e+00, 1.58489319e+00, 1.66810054e+00, 1.75567629e+00,
|
||||
1.84784980e+00, 1.94486244e+00, 2.04696827e+00, 2.15443469e+00,
|
||||
2.26754313e+00, 2.38658979e+00, 2.51188643e+00, 2.64376119e+00,
|
||||
2.78255940e+00, 2.92864456e+00, 3.08239924e+00, 3.24422608e+00,
|
||||
3.41454887e+00, 3.59381366e+00, 3.78248991e+00, 3.98107171e+00,
|
||||
4.19007911e+00, 4.41005945e+00, 4.64158883e+00, 4.88527357e+00,
|
||||
5.14175183e+00, 5.41169527e+00, 5.69581081e+00, 5.99484250e+00,
|
||||
6.30957344e+00, 6.64082785e+00, 6.98947321e+00, 7.35642254e+00,
|
||||
7.74263683e+00, 8.14912747e+00, 8.57695899e+00, 9.02725178e+00,
|
||||
9.50118507e+00, 1.00000000e+01, 1.05250029e+01, 1.10775685e+01,
|
||||
1.16591440e+01, 1.22712524e+01, 1.29154967e+01, 1.35935639e+01,
|
||||
1.43072299e+01, 1.50583635e+01, 1.58489319e+01, 1.66810054e+01,
|
||||
1.75567629e+01, 1.84784980e+01, 1.94486244e+01, 2.04696827e+01,
|
||||
2.15443469e+01, 2.26754313e+01, 2.38658979e+01, 2.51188643e+01 };
|
||||
|
||||
[LC3_SRATE_8K] = { /* g_tilt = 14 */
|
||||
1.00000000e+00, 1.05250029e+00, 1.10775685e+00, 1.16591440e+00,
|
||||
1.22712524e+00, 1.29154967e+00, 1.35935639e+00, 1.43072299e+00,
|
||||
1.50583635e+00, 1.58489319e+00, 1.66810054e+00, 1.75567629e+00,
|
||||
1.84784980e+00, 1.94486244e+00, 2.04696827e+00, 2.15443469e+00,
|
||||
2.26754313e+00, 2.38658979e+00, 2.51188643e+00, 2.64376119e+00,
|
||||
2.78255940e+00, 2.92864456e+00, 3.08239924e+00, 3.24422608e+00,
|
||||
3.41454887e+00, 3.59381366e+00, 3.78248991e+00, 3.98107171e+00,
|
||||
4.19007911e+00, 4.41005945e+00, 4.64158883e+00, 4.88527357e+00,
|
||||
5.14175183e+00, 5.41169527e+00, 5.69581081e+00, 5.99484250e+00,
|
||||
6.30957344e+00, 6.64082785e+00, 6.98947321e+00, 7.35642254e+00,
|
||||
7.74263683e+00, 8.14912747e+00, 8.57695899e+00, 9.02725178e+00,
|
||||
9.50118507e+00, 1.00000000e+01, 1.05250029e+01, 1.10775685e+01,
|
||||
1.16591440e+01, 1.22712524e+01, 1.29154967e+01, 1.35935639e+01,
|
||||
1.43072299e+01, 1.50583635e+01, 1.58489319e+01, 1.66810054e+01,
|
||||
1.75567629e+01, 1.84784980e+01, 1.94486244e+01, 2.04696827e+01,
|
||||
2.15443469e+01, 2.26754313e+01, 2.38658979e+01, 2.51188643e+01 },
|
||||
static const float ge_18[LC3_MAX_BANDS] = { /* g_tilt = 18 */
|
||||
1.00000000e+00, 1.06800043e+00, 1.14062492e+00, 1.21818791e+00,
|
||||
1.30102522e+00, 1.38949549e+00, 1.48398179e+00, 1.58489319e+00,
|
||||
1.69266662e+00, 1.80776868e+00, 1.93069773e+00, 2.06198601e+00,
|
||||
2.20220195e+00, 2.35195264e+00, 2.51188643e+00, 2.68269580e+00,
|
||||
2.86512027e+00, 3.05994969e+00, 3.26802759e+00, 3.49025488e+00,
|
||||
3.72759372e+00, 3.98107171e+00, 4.25178630e+00, 4.54090961e+00,
|
||||
4.84969343e+00, 5.17947468e+00, 5.53168120e+00, 5.90783791e+00,
|
||||
6.30957344e+00, 6.73862717e+00, 7.19685673e+00, 7.68624610e+00,
|
||||
8.20891416e+00, 8.76712387e+00, 9.36329209e+00, 1.00000000e+01,
|
||||
1.06800043e+01, 1.14062492e+01, 1.21818791e+01, 1.30102522e+01,
|
||||
1.38949549e+01, 1.48398179e+01, 1.58489319e+01, 1.69266662e+01,
|
||||
1.80776868e+01, 1.93069773e+01, 2.06198601e+01, 2.20220195e+01,
|
||||
2.35195264e+01, 2.51188643e+01, 2.68269580e+01, 2.86512027e+01,
|
||||
3.05994969e+01, 3.26802759e+01, 3.49025488e+01, 3.72759372e+01,
|
||||
3.98107171e+01, 4.25178630e+01, 4.54090961e+01, 4.84969343e+01,
|
||||
5.17947468e+01, 5.53168120e+01, 5.90783791e+01, 6.30957344e+01 };
|
||||
|
||||
[LC3_SRATE_16K] = { /* g_tilt = 18 */
|
||||
1.00000000e+00, 1.06800043e+00, 1.14062492e+00, 1.21818791e+00,
|
||||
1.30102522e+00, 1.38949549e+00, 1.48398179e+00, 1.58489319e+00,
|
||||
1.69266662e+00, 1.80776868e+00, 1.93069773e+00, 2.06198601e+00,
|
||||
2.20220195e+00, 2.35195264e+00, 2.51188643e+00, 2.68269580e+00,
|
||||
2.86512027e+00, 3.05994969e+00, 3.26802759e+00, 3.49025488e+00,
|
||||
3.72759372e+00, 3.98107171e+00, 4.25178630e+00, 4.54090961e+00,
|
||||
4.84969343e+00, 5.17947468e+00, 5.53168120e+00, 5.90783791e+00,
|
||||
6.30957344e+00, 6.73862717e+00, 7.19685673e+00, 7.68624610e+00,
|
||||
8.20891416e+00, 8.76712387e+00, 9.36329209e+00, 1.00000000e+01,
|
||||
1.06800043e+01, 1.14062492e+01, 1.21818791e+01, 1.30102522e+01,
|
||||
1.38949549e+01, 1.48398179e+01, 1.58489319e+01, 1.69266662e+01,
|
||||
1.80776868e+01, 1.93069773e+01, 2.06198601e+01, 2.20220195e+01,
|
||||
2.35195264e+01, 2.51188643e+01, 2.68269580e+01, 2.86512027e+01,
|
||||
3.05994969e+01, 3.26802759e+01, 3.49025488e+01, 3.72759372e+01,
|
||||
3.98107171e+01, 4.25178630e+01, 4.54090961e+01, 4.84969343e+01,
|
||||
5.17947468e+01, 5.53168120e+01, 5.90783791e+01, 6.30957344e+01 },
|
||||
static const float ge_22[LC3_MAX_BANDS] = { /* g_tilt = 22 */
|
||||
1.00000000e+00, 1.08372885e+00, 1.17446822e+00, 1.27280509e+00,
|
||||
1.37937560e+00, 1.49486913e+00, 1.62003281e+00, 1.75567629e+00,
|
||||
1.90267705e+00, 2.06198601e+00, 2.23463373e+00, 2.42173704e+00,
|
||||
2.62450630e+00, 2.84425319e+00, 3.08239924e+00, 3.34048498e+00,
|
||||
3.62017995e+00, 3.92329345e+00, 4.25178630e+00, 4.60778348e+00,
|
||||
4.99358789e+00, 5.41169527e+00, 5.86481029e+00, 6.35586411e+00,
|
||||
6.88803330e+00, 7.46476041e+00, 8.08977621e+00, 8.76712387e+00,
|
||||
9.50118507e+00, 1.02967084e+01, 1.11588399e+01, 1.20931568e+01,
|
||||
1.31057029e+01, 1.42030283e+01, 1.53922315e+01, 1.66810054e+01,
|
||||
1.80776868e+01, 1.95913107e+01, 2.12316686e+01, 2.30093718e+01,
|
||||
2.49359200e+01, 2.70237760e+01, 2.92864456e+01, 3.17385661e+01,
|
||||
3.43959997e+01, 3.72759372e+01, 4.03970086e+01, 4.37794036e+01,
|
||||
4.74450028e+01, 5.14175183e+01, 5.57226480e+01, 6.03882412e+01,
|
||||
6.54444792e+01, 7.09240702e+01, 7.68624610e+01, 8.32980665e+01,
|
||||
9.02725178e+01, 9.78309319e+01, 1.06022203e+02, 1.14899320e+02,
|
||||
1.24519708e+02, 1.34945600e+02, 1.46244440e+02, 1.58489319e+02 };
|
||||
|
||||
[LC3_SRATE_24K] = { /* g_tilt = 22 */
|
||||
1.00000000e+00, 1.08372885e+00, 1.17446822e+00, 1.27280509e+00,
|
||||
1.37937560e+00, 1.49486913e+00, 1.62003281e+00, 1.75567629e+00,
|
||||
1.90267705e+00, 2.06198601e+00, 2.23463373e+00, 2.42173704e+00,
|
||||
2.62450630e+00, 2.84425319e+00, 3.08239924e+00, 3.34048498e+00,
|
||||
3.62017995e+00, 3.92329345e+00, 4.25178630e+00, 4.60778348e+00,
|
||||
4.99358789e+00, 5.41169527e+00, 5.86481029e+00, 6.35586411e+00,
|
||||
6.88803330e+00, 7.46476041e+00, 8.08977621e+00, 8.76712387e+00,
|
||||
9.50118507e+00, 1.02967084e+01, 1.11588399e+01, 1.20931568e+01,
|
||||
1.31057029e+01, 1.42030283e+01, 1.53922315e+01, 1.66810054e+01,
|
||||
1.80776868e+01, 1.95913107e+01, 2.12316686e+01, 2.30093718e+01,
|
||||
2.49359200e+01, 2.70237760e+01, 2.92864456e+01, 3.17385661e+01,
|
||||
3.43959997e+01, 3.72759372e+01, 4.03970086e+01, 4.37794036e+01,
|
||||
4.74450028e+01, 5.14175183e+01, 5.57226480e+01, 6.03882412e+01,
|
||||
6.54444792e+01, 7.09240702e+01, 7.68624610e+01, 8.32980665e+01,
|
||||
9.02725178e+01, 9.78309319e+01, 1.06022203e+02, 1.14899320e+02,
|
||||
1.24519708e+02, 1.34945600e+02, 1.46244440e+02, 1.58489319e+02 },
|
||||
static const float ge_26[LC3_MAX_BANDS] = { /* g_tilt = 26 */
|
||||
1.00000000e+00, 1.09968890e+00, 1.20931568e+00, 1.32987103e+00,
|
||||
1.46244440e+00, 1.60823388e+00, 1.76855694e+00, 1.94486244e+00,
|
||||
2.13874364e+00, 2.35195264e+00, 2.58641621e+00, 2.84425319e+00,
|
||||
3.12779366e+00, 3.43959997e+00, 3.78248991e+00, 4.15956216e+00,
|
||||
4.57422434e+00, 5.03022373e+00, 5.53168120e+00, 6.08312841e+00,
|
||||
6.68954879e+00, 7.35642254e+00, 8.08977621e+00, 8.89623710e+00,
|
||||
9.78309319e+00, 1.07583590e+01, 1.18308480e+01, 1.30102522e+01,
|
||||
1.43072299e+01, 1.57335019e+01, 1.73019574e+01, 1.90267705e+01,
|
||||
2.09235283e+01, 2.30093718e+01, 2.53031508e+01, 2.78255940e+01,
|
||||
3.05994969e+01, 3.36499270e+01, 3.70044512e+01, 4.06933843e+01,
|
||||
4.47500630e+01, 4.92111475e+01, 5.41169527e+01, 5.95118121e+01,
|
||||
6.54444792e+01, 7.19685673e+01, 7.91430346e+01, 8.70327166e+01,
|
||||
9.57089124e+01, 1.05250029e+02, 1.15742288e+02, 1.27280509e+02,
|
||||
1.39968963e+02, 1.53922315e+02, 1.69266662e+02, 1.86140669e+02,
|
||||
2.04696827e+02, 2.25102829e+02, 2.47543082e+02, 2.72220379e+02,
|
||||
2.99357729e+02, 3.29200372e+02, 3.62017995e+02, 3.98107171e+02 };
|
||||
|
||||
[LC3_SRATE_32K] = { /* g_tilt = 26 */
|
||||
1.00000000e+00, 1.09968890e+00, 1.20931568e+00, 1.32987103e+00,
|
||||
1.46244440e+00, 1.60823388e+00, 1.76855694e+00, 1.94486244e+00,
|
||||
2.13874364e+00, 2.35195264e+00, 2.58641621e+00, 2.84425319e+00,
|
||||
3.12779366e+00, 3.43959997e+00, 3.78248991e+00, 4.15956216e+00,
|
||||
4.57422434e+00, 5.03022373e+00, 5.53168120e+00, 6.08312841e+00,
|
||||
6.68954879e+00, 7.35642254e+00, 8.08977621e+00, 8.89623710e+00,
|
||||
9.78309319e+00, 1.07583590e+01, 1.18308480e+01, 1.30102522e+01,
|
||||
1.43072299e+01, 1.57335019e+01, 1.73019574e+01, 1.90267705e+01,
|
||||
2.09235283e+01, 2.30093718e+01, 2.53031508e+01, 2.78255940e+01,
|
||||
3.05994969e+01, 3.36499270e+01, 3.70044512e+01, 4.06933843e+01,
|
||||
4.47500630e+01, 4.92111475e+01, 5.41169527e+01, 5.95118121e+01,
|
||||
6.54444792e+01, 7.19685673e+01, 7.91430346e+01, 8.70327166e+01,
|
||||
9.57089124e+01, 1.05250029e+02, 1.15742288e+02, 1.27280509e+02,
|
||||
1.39968963e+02, 1.53922315e+02, 1.69266662e+02, 1.86140669e+02,
|
||||
2.04696827e+02, 2.25102829e+02, 2.47543082e+02, 2.72220379e+02,
|
||||
2.99357729e+02, 3.29200372e+02, 3.62017995e+02, 3.98107171e+02 },
|
||||
static const float ge_30[LC3_MAX_BANDS] = { /* g_tilt = 30 */
|
||||
1.00000000e+00, 1.11588399e+00, 1.24519708e+00, 1.38949549e+00,
|
||||
1.55051578e+00, 1.73019574e+00, 1.93069773e+00, 2.15443469e+00,
|
||||
2.40409918e+00, 2.68269580e+00, 2.99357729e+00, 3.34048498e+00,
|
||||
3.72759372e+00, 4.15956216e+00, 4.64158883e+00, 5.17947468e+00,
|
||||
5.77969288e+00, 6.44946677e+00, 7.19685673e+00, 8.03085722e+00,
|
||||
8.96150502e+00, 1.00000000e+01, 1.11588399e+01, 1.24519708e+01,
|
||||
1.38949549e+01, 1.55051578e+01, 1.73019574e+01, 1.93069773e+01,
|
||||
2.15443469e+01, 2.40409918e+01, 2.68269580e+01, 2.99357729e+01,
|
||||
3.34048498e+01, 3.72759372e+01, 4.15956216e+01, 4.64158883e+01,
|
||||
5.17947468e+01, 5.77969288e+01, 6.44946677e+01, 7.19685673e+01,
|
||||
8.03085722e+01, 8.96150502e+01, 1.00000000e+02, 1.11588399e+02,
|
||||
1.24519708e+02, 1.38949549e+02, 1.55051578e+02, 1.73019574e+02,
|
||||
1.93069773e+02, 2.15443469e+02, 2.40409918e+02, 2.68269580e+02,
|
||||
2.99357729e+02, 3.34048498e+02, 3.72759372e+02, 4.15956216e+02,
|
||||
4.64158883e+02, 5.17947468e+02, 5.77969288e+02, 6.44946677e+02,
|
||||
7.19685673e+02, 8.03085722e+02, 8.96150502e+02, 1.00000000e+03 };
|
||||
|
||||
#if LC3_PLUS_HR
|
||||
|
||||
static const float ge_34[LC3_MAX_BANDS] = { /* g_tilt = 34 */
|
||||
1.00000000e+00, 1.13231759e+00, 1.28214312e+00, 1.45179321e+00,
|
||||
1.64389099e+00, 1.86140669e+00, 2.10770353e+00, 2.38658979e+00,
|
||||
2.70237760e+00, 3.05994969e+00, 3.46483486e+00, 3.92329345e+00,
|
||||
4.44241419e+00, 5.03022373e+00, 5.69581081e+00, 6.44946677e+00,
|
||||
7.30284467e+00, 8.26913948e+00, 9.36329209e+00, 1.06022203e+01,
|
||||
1.20050806e+01, 1.35935639e+01, 1.53922315e+01, 1.74288945e+01,
|
||||
1.97350438e+01, 2.23463373e+01, 2.53031508e+01, 2.86512027e+01,
|
||||
3.24422608e+01, 3.67349426e+01, 4.15956216e+01, 4.70994540e+01,
|
||||
5.33315403e+01, 6.03882412e+01, 6.83786677e+01, 7.74263683e+01,
|
||||
8.76712387e+01, 9.92716858e+01, 1.12407076e+02, 1.27280509e+02,
|
||||
1.44121960e+02, 1.63191830e+02, 1.84784980e+02, 2.09235283e+02,
|
||||
2.36920791e+02, 2.68269580e+02, 3.03766364e+02, 3.43959997e+02,
|
||||
3.89471955e+02, 4.41005945e+02, 4.99358789e+02, 5.65432741e+02,
|
||||
6.40249439e+02, 7.24965701e+02, 8.20891416e+02, 9.29509790e+02,
|
||||
1.05250029e+03, 1.19176459e+03, 1.34945600e+03, 1.52801277e+03,
|
||||
1.73019574e+03, 1.95913107e+03, 2.21835857e+03, 2.51188643e+03 };
|
||||
|
||||
#endif /* LC3_PLUS_HR */
|
||||
|
||||
static const float *ge_table[LC3_NUM_SRATE] = {
|
||||
[LC3_SRATE_8K ] = ge_14, [LC3_SRATE_16K ] = ge_18,
|
||||
[LC3_SRATE_24K ] = ge_22, [LC3_SRATE_32K ] = ge_26,
|
||||
[LC3_SRATE_48K ] = ge_30,
|
||||
|
||||
#if LC3_PLUS_HR
|
||||
[LC3_SRATE_48K_HR] = ge_30, [LC3_SRATE_96K_HR] = ge_34,
|
||||
#endif /* LC3_PLUS_HR */
|
||||
|
||||
[LC3_SRATE_48K] = { /* g_tilt = 30 */
|
||||
1.00000000e+00, 1.11588399e+00, 1.24519708e+00, 1.38949549e+00,
|
||||
1.55051578e+00, 1.73019574e+00, 1.93069773e+00, 2.15443469e+00,
|
||||
2.40409918e+00, 2.68269580e+00, 2.99357729e+00, 3.34048498e+00,
|
||||
3.72759372e+00, 4.15956216e+00, 4.64158883e+00, 5.17947468e+00,
|
||||
5.77969288e+00, 6.44946677e+00, 7.19685673e+00, 8.03085722e+00,
|
||||
8.96150502e+00, 1.00000000e+01, 1.11588399e+01, 1.24519708e+01,
|
||||
1.38949549e+01, 1.55051578e+01, 1.73019574e+01, 1.93069773e+01,
|
||||
2.15443469e+01, 2.40409918e+01, 2.68269580e+01, 2.99357729e+01,
|
||||
3.34048498e+01, 3.72759372e+01, 4.15956216e+01, 4.64158883e+01,
|
||||
5.17947468e+01, 5.77969288e+01, 6.44946677e+01, 7.19685673e+01,
|
||||
8.03085722e+01, 8.96150502e+01, 1.00000000e+02, 1.11588399e+02,
|
||||
1.24519708e+02, 1.38949549e+02, 1.55051578e+02, 1.73019574e+02,
|
||||
1.93069773e+02, 2.15443469e+02, 2.40409918e+02, 2.68269580e+02,
|
||||
2.99357729e+02, 3.34048498e+02, 3.72759372e+02, 4.15956216e+02,
|
||||
4.64158883e+02, 5.17947468e+02, 5.77969288e+02, 6.44946677e+02,
|
||||
7.19685673e+02, 8.03085722e+02, 8.96150502e+02, 1.00000000e+03 },
|
||||
};
|
||||
|
||||
float e[LC3_MAX_BANDS];
|
||||
@@ -291,7 +322,7 @@ LC3_HOT static void compute_scale_factors(
|
||||
float noise_floor = fmaxf(e_sum * (1e-4f / 64), 0x1p-32f);
|
||||
|
||||
for (int i = 0; i < LC3_MAX_BANDS; i++)
|
||||
e[i] = fast_log2f(fmaxf(e[i], noise_floor)) * 0.5f;
|
||||
e[i] = lc3_log2f(fmaxf(e[i], noise_floor)) * 0.5f;
|
||||
|
||||
/* --- Grouping & scaling --- */
|
||||
|
||||
@@ -314,8 +345,13 @@ LC3_HOT static void compute_scale_factors(
|
||||
(e[61] + e[62]) * 3.f/12 ;
|
||||
scf_sum += scf[15];
|
||||
|
||||
float cf = lc3_hr(sr) ? 0.6f : 0.85f;
|
||||
if (lc3_hr(sr) && 8 * nbytes >
|
||||
(dt < LC3_DT_10M ? 1150 * (int)(1 + dt) : 4400))
|
||||
cf *= dt < LC3_DT_10M ? 0.25f : 0.35f;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
scf[i] = 0.85f * (scf[i] - scf_sum * 1.f/16);
|
||||
scf[i] = cf * (scf[i] - scf_sum * 1.f/16);
|
||||
|
||||
/* --- Attack handling --- */
|
||||
|
||||
@@ -714,10 +750,10 @@ LC3_HOT static void spectral_shaping(enum lc3_dt dt, enum lc3_srate sr,
|
||||
|
||||
/* --- Spectral shaping --- */
|
||||
|
||||
const uint16_t *lim = lc3_band_lim[dt][sr];
|
||||
const int *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
for (int i = 0, ib = 0; ib < nb; ib++) {
|
||||
float g_sns = fast_exp2f(-scf[ib]);
|
||||
float g_sns = lc3_exp2f(-scf[ib]);
|
||||
|
||||
for ( ; i < lim[ib+1]; i++)
|
||||
y[i] = x[i] * g_sns;
|
||||
@@ -732,7 +768,8 @@ LC3_HOT static void spectral_shaping(enum lc3_dt dt, enum lc3_srate sr,
|
||||
/**
|
||||
* SNS analysis
|
||||
*/
|
||||
void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
void lc3_sns_analyze(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const float *eb, bool att, struct lc3_sns_data *data,
|
||||
const float *x, float *y)
|
||||
{
|
||||
@@ -746,7 +783,7 @@ void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
float scf[16], cn[4][16];
|
||||
int c[4][16];
|
||||
|
||||
compute_scale_factors(dt, sr, eb, att, scf);
|
||||
compute_scale_factors(dt, sr, nbytes, eb, att, scf);
|
||||
|
||||
resolve_codebooks(scf, &data->lfcb, &data->hfcb);
|
||||
|
||||
@@ -765,7 +802,8 @@ void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
/**
|
||||
* SNS synthesis
|
||||
*/
|
||||
void lc3_sns_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
void lc3_sns_synthesize(
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
const lc3_sns_data_t *data, const float *x, float *y)
|
||||
{
|
||||
float scf[16], cn[16];
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef struct lc3_sns_data {
|
||||
/**
|
||||
* SNS analysis
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* nbytes Size in bytes of the frame
|
||||
* eb Energy estimation per bands, and count of bands
|
||||
* att 1: Attack detected 0: Otherwise
|
||||
* data Return bitstream data
|
||||
@@ -50,7 +51,8 @@ typedef struct lc3_sns_data {
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
void lc3_sns_analyze(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const float *eb, bool att, lc3_sns_data_t *data,
|
||||
const float *x, float *y);
|
||||
|
||||
|
||||
438
src/spec.c
438
src/spec.c
@@ -32,14 +32,46 @@
|
||||
*/
|
||||
static int resolve_gain_offset(enum lc3_srate sr, int nbytes)
|
||||
{
|
||||
int g_off = (nbytes * 8) / (10 * (1 + sr));
|
||||
return 105 + 5*(1 + sr) + LC3_MIN(g_off, 115);
|
||||
int sr_ind = lc3_hr(sr) ? 4 + (sr - LC3_SRATE_48K_HR) : sr;
|
||||
|
||||
int g_off = (nbytes * 8) / (10 * (1 + sr_ind));
|
||||
return LC3_MIN(lc3_hr(sr) ? 181 : 255,
|
||||
105 + 5*(1 + sr_ind) + LC3_MIN(g_off, 115));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquantize gain
|
||||
* g_int Quantization gain value
|
||||
* return Unquantized gain value
|
||||
*/
|
||||
static float unquantize_gain(int g_int)
|
||||
{
|
||||
/* Unquantization gain table :
|
||||
* G[i] = 10 ^ (i / 28) , i = [0..27] */
|
||||
|
||||
static const float iq_table[] = {
|
||||
1.00000000e+00, 1.08571112e+00, 1.17876863e+00, 1.27980221e+00,
|
||||
1.38949549e+00, 1.50859071e+00, 1.63789371e+00, 1.77827941e+00,
|
||||
1.93069773e+00, 2.09617999e+00, 2.27584593e+00, 2.47091123e+00,
|
||||
2.68269580e+00, 2.91263265e+00, 3.16227766e+00, 3.43332002e+00,
|
||||
3.72759372e+00, 4.04708995e+00, 4.39397056e+00, 4.77058270e+00,
|
||||
5.17947468e+00, 5.62341325e+00, 6.10540230e+00, 6.62870316e+00,
|
||||
7.19685673e+00, 7.81370738e+00, 8.48342898e+00, 9.21055318e+00
|
||||
};
|
||||
|
||||
float g = 1.f;
|
||||
|
||||
for ( ; g_int < 0; g_int += 28, g *= 0.1f);
|
||||
for ( ; g_int >= 28; g_int -= 28, g *= 10.f);
|
||||
|
||||
return g * iq_table[g_int];
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Gain Estimation
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* x Spectral coefficients
|
||||
* nbytes Size of the frame
|
||||
* nbits_budget Number of bits available coding the spectrum
|
||||
* nbits_off Offset on the available bits, temporarily smoothed
|
||||
* g_off Gain index offset
|
||||
@@ -49,29 +81,65 @@ static int resolve_gain_offset(enum lc3_srate sr, int nbytes)
|
||||
*/
|
||||
LC3_HOT static int estimate_gain(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x,
|
||||
int nbits_budget, float nbits_off, int g_off, bool *reset_off, int *g_min)
|
||||
int nbytes, int nbits_budget, float nbits_off, int g_off,
|
||||
bool *reset_off, int *g_min)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr) >> 2;
|
||||
int e[LC3_MAX_NE];
|
||||
int n4 = lc3_ne(dt, sr) / 4;
|
||||
union { float f; int32_t q16; } e[LC3_MAX_NE / 4];
|
||||
|
||||
/* --- Signal adaptative noise floor --- */
|
||||
|
||||
int reg_bits = 0;
|
||||
float low_bits = 0;
|
||||
|
||||
if (lc3_hr(sr)) {
|
||||
int reg_c = (const int [LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_48K_HR]){
|
||||
[LC3_DT_2M5] = { -6, -6 },
|
||||
[LC3_DT_5M ] = { 0, 0 },
|
||||
[LC3_DT_10M] = { 2, 5 }
|
||||
}[dt][sr - LC3_SRATE_48K_HR];
|
||||
|
||||
reg_bits = (8*nbytes * 4) / (125 * (1 + dt));
|
||||
reg_bits = LC3_CLIP(reg_bits + reg_c, 6, 23);
|
||||
|
||||
float m0 = 1e-5f, m1 = 1e-5f, k = 0;
|
||||
|
||||
for (int i = 0; i < n4; i++) {
|
||||
m0 += fabsf(x[4*i + 0]), m1 += fabsf(x[4*i + 0]) * k++;
|
||||
m0 += fabsf(x[4*i + 1]), m1 += fabsf(x[4*i + 1]) * k++;
|
||||
m0 += fabsf(x[4*i + 2]), m1 += fabsf(x[4*i + 2]) * k++;
|
||||
m0 += fabsf(x[4*i + 3]), m1 += fabsf(x[4*i + 3]) * k++;
|
||||
}
|
||||
|
||||
int m = roundf((1.6f * m0) / ((1 + dt) * m1));
|
||||
low_bits = 8 - LC3_MIN(m, 8);
|
||||
}
|
||||
|
||||
/* --- Energy (dB) by 4 MDCT blocks --- */
|
||||
|
||||
float x2_max = 0;
|
||||
|
||||
for (int i = 0; i < ne; i++, x += 4) {
|
||||
float x0 = x[0] * x[0];
|
||||
float x1 = x[1] * x[1];
|
||||
float x2 = x[2] * x[2];
|
||||
float x3 = x[3] * x[3];
|
||||
for (int i = 0; i < n4; i++) {
|
||||
float x0 = x[4*i + 0] * x[4*i + 0];
|
||||
float x1 = x[4*i + 1] * x[4*i + 1];
|
||||
float x2 = x[4*i + 2] * x[4*i + 2];
|
||||
float x3 = x[4*i + 3] * x[4*i + 3];
|
||||
|
||||
x2_max = fmaxf(x2_max, x0);
|
||||
x2_max = fmaxf(x2_max, x1);
|
||||
x2_max = fmaxf(x2_max, x2);
|
||||
x2_max = fmaxf(x2_max, x3);
|
||||
|
||||
e[i] = fast_db_q16(fmaxf(x0 + x1 + x2 + x3, 1e-10f));
|
||||
e[i].f = x0 + x1 + x2 + x3;
|
||||
}
|
||||
|
||||
float x_max = sqrtf(x2_max);
|
||||
float nf = lc3_hr(sr) ?
|
||||
ldexpf(x_max, -reg_bits) * lc3_exp2f(-low_bits) : 0;
|
||||
|
||||
for (int i = 0; i < n4; i++)
|
||||
e[i].q16 = lc3_db_q16(fmaxf(e[i].f + nf, 1e-10f));
|
||||
|
||||
/* --- Determine gain index --- */
|
||||
|
||||
int nbits = nbits_budget + nbits_off + 0.5f;
|
||||
@@ -81,14 +149,14 @@ LC3_HOT static int estimate_gain(
|
||||
const int k_2u7 = 2.7f * 0x1p16f + 0.5f;
|
||||
const int k_1u4 = 1.4f * 0x1p16f + 0.5f;
|
||||
|
||||
for (int i = 128, j, j0 = ne-1, j1 ; i > 0; i >>= 1) {
|
||||
for (int i = 128, j, j0 = n4-1, j1 ; i > 0; i >>= 1) {
|
||||
int gn = (g_int - i) * k_20_28;
|
||||
int v = 0;
|
||||
|
||||
for (j = j0; j >= 0 && e[j] < gn; j--);
|
||||
for (j = j0; j >= 0 && e[j].q16 < gn; j--);
|
||||
|
||||
for (j1 = j; j >= 0; j--) {
|
||||
int e_diff = e[j] - gn;
|
||||
int e_diff = e[j].q16 - gn;
|
||||
|
||||
v += e_diff < 0 ? k_2u7 :
|
||||
e_diff < 43 << 16 ? e_diff + ( 7 << 16)
|
||||
@@ -103,10 +171,14 @@ LC3_HOT static int estimate_gain(
|
||||
|
||||
/* --- Limit gain index --- */
|
||||
|
||||
*g_min = x2_max == 0 ? -g_off :
|
||||
ceilf(28 * log10f(sqrtf(x2_max) / (32768 - 0.375f)));
|
||||
float x_lim = lc3_hr(sr) ? 0x7fffp8f : 0x7fffp0f;
|
||||
|
||||
*reset_off = g_int < *g_min || x2_max == 0;
|
||||
*g_min = 255 - g_off;
|
||||
for (int i = 128 ; i > 0; i >>= 1)
|
||||
if (x_lim * unquantize_gain(*g_min - i) > x_max)
|
||||
*g_min -= i;
|
||||
|
||||
*reset_off = g_int < *g_min || x_max == 0;
|
||||
if (*reset_off)
|
||||
g_int = *g_min;
|
||||
|
||||
@@ -115,21 +187,23 @@ LC3_HOT static int estimate_gain(
|
||||
|
||||
/**
|
||||
* Global Gain Adjustment
|
||||
* sr Samplerate of the frame
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* g_idx The estimated quantized gain index
|
||||
* nbits Computed number of bits coding the spectrum
|
||||
* nbits_budget Number of bits available for coding the spectrum
|
||||
* g_idx_min Minimum gain index value
|
||||
* return Gain adjust value (-1 to 2)
|
||||
*/
|
||||
LC3_HOT static int adjust_gain(enum lc3_srate sr, int g_idx,
|
||||
int nbits, int nbits_budget, int g_idx_min)
|
||||
LC3_HOT static int adjust_gain(
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
int g_idx, int nbits, int nbits_budget, int g_idx_min)
|
||||
{
|
||||
/* --- Compute delta threshold --- */
|
||||
|
||||
const int *t = (const int [LC3_NUM_SRATE][3]){
|
||||
{ 80, 500, 850 }, { 230, 1025, 1700 }, { 380, 1550, 2550 },
|
||||
{ 530, 2075, 3400 }, { 680, 2600, 4250 }
|
||||
{ 530, 2075, 3400 }, { 680, 2600, 4250 },
|
||||
{ 680, 2600, 4250 }, { 830, 3125, 5100 }
|
||||
}[sr];
|
||||
|
||||
int delta, den = 48;
|
||||
@@ -150,84 +224,46 @@ LC3_HOT static int adjust_gain(enum lc3_srate sr, int g_idx,
|
||||
|
||||
/* --- Adjust gain --- */
|
||||
|
||||
if (nbits < nbits_budget - (delta + 2))
|
||||
if (lc3_hr(sr) && nbits > nbits_budget) {
|
||||
int factor = 1 + (dt <= LC3_DT_5M) +
|
||||
(dt <= LC3_DT_2M5) * (1 + (nbits >= 520));
|
||||
|
||||
int g_incr = factor + (factor * (nbits - nbits_budget)) / delta;
|
||||
return LC3_MIN(g_idx + g_incr, 255) - g_idx;
|
||||
}
|
||||
|
||||
if (!lc3_hr(sr) && nbits < nbits_budget - (delta + 2))
|
||||
return -(g_idx > g_idx_min);
|
||||
|
||||
if (nbits > nbits_budget)
|
||||
if (!lc3_hr(sr) && nbits > nbits_budget)
|
||||
return (g_idx < 255) + (g_idx < 254 && nbits >= nbits_budget + delta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquantize gain
|
||||
* g_int Quantization gain value
|
||||
* return Unquantized gain value
|
||||
*/
|
||||
static float unquantize_gain(int g_int)
|
||||
{
|
||||
/* Unquantization gain table :
|
||||
* G[i] = 10 ^ (i / 28) , i = [0..64] */
|
||||
|
||||
static const float iq_table[] = {
|
||||
1.00000000e+00, 1.08571112e+00, 1.17876863e+00, 1.27980221e+00,
|
||||
1.38949549e+00, 1.50859071e+00, 1.63789371e+00, 1.77827941e+00,
|
||||
1.93069773e+00, 2.09617999e+00, 2.27584593e+00, 2.47091123e+00,
|
||||
2.68269580e+00, 2.91263265e+00, 3.16227766e+00, 3.43332002e+00,
|
||||
3.72759372e+00, 4.04708995e+00, 4.39397056e+00, 4.77058270e+00,
|
||||
5.17947468e+00, 5.62341325e+00, 6.10540230e+00, 6.62870316e+00,
|
||||
7.19685673e+00, 7.81370738e+00, 8.48342898e+00, 9.21055318e+00,
|
||||
1.00000000e+01, 1.08571112e+01, 1.17876863e+01, 1.27980221e+01,
|
||||
1.38949549e+01, 1.50859071e+01, 1.63789371e+01, 1.77827941e+01,
|
||||
1.93069773e+01, 2.09617999e+01, 2.27584593e+01, 2.47091123e+01,
|
||||
2.68269580e+01, 2.91263265e+01, 3.16227766e+01, 3.43332002e+01,
|
||||
3.72759372e+01, 4.04708995e+01, 4.39397056e+01, 4.77058270e+01,
|
||||
5.17947468e+01, 5.62341325e+01, 6.10540230e+01, 6.62870316e+01,
|
||||
7.19685673e+01, 7.81370738e+01, 8.48342898e+01, 9.21055318e+01,
|
||||
1.00000000e+02, 1.08571112e+02, 1.17876863e+02, 1.27980221e+02,
|
||||
1.38949549e+02, 1.50859071e+02, 1.63789371e+02, 1.77827941e+02,
|
||||
1.93069773e+02
|
||||
};
|
||||
|
||||
float g = iq_table[LC3_ABS(g_int) & 0x3f];
|
||||
for(int n64 = LC3_ABS(g_int) >> 6; n64--; )
|
||||
g *= iq_table[64];
|
||||
|
||||
return g_int >= 0 ? g : 1 / g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spectrum quantization
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* g_int Quantization gain value
|
||||
* x Spectral coefficients, scaled as output
|
||||
* xq, nq Output spectral quantized coefficients, and count
|
||||
*
|
||||
* The spectral coefficients `xq` are stored as :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
* n Return count of significants
|
||||
*/
|
||||
LC3_HOT static void quantize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int g_int, float *x, uint16_t *xq, int *nq)
|
||||
LC3_HOT static void quantize(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int g_int, float *x, int *n)
|
||||
{
|
||||
float g_inv = 1 / unquantize_gain(g_int);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
float g_inv = unquantize_gain(-g_int);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
*nq = ne;
|
||||
*n = ne;
|
||||
|
||||
for (int i = 0; i < ne; i += 2) {
|
||||
uint16_t x0, x1;
|
||||
float xq_min = lc3_hr(sr) ? 0.5f : 10.f/16;
|
||||
|
||||
x[i+0] *= g_inv;
|
||||
x[i+1] *= g_inv;
|
||||
|
||||
x0 = fminf(fabsf(x[i+0]) + 6.f/16, INT16_MAX);
|
||||
x1 = fminf(fabsf(x[i+1]) + 6.f/16, INT16_MAX);
|
||||
|
||||
xq[i+0] = (x0 << 1) + ((x0 > 0) & (x[i+0] < 0));
|
||||
xq[i+1] = (x1 << 1) + ((x1 > 0) & (x[i+1] < 0));
|
||||
|
||||
*nq = x0 || x1 ? ne : *nq - 2;
|
||||
*n = fabsf(x[i+0]) >= xq_min ||
|
||||
fabsf(x[i+1]) >= xq_min ? ne : *n - 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,11 +274,12 @@ LC3_HOT static void quantize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
* x, nq Spectral quantized, and count of significants
|
||||
* return Unquantized gain value
|
||||
*/
|
||||
LC3_HOT static float unquantize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
LC3_HOT static float unquantize(
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
int g_int, float *x, int nq)
|
||||
{
|
||||
float g = unquantize_gain(g_int);
|
||||
int i, ne = LC3_NE(dt, sr);
|
||||
int i, ne = lc3_ne(dt, sr);
|
||||
|
||||
for (i = 0; i < nq; i++)
|
||||
x[i] = x[i] * g;
|
||||
@@ -259,13 +296,19 @@ LC3_HOT static float unquantize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resolve High-bitrate mode according size of the frame
|
||||
* Resolve High-bitrate and LSB modes according size of the frame
|
||||
* sr, nbytes Samplerate and size of the frame
|
||||
* p_lsb_mode True when LSB mode allowed, when not NULL
|
||||
* return True when High-Rate mode enabled
|
||||
*/
|
||||
static int resolve_high_rate(enum lc3_srate sr, int nbytes)
|
||||
static bool resolve_modes(enum lc3_srate sr, int nbytes, bool *p_lsb_mode)
|
||||
{
|
||||
return nbytes > 20 * (1 + (int)sr);
|
||||
int sr_ind = lc3_hr(sr) ? 4 + (sr - LC3_SRATE_48K_HR) : sr;
|
||||
|
||||
if (p_lsb_mode)
|
||||
*p_lsb_mode = (nbytes >= 20 * (3 + sr_ind)) && (sr < LC3_SRATE_96K_HR);
|
||||
|
||||
return (nbytes > 20 * (1 + sr_ind)) && (sr < LC3_SRATE_96K_HR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,21 +319,13 @@ static int resolve_high_rate(enum lc3_srate sr, int nbytes)
|
||||
* nbits_budget Truncate to stay in budget, when not zero
|
||||
* p_lsb_mode Return True when LSB's are not AC coded, or NULL
|
||||
* return The number of bits coding the spectrum
|
||||
*
|
||||
* The spectral coefficients `x` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
*/
|
||||
LC3_HOT static int compute_nbits(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const uint16_t *x, int *n, int nbits_budget, bool *p_lsb_mode)
|
||||
const float *x, int *n, int nbits_budget, bool *p_lsb_mode)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
|
||||
/* --- Mode and rate --- */
|
||||
|
||||
bool lsb_mode = nbytes >= 20 * (3 + (int)sr);
|
||||
bool high_rate = resolve_high_rate(sr, nbytes);
|
||||
bool lsb_mode, high_rate = resolve_modes(sr, nbytes, &lsb_mode);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
/* --- Loop on quantized coefficients --- */
|
||||
|
||||
@@ -308,12 +343,15 @@ LC3_HOT static int compute_nbits(
|
||||
for ( ; i < LC3_MIN(*n, (ne + 2) >> (1 - h))
|
||||
&& nbits <= nbits_budget; i += 2) {
|
||||
|
||||
float xq_off = lc3_hr(sr) ? 0.5f : 6.f/16;
|
||||
uint32_t a = fabsf(x[i+0]) + xq_off;
|
||||
uint32_t b = fabsf(x[i+1]) + xq_off;
|
||||
|
||||
const uint8_t *lut = lut_coeff[state];
|
||||
uint16_t a = x[i] >> 1, b = x[i+1] >> 1;
|
||||
|
||||
/* --- Sign values --- */
|
||||
|
||||
int s = (a > 0) + (b > 0);
|
||||
int s = (a != 0) + (b != 0);
|
||||
nbits += s * 2048;
|
||||
|
||||
/* --- LSB values Reduce to 2*2 bits MSB values ---
|
||||
@@ -322,8 +360,8 @@ LC3_HOT static int compute_nbits(
|
||||
* The LSB mode does not arthmetic code the first LSB,
|
||||
* add the sign of the LSB when one of pair was at value 1 */
|
||||
|
||||
int k = 0;
|
||||
int m = (a | b) >> 2;
|
||||
uint32_t m = (a | b) >> 2;
|
||||
unsigned k = 0;
|
||||
|
||||
if (m) {
|
||||
|
||||
@@ -375,19 +413,15 @@ LC3_HOT static int compute_nbits(
|
||||
* Put quantized spectrum
|
||||
* bits Bitstream context
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* x Spectral quantized
|
||||
* x Spectral quantized coefficients
|
||||
* nq, lsb_mode Count of significants, and LSB discard indication
|
||||
*
|
||||
* The spectral coefficients `x` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
*/
|
||||
LC3_HOT static void put_quantized(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const uint16_t *x, int nq, bool lsb_mode)
|
||||
const float *x, int nq, bool lsb_mode)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
bool high_rate = resolve_high_rate(sr, nbytes);
|
||||
bool high_rate = resolve_modes(sr, nbytes, NULL);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
/* --- Loop on quantized coefficients --- */
|
||||
|
||||
@@ -398,16 +432,19 @@ LC3_HOT static void put_quantized(lc3_bits_t *bits,
|
||||
|
||||
for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
|
||||
|
||||
float xq_off = lc3_hr(sr) ? 0.5f : 6.f/16;
|
||||
uint32_t a = fabsf(x[i+0]) + xq_off;
|
||||
uint32_t b = fabsf(x[i+1]) + xq_off;
|
||||
|
||||
const uint8_t *lut = lut_coeff[state];
|
||||
uint16_t a = x[i] >> 1, b = x[i+1] >> 1;
|
||||
|
||||
/* --- LSB values Reduce to 2*2 bits MSB values ---
|
||||
* Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
|
||||
* coded with an escape code and 1 bits for each values.
|
||||
* The LSB mode discard the first LSB (at this step) */
|
||||
|
||||
int m = (a | b) >> 2;
|
||||
int k = 0, shr = 0;
|
||||
uint32_t m = (a | b) >> 2;
|
||||
unsigned k = 0, shr = 0;
|
||||
|
||||
if (m) {
|
||||
|
||||
@@ -431,8 +468,8 @@ LC3_HOT static void put_quantized(lc3_bits_t *bits,
|
||||
|
||||
/* --- Sign values --- */
|
||||
|
||||
if (a) lc3_put_bit(bits, x[i+0] & 1);
|
||||
if (b) lc3_put_bit(bits, x[i+1] & 1);
|
||||
if (a) lc3_put_bit(bits, x[i+0] < 0);
|
||||
if (b) lc3_put_bit(bits, x[i+1] < 0);
|
||||
|
||||
/* --- MSB values --- */
|
||||
|
||||
@@ -453,18 +490,18 @@ LC3_HOT static void put_quantized(lc3_bits_t *bits,
|
||||
* bits Bitstream context
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* nq, lsb_mode Count of significants, and LSB discard indication
|
||||
* xq Return `nq` spectral quantized coefficients
|
||||
* x Return `nq` spectral quantized coefficients
|
||||
* nf_seed Return the noise factor seed associated
|
||||
* return 0: Ok -1: Invalid bitstream data
|
||||
*/
|
||||
LC3_HOT static int get_quantized(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
int nq, bool lsb_mode, float *xq, uint16_t *nf_seed)
|
||||
int nq, bool lsb_mode, float *x, uint16_t *nf_seed)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
bool high_rate = resolve_high_rate(sr, nbytes);
|
||||
bool high_rate = resolve_modes(sr, nbytes, NULL);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
*nf_seed = 0;
|
||||
*nf_seed = 0;
|
||||
|
||||
/* --- Loop on quantized coefficients --- */
|
||||
|
||||
@@ -476,6 +513,7 @@ LC3_HOT static int get_quantized(lc3_bits_t *bits,
|
||||
for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
|
||||
|
||||
const uint8_t *lut = lut_coeff[state];
|
||||
int max_shl = lc3_hr(sr) ? 22 : 14;
|
||||
|
||||
/* --- LSB values ---
|
||||
* Until the symbol read indicates the escape value 16,
|
||||
@@ -492,7 +530,7 @@ LC3_HOT static int get_quantized(lc3_bits_t *bits,
|
||||
shl++;
|
||||
}
|
||||
|
||||
for ( ; s >= 16 && shl < 14; shl++) {
|
||||
for ( ; s >= 16 && shl < max_shl; shl++) {
|
||||
u |= lc3_get_bit(bits) << shl;
|
||||
v |= lc3_get_bit(bits) << shl;
|
||||
|
||||
@@ -511,10 +549,11 @@ LC3_HOT static int get_quantized(lc3_bits_t *bits,
|
||||
u |= a << shl;
|
||||
v |= b << shl;
|
||||
|
||||
xq[i ] = u && lc3_get_bit(bits) ? -u : u;
|
||||
xq[i+1] = v && lc3_get_bit(bits) ? -v : v;
|
||||
x[i+0] = u && lc3_get_bit(bits) ? -u : u;
|
||||
x[i+1] = v && lc3_get_bit(bits) ? -v : v;
|
||||
|
||||
*nf_seed = (*nf_seed + u * i + v * (i+1)) & 0xffff;
|
||||
*nf_seed = (*nf_seed + (u & 0x7fff) * (i )
|
||||
+ (v & 0x7fff) * (i+1)) & 0xffff;
|
||||
|
||||
/* --- Update state --- */
|
||||
|
||||
@@ -529,25 +568,30 @@ LC3_HOT static int get_quantized(lc3_bits_t *bits,
|
||||
* Put residual bits of quantization
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* hrmode High-Resolution mode
|
||||
* x, n Spectral quantized, and count of significants
|
||||
* xf Scaled spectral coefficients
|
||||
*
|
||||
* The spectral coefficients `x` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
*/
|
||||
LC3_HOT static void put_residual(
|
||||
lc3_bits_t *bits, int nbits, const uint16_t *x, int n, const float *xf)
|
||||
LC3_HOT static void put_residual(lc3_bits_t *bits,
|
||||
int nbits, bool hrmode, float *x, int n)
|
||||
{
|
||||
for (int i = 0; i < n && nbits > 0; i++) {
|
||||
float xq_lim = hrmode ? 0.5f : 10.f/16;
|
||||
float xq_off = xq_lim / 2;
|
||||
|
||||
if (x[i] == 0)
|
||||
continue;
|
||||
for (int iter = 0; iter < (hrmode ? 20 : 1) && nbits > 0; iter++) {
|
||||
for (int i = 0; i < n && nbits > 0; i++) {
|
||||
|
||||
float xq = x[i] & 1 ? -(x[i] >> 1) : (x[i] >> 1);
|
||||
float xr = fabsf(x[i]);
|
||||
if (xr < xq_lim)
|
||||
continue;
|
||||
|
||||
lc3_put_bit(bits, xf[i] >= xq);
|
||||
nbits--;
|
||||
bool b = (xr - truncf(xr) < xq_lim) ^ (x[i] < 0);
|
||||
lc3_put_bit(bits, b);
|
||||
nbits--;
|
||||
|
||||
x[i] += b ? -xq_off : xq_off;
|
||||
}
|
||||
|
||||
xq_off *= xq_lim;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,22 +599,31 @@ LC3_HOT static void put_residual(
|
||||
* Get residual bits of quantization
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* hrmode High-Resolution mode
|
||||
* x, nq Spectral quantized, and count of significants
|
||||
*/
|
||||
LC3_HOT static void get_residual(
|
||||
lc3_bits_t *bits, int nbits, float *x, int nq)
|
||||
LC3_HOT static void get_residual(lc3_bits_t *bits,
|
||||
int nbits, bool hrmode, float *x, int n)
|
||||
{
|
||||
for (int i = 0; i < nq && nbits > 0; i++) {
|
||||
float xq_off_1 = hrmode ? 0.25f : 5.f/16;
|
||||
float xq_off_2 = hrmode ? 0.25f : 3.f/16;
|
||||
|
||||
if (x[i] == 0)
|
||||
continue;
|
||||
for (int iter = 0; iter < (hrmode ? 20 : 1) && nbits > 0; iter++) {
|
||||
for (int i = 0; i < n && nbits > 0; i++) {
|
||||
|
||||
if (lc3_get_bit(bits) == 0)
|
||||
x[i] -= x[i] < 0 ? 5.f/16 : 3.f/16;
|
||||
else
|
||||
x[i] += x[i] > 0 ? 5.f/16 : 3.f/16;
|
||||
if (x[i] == 0)
|
||||
continue;
|
||||
|
||||
nbits--;
|
||||
if (lc3_get_bit(bits) == 0)
|
||||
x[i] -= x[i] < 0 ? xq_off_1 : xq_off_2;
|
||||
else
|
||||
x[i] += x[i] > 0 ? xq_off_1 : xq_off_2;
|
||||
|
||||
nbits--;
|
||||
}
|
||||
|
||||
xq_off_1 *= 0.5f;
|
||||
xq_off_2 *= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,18 +631,17 @@ LC3_HOT static void get_residual(
|
||||
* Put LSB values of quantized spectrum values
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* hrmode High-Resolution mode
|
||||
* x, n Spectral quantized, and count of significants
|
||||
*
|
||||
* The spectral coefficients `x` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
*/
|
||||
LC3_HOT static void put_lsb(
|
||||
lc3_bits_t *bits, int nbits, const uint16_t *x, int n)
|
||||
LC3_HOT static void put_lsb(lc3_bits_t *bits,
|
||||
int nbits, bool hrmode, const float *x, int n)
|
||||
{
|
||||
for (int i = 0; i < n && nbits > 0; i += 2) {
|
||||
uint16_t a = x[i] >> 1, b = x[i+1] >> 1;
|
||||
int a_neg = x[i] & 1, b_neg = x[i+1] & 1;
|
||||
|
||||
float xq_off = hrmode ? 0.5f : 6.f/16;
|
||||
uint32_t a = fabsf(x[i+0]) + xq_off;
|
||||
uint32_t b = fabsf(x[i+1]) + xq_off;
|
||||
|
||||
if ((a | b) >> 2 == 0)
|
||||
continue;
|
||||
@@ -598,13 +650,13 @@ LC3_HOT static void put_lsb(
|
||||
lc3_put_bit(bits, a & 1);
|
||||
|
||||
if (a == 1 && nbits-- > 0)
|
||||
lc3_put_bit(bits, a_neg);
|
||||
lc3_put_bit(bits, x[i+0] < 0);
|
||||
|
||||
if (nbits-- > 0)
|
||||
lc3_put_bit(bits, b & 1);
|
||||
|
||||
if (b == 1 && nbits-- > 0)
|
||||
lc3_put_bit(bits, b_neg);
|
||||
lc3_put_bit(bits, x[i+1] < 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,34 +707,31 @@ LC3_HOT static void get_lsb(lc3_bits_t *bits,
|
||||
/**
|
||||
* Estimate noise level
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* xq, nq Quantized spectral coefficients
|
||||
* x Quantization scaled spectrum coefficients
|
||||
* hrmode High-Resolution mode
|
||||
* x, n Spectral quantized, and count of significants
|
||||
* return Noise factor (0 to 7)
|
||||
*
|
||||
* The spectral coefficients `x` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
*/
|
||||
LC3_HOT static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const uint16_t *xq, int nq, const float *x)
|
||||
LC3_HOT static int estimate_noise(
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw, bool hrmode, const float *x, int n)
|
||||
{
|
||||
int bw_stop = 20 * (1 + dt) * (1 + bw);
|
||||
int bw_stop = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB));
|
||||
int w = 1 + (dt >= LC3_DT_7M5) + (dt>= LC3_DT_10M);
|
||||
|
||||
float xq_lim = hrmode ? 0.5f : 10.f/16;
|
||||
float sum = 0;
|
||||
int i, n = 0, z = 0;
|
||||
int i, ns = 0, z = 0;
|
||||
|
||||
for (i = 6 * (1 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
z = xq[i] ? 0 : z + 1;
|
||||
for (i = 6 * (1 + dt) - w; i < LC3_MIN(n, bw_stop); i++) {
|
||||
z = fabsf(x[i]) < xq_lim ? z + 1 : 0;
|
||||
if (z > 2*w)
|
||||
sum += fabsf(x[i - w]), n++;
|
||||
sum += fabsf(x[i - w]), ns++;
|
||||
}
|
||||
|
||||
for ( ; i < bw_stop + w; i++)
|
||||
if (++z > 2*w)
|
||||
sum += fabsf(x[i - w]), n++;
|
||||
sum += fabsf(x[i - w]), ns++;
|
||||
|
||||
int nf = n ? 8 - (int)((16 * sum) / n + 0.5f) : 8;
|
||||
int nf = ns ? 8 - (int)((16 * sum) / ns + 0.5f) : 8;
|
||||
|
||||
return LC3_CLIP(nf, 0, 7);
|
||||
}
|
||||
@@ -697,7 +746,7 @@ LC3_HOT static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
LC3_HOT static void fill_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
int nf, uint16_t nf_seed, float g, float *x, int nq)
|
||||
{
|
||||
int bw_stop = 20 * (1 + dt) * (1 + bw);
|
||||
int bw_stop = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB));
|
||||
int w = 1 + (dt >= LC3_DT_7M5) + (dt>= LC3_DT_10M);
|
||||
|
||||
float s = g * (float)(8 - nf) / 16;
|
||||
@@ -745,13 +794,13 @@ static int get_noise_factor(lc3_bits_t *bits)
|
||||
|
||||
/**
|
||||
* Bit consumption of the number of coded coefficients
|
||||
* dt, sr Duration, samplerate of the frame
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* return Bit consumpution of the number of coded coefficients
|
||||
*/
|
||||
static int get_nbits_nq(enum lc3_dt dt, enum lc3_srate sr)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
return 4 + (ne > 32) + (ne > 64) + (ne > 128) + (ne > 256);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
return 4 + (ne > 32) + (ne > 64) + (ne > 128) + (ne > 256) + (ne > 512);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -761,16 +810,18 @@ static int get_nbits_nq(enum lc3_dt dt, enum lc3_srate sr)
|
||||
*/
|
||||
static int get_nbits_ac(enum lc3_dt dt, enum lc3_srate sr, int nbytes)
|
||||
{
|
||||
return get_nbits_nq(dt, sr) + 3 + LC3_MIN((nbytes-1) / 160, 2);
|
||||
return get_nbits_nq(dt, sr) +
|
||||
3 + lc3_hr(sr) + LC3_MIN((nbytes-1) / 160, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spectrum analysis
|
||||
*/
|
||||
void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, bool pitch, const lc3_tns_data_t *tns,
|
||||
struct lc3_spec_analysis *spec, float *x,
|
||||
uint16_t *xq, struct lc3_spec_side *side)
|
||||
void lc3_spec_analyze(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
bool pitch, const lc3_tns_data_t *tns,
|
||||
struct lc3_spec_analysis *spec,
|
||||
float *x, struct lc3_spec_side *side)
|
||||
{
|
||||
bool reset_off;
|
||||
|
||||
@@ -792,35 +843,36 @@ void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int g_off = resolve_gain_offset(sr, nbytes);
|
||||
|
||||
int g_min, g_int = estimate_gain(dt, sr,
|
||||
x, nbits_budget, nbits_off, g_off, &reset_off, &g_min);
|
||||
x, nbytes, nbits_budget, nbits_off, g_off, &reset_off, &g_min);
|
||||
|
||||
/* --- Quantization --- */
|
||||
|
||||
quantize(dt, sr, g_int, x, xq, &side->nq);
|
||||
quantize(dt, sr, g_int, x, &side->nq);
|
||||
|
||||
int nbits = compute_nbits(dt, sr, nbytes, xq, &side->nq, 0, NULL);
|
||||
int nbits = compute_nbits(dt, sr, nbytes, x, &side->nq, 0, NULL);
|
||||
|
||||
spec->nbits_off = reset_off ? 0 : nbits_off;
|
||||
spec->nbits_spare = reset_off ? 0 : nbits_budget - nbits;
|
||||
|
||||
/* --- Adjust gain and requantize --- */
|
||||
|
||||
int g_adj = adjust_gain(sr, g_off + g_int,
|
||||
nbits, nbits_budget, g_off + g_min);
|
||||
int g_adj = adjust_gain(dt, sr,
|
||||
g_off + g_int, nbits, nbits_budget, g_off + g_min);
|
||||
|
||||
if (g_adj)
|
||||
quantize(dt, sr, g_adj, x, xq, &side->nq);
|
||||
quantize(dt, sr, g_adj, x, &side->nq);
|
||||
|
||||
side->g_idx = g_int + g_adj + g_off;
|
||||
nbits = compute_nbits(dt, sr, nbytes,
|
||||
xq, &side->nq, nbits_budget, &side->lsb_mode);
|
||||
x, &side->nq, nbits_budget, &side->lsb_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put spectral quantization side data
|
||||
*/
|
||||
void lc3_spec_put_side(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, const struct lc3_spec_side *side)
|
||||
enum lc3_dt dt, enum lc3_srate sr,
|
||||
const struct lc3_spec_side *side)
|
||||
{
|
||||
int nbits_nq = get_nbits_nq(dt, sr);
|
||||
|
||||
@@ -833,22 +885,22 @@ void lc3_spec_put_side(lc3_bits_t *bits,
|
||||
* Encode spectral coefficients
|
||||
*/
|
||||
void lc3_spec_encode(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
|
||||
const uint16_t *xq, const lc3_spec_side_t *side, const float *x)
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
|
||||
int nbytes, const lc3_spec_side_t *side, float *x)
|
||||
{
|
||||
bool lsb_mode = side->lsb_mode;
|
||||
int nq = side->nq;
|
||||
|
||||
put_noise_factor(bits, estimate_noise(dt, bw, xq, nq, x));
|
||||
put_noise_factor(bits, estimate_noise(dt, bw, lc3_hr(sr), x, nq));
|
||||
|
||||
put_quantized(bits, dt, sr, nbytes, xq, nq, lsb_mode);
|
||||
put_quantized(bits, dt, sr, nbytes, x, nq, lsb_mode);
|
||||
|
||||
int nbits_left = lc3_get_bits_left(bits);
|
||||
|
||||
if (lsb_mode)
|
||||
put_lsb(bits, nbits_left, xq, nq);
|
||||
put_lsb(bits, nbits_left, lc3_hr(sr), x, nq);
|
||||
else
|
||||
put_residual(bits, nbits_left, xq, nq, x);
|
||||
put_residual(bits, nbits_left, lc3_hr(sr), x, nq);
|
||||
}
|
||||
|
||||
|
||||
@@ -863,7 +915,7 @@ int lc3_spec_get_side(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, struct lc3_spec_side *side)
|
||||
{
|
||||
int nbits_nq = get_nbits_nq(dt, sr);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
int ne = lc3_ne(dt, sr);
|
||||
|
||||
side->nq = (lc3_get_bits(bits, nbits_nq) + 1) << 1;
|
||||
side->lsb_mode = lc3_get_bit(bits);
|
||||
@@ -895,7 +947,7 @@ int lc3_spec_decode(lc3_bits_t *bits,
|
||||
if (lsb_mode)
|
||||
get_lsb(bits, nbits_left, x, nq, &nf_seed);
|
||||
else
|
||||
get_residual(bits, nbits_left, x, nq);
|
||||
get_residual(bits, nbits_left, lc3_hr(sr), x, nq);
|
||||
|
||||
int g_int = side->g_idx - resolve_gain_offset(sr, nbytes);
|
||||
float g = unquantize(dt, sr, g_int, x, nq);
|
||||
|
||||
29
src/spec.h
29
src/spec.h
@@ -46,15 +46,12 @@ typedef struct lc3_spec_side {
|
||||
* pitch, tns Pitch present indication and TNS bistream data
|
||||
* spec Context of analysis
|
||||
* x Spectral coefficients, scaled as output
|
||||
* xq, side Return quantization data
|
||||
*
|
||||
* The spectral coefficients `xq` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
* side Return quantization data
|
||||
*/
|
||||
void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, bool pitch, const lc3_tns_data_t *tns,
|
||||
lc3_spec_analysis_t *spec, float *x, uint16_t *xq, lc3_spec_side_t *side);
|
||||
void lc3_spec_analyze(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
bool pitch, const lc3_tns_data_t *tns, lc3_spec_analysis_t *spec,
|
||||
float *x, lc3_spec_side_t *side);
|
||||
|
||||
/**
|
||||
* Put spectral quantization side data
|
||||
@@ -70,16 +67,11 @@ void lc3_spec_put_side(lc3_bits_t *bits,
|
||||
* bits Bitstream context
|
||||
* dt, sr, bw Duration, samplerate, bandwidth
|
||||
* nbytes and size of the frame
|
||||
* xq, side Quantization data
|
||||
* x Scaled spectral coefficients
|
||||
*
|
||||
* The spectral coefficients `xq` storage is :
|
||||
* b0 0:positive or zero 1:negative
|
||||
* b15..b1 Absolute value
|
||||
* side, x Quantization data, and scaled coefficients
|
||||
*/
|
||||
void lc3_spec_encode(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
|
||||
const uint16_t *xq, const lc3_spec_side_t *side, const float *x);
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
|
||||
int nbytes, const lc3_spec_side_t *side, float *x);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@@ -105,8 +97,9 @@ int lc3_spec_get_side(lc3_bits_t *bits,
|
||||
* x Spectral coefficients
|
||||
* return 0: Ok -1: Invalid bitstream data
|
||||
*/
|
||||
int lc3_spec_decode(lc3_bits_t *bits, enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_bandwidth bw, int nbytes, const lc3_spec_side_t *side, float *x);
|
||||
int lc3_spec_decode(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
|
||||
int nbytes, const lc3_spec_side_t *side, float *x);
|
||||
|
||||
|
||||
#endif /* __LC3_SPEC_H */
|
||||
|
||||
1888
src/tables.c
1888
src/tables.c
File diff suppressed because it is too large
Load Diff
68
src/tables.h
68
src/tables.h
@@ -23,6 +23,72 @@
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
/**
|
||||
* Characteristics
|
||||
*
|
||||
* ns Number of temporal samples / frequency coefficients within a frame
|
||||
*
|
||||
* ne Number of encoded frequency coefficients
|
||||
*
|
||||
* nd Number of MDCT delayed samples, sum of half a frame and an ovelap
|
||||
* of future by 1.25 ms (2.5ms, 5ms and 10ms frame durations),
|
||||
* or 2 ms (7.5ms frame duration).
|
||||
*
|
||||
* nh Number of 18 ms samples of the history buffer, aligned on a frame
|
||||
*
|
||||
* nt Number of 1.25 ms previous samples
|
||||
*/
|
||||
|
||||
extern const int lc3_ns_2m5[LC3_NUM_SRATE];
|
||||
extern const int lc3_ne_2m5[LC3_NUM_SRATE];
|
||||
extern const int lc3_ns_4m [LC3_NUM_SRATE];
|
||||
|
||||
static inline int lc3_ns(enum lc3_dt dt, enum lc3_srate sr) {
|
||||
return lc3_ns_2m5[sr] * (1 + dt);
|
||||
}
|
||||
|
||||
static inline int lc3_ne(enum lc3_dt dt, enum lc3_srate sr) {
|
||||
return lc3_ne_2m5[sr] * (1 + dt);
|
||||
}
|
||||
|
||||
static inline int lc3_nd(enum lc3_dt dt, enum lc3_srate sr) {
|
||||
return ( lc3_ns(dt, sr) +
|
||||
(dt == LC3_DT_7M5 ? lc3_ns_4m[sr] : lc3_ns_2m5[sr]) ) >> 1;
|
||||
}
|
||||
|
||||
static inline int lc3_nh(enum lc3_dt dt, enum lc3_srate sr) {
|
||||
return sr > LC3_SRATE_48K_HR ? 0 :
|
||||
(8 + (dt == LC3_DT_7M5)) * lc3_ns_2m5[sr];
|
||||
}
|
||||
|
||||
static inline int lc3_nt(enum lc3_srate sr) {
|
||||
return lc3_ns_2m5[sr] >> 1;
|
||||
}
|
||||
|
||||
#define LC3_MAX_SRATE_HZ ( LC3_PLUS_HR ? 96000 : 48000 )
|
||||
|
||||
#define LC3_MAX_NS ( LC3_NS(10000, LC3_MAX_SRATE_HZ) )
|
||||
#define LC3_MAX_NE ( LC3_PLUS_HR ? LC3_MAX_NS : LC3_NS(10000, 40000) )
|
||||
|
||||
|
||||
/**
|
||||
* Limits on size of frame
|
||||
*/
|
||||
|
||||
extern const int lc3_frame_bytes_hr_lim
|
||||
[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_48K_HR][2];
|
||||
|
||||
static inline int lc3_min_frame_bytes(enum lc3_dt dt, enum lc3_srate sr) {
|
||||
return !lc3_hr(sr) ? LC3_MIN_FRAME_BYTES :
|
||||
lc3_frame_bytes_hr_lim[dt][sr - LC3_SRATE_48K_HR][0];
|
||||
}
|
||||
|
||||
static inline int lc3_max_frame_bytes(enum lc3_dt dt, enum lc3_srate sr) {
|
||||
return !lc3_hr(sr) ? LC3_MAX_FRAME_BYTES :
|
||||
lc3_frame_bytes_hr_lim[dt][sr - LC3_SRATE_48K_HR][1];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MDCT Twiddles and window coefficients
|
||||
*/
|
||||
@@ -45,7 +111,7 @@ extern const float *lc3_mdct_win[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
#define LC3_MAX_BANDS 64
|
||||
|
||||
extern const int lc3_num_bands[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
extern const uint16_t *lc3_band_lim[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
extern const int *lc3_band_lim[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
|
||||
|
||||
/**
|
||||
|
||||
40
src/tns.c
40
src/tns.c
@@ -61,7 +61,7 @@ LC3_HOT static void compute_lpc_coeffs(
|
||||
const float *x, float *gain, float (*a)[9])
|
||||
{
|
||||
|
||||
#if !LC3_NPLUS
|
||||
#if LC3_PLUS
|
||||
|
||||
static const int sub_2m5_nb[] = { 3, 10, 20 };
|
||||
static const int sub_2m5_wb[] = { 3, 20, 40 };
|
||||
@@ -75,7 +75,7 @@ LC3_HOT static void compute_lpc_coeffs(
|
||||
static const int sub_5m_swb[] = { 6, 43, 80, 120, 160 };
|
||||
static const int sub_5m_fb[] = { 6, 53, 100, 150, 200 };
|
||||
|
||||
#endif /* !LC3_NPLUS */
|
||||
#endif /* LC3_PLUS */
|
||||
|
||||
static const int sub_7m5_nb[] = { 9, 26, 43, 60 };
|
||||
static const int sub_7m5_wb[] = { 9, 46, 83, 120 };
|
||||
@@ -89,8 +89,6 @@ LC3_HOT static void compute_lpc_coeffs(
|
||||
static const int sub_10m_swb[] = { 12, 61, 110, 160, 213, 266, 320 };
|
||||
static const int sub_10m_fb[] = { 12, 74, 137, 200, 266, 333, 400 };
|
||||
|
||||
/* --- Normalized autocorrelation --- */
|
||||
|
||||
static const float lag_window[] = {
|
||||
1.00000000e+00, 9.98028026e-01, 9.92135406e-01, 9.82391584e-01,
|
||||
9.68910791e-01, 9.51849807e-01, 9.31404933e-01, 9.07808230e-01,
|
||||
@@ -99,22 +97,30 @@ LC3_HOT static void compute_lpc_coeffs(
|
||||
|
||||
const int *sub = (const int * const [LC3_NUM_DT][LC3_NUM_BANDWIDTH]){
|
||||
|
||||
#if !LC3_NPLUS
|
||||
#if LC3_PLUS
|
||||
|
||||
[LC3_DT_2M5] = { sub_2m5_nb, sub_2m5_wb,
|
||||
sub_2m5_sswb, sub_2m5_swb, sub_2m5_fb },
|
||||
[LC3_DT_5M ] = { sub_5m_nb , sub_5m_wb ,
|
||||
sub_5m_sswb , sub_5m_swb , sub_5m_fb },
|
||||
[LC3_DT_2M5] = {
|
||||
sub_2m5_nb, sub_2m5_wb, sub_2m5_sswb, sub_2m5_swb,
|
||||
sub_2m5_fb, sub_2m5_fb, sub_2m5_fb },
|
||||
|
||||
#endif /* !LC3_NPLUS */
|
||||
[LC3_DT_5M] = {
|
||||
sub_5m_nb , sub_5m_wb , sub_5m_sswb , sub_5m_swb ,
|
||||
sub_5m_fb , sub_5m_fb , sub_5m_fb },
|
||||
|
||||
[LC3_DT_7M5] = { sub_7m5_nb, sub_7m5_wb,
|
||||
sub_7m5_sswb, sub_7m5_swb, sub_7m5_fb },
|
||||
[LC3_DT_10M] = { sub_10m_nb, sub_10m_wb,
|
||||
sub_10m_sswb, sub_10m_swb, sub_10m_fb },
|
||||
#endif /* LC3_PLUS */
|
||||
|
||||
[LC3_DT_7M5] = {
|
||||
sub_7m5_nb, sub_7m5_wb, sub_7m5_sswb, sub_7m5_swb,
|
||||
sub_7m5_fb },
|
||||
|
||||
[LC3_DT_10M] = {
|
||||
sub_10m_nb, sub_10m_wb, sub_10m_sswb, sub_10m_swb,
|
||||
sub_10m_fb, sub_10m_fb, sub_10m_fb },
|
||||
|
||||
}[dt][bw];
|
||||
|
||||
/* --- Normalized autocorrelation --- */
|
||||
|
||||
int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int nsubdivisions = 2 + (dt >= LC3_DT_7M5);
|
||||
|
||||
@@ -296,7 +302,8 @@ LC3_HOT static void forward_filtering(
|
||||
const int rc_order[2], float (* const rc)[8], float *x)
|
||||
{
|
||||
int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
|
||||
int nf = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB))
|
||||
>> (nfilters - 1);
|
||||
int i0, ie = 3*(1 + dt);
|
||||
|
||||
float s[8] = { 0 };
|
||||
@@ -337,7 +344,8 @@ LC3_HOT static void inverse_filtering(
|
||||
const int rc_order[2], float (* const rc)[8], float *x)
|
||||
{
|
||||
int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
|
||||
int nf = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB))
|
||||
>> (nfilters - 1);
|
||||
int i0, ie = 3*(1 + dt);
|
||||
|
||||
float s[8] = { 0 };
|
||||
|
||||
Reference in New Issue
Block a user