mirror of
https://github.com/google/liblc3.git
synced 2026-04-29 18:24:49 +00:00
feature: Add 2.5 ms and 5 ms LC3 plus frame durations
fix: Check TNS bitstream data fix: LTPF Activation with 2.5 ms frame sizes
This commit is contained in:
committed by
Antoine Soulier
parent
a75f187e00
commit
149cb6537e
12
src/attdet.c
12
src/attdet.c
@@ -27,14 +27,14 @@ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr,
|
||||
{
|
||||
/* --- Check enabling --- */
|
||||
|
||||
const int nbytes_ranges[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_32K][2] = {
|
||||
[LC3_DT_7M5] = { { 61, 149 }, { 75, 149 } },
|
||||
[LC3_DT_10M] = { { 81, INT_MAX }, { 100, INT_MAX } },
|
||||
const int nbytes_ranges[][LC3_NUM_SRATE - LC3_SRATE_32K][2] = {
|
||||
[LC3_DT_7M5 - LC3_DT_7M5] = { { 61, 149 }, { 75, 149 } },
|
||||
[LC3_DT_10M - LC3_DT_7M5] = { { 81, INT_MAX }, { 100, INT_MAX } },
|
||||
};
|
||||
|
||||
if (sr < LC3_SRATE_32K ||
|
||||
nbytes < nbytes_ranges[dt][sr - LC3_SRATE_32K][0] ||
|
||||
nbytes > nbytes_ranges[dt][sr - LC3_SRATE_32K][1] )
|
||||
if (dt < LC3_DT_7M5 || sr < LC3_SRATE_32K ||
|
||||
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;
|
||||
|
||||
/* --- Filtering & Energy calculation --- */
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Time domain attack detector
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_ATTDET_H
|
||||
#define __LC3_ATTDET_H
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Bitstream management
|
||||
*
|
||||
* The bitstream is written by the 2 ends of the buffer :
|
||||
*
|
||||
* - Arthmetic coder put bits while increasing memory addresses
|
||||
@@ -56,10 +54,6 @@
|
||||
* - The procedure `lc3_check_bits()` returns indication that read has been
|
||||
* made crossing the other bit plane.
|
||||
*
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LC3_BITS_H
|
||||
|
||||
55
src/bwdet.c
55
src/bwdet.c
@@ -25,29 +25,54 @@
|
||||
enum lc3_bandwidth lc3_bwdet_run(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *e)
|
||||
{
|
||||
/* Bandwidth regions (Table 3.6) */
|
||||
/* Bandwidth regions */
|
||||
|
||||
struct region { int is : 8; int ie : 8; };
|
||||
|
||||
static const struct region bws_table[LC3_NUM_DT]
|
||||
[LC3_NUM_BANDWIDTH-1][LC3_NUM_BANDWIDTH-1] = {
|
||||
#if !LC3_NPLUS
|
||||
|
||||
[LC3_DT_7M5] = {
|
||||
{ { 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_2m5[][LC3_NUM_BANDWIDTH-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 } },
|
||||
};
|
||||
|
||||
[LC3_DT_10M] = {
|
||||
{ { 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_5m[][LC3_NUM_BANDWIDTH-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 */
|
||||
|
||||
static const struct region bws_table_7m5[][LC3_NUM_BANDWIDTH-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] = {
|
||||
{ { 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 */
|
||||
[LC3_DT_7M5] = bws_table_7m5,
|
||||
[LC3_DT_10M] = bws_table_10m,
|
||||
};
|
||||
|
||||
static const int l_table[LC3_NUM_DT][LC3_NUM_BANDWIDTH-1] = {
|
||||
[LC3_DT_2M5] = { 4, 4, 3, 1 },
|
||||
[LC3_DT_5M ] = { 4, 4, 3, 1 },
|
||||
[LC3_DT_7M5] = { 4, 4, 3, 2 },
|
||||
[LC3_DT_10M] = { 4, 4, 3, 1 },
|
||||
};
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Bandwidth detector
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_BWDET_H
|
||||
#define __LC3_BWDET_H
|
||||
|
||||
@@ -31,7 +24,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Bandwidth detector (cf. 3.3.5)
|
||||
* Bandwidth detector
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* e Energy estimation per bands
|
||||
* return Return detected bandwitdth
|
||||
|
||||
29
src/common.h
29
src/common.h
@@ -16,10 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Common constants and types
|
||||
*/
|
||||
|
||||
#ifndef __LC3_COMMON_H
|
||||
#define __LC3_COMMON_H
|
||||
|
||||
@@ -87,7 +83,7 @@
|
||||
*/
|
||||
|
||||
#define LC3_DT_US(dt) \
|
||||
( (3 + (dt)) * 2500 )
|
||||
( (1 + (dt)) * 2500 )
|
||||
|
||||
#define LC3_SRATE_KHZ(sr) \
|
||||
( (1 + (sr) + ((sr) == LC3_SRATE_48K)) * 8 )
|
||||
@@ -96,19 +92,20 @@
|
||||
/**
|
||||
* Return number of samples, delayed samples and
|
||||
* encoded spectrum coefficients within a frame
|
||||
* - For encoding, keep 1.25 ms for temporal window
|
||||
*
|
||||
* - 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 * (3 + (dt)) * (1 + (sr) + ((sr) == LC3_SRATE_48K)) )
|
||||
|
||||
#define LC3_ND(dt, sr) \
|
||||
( (dt) == LC3_DT_7M5 ? 23 * LC3_NS(dt, sr) / 30 \
|
||||
: 5 * LC3_NS(dt, sr) / 8 )
|
||||
( 20 * (1 + (dt)) * (1 + (sr) + ((sr) == LC3_SRATE_48K)) )
|
||||
|
||||
#define LC3_NE(dt, sr) \
|
||||
( 20 * (3 + (dt)) * (1 + (sr)) )
|
||||
( 20 * (1 + (dt)) * (1 + (sr)) )
|
||||
|
||||
#define LC3_MAX_NS \
|
||||
LC3_NS(LC3_DT_10M, LC3_SRATE_48K)
|
||||
@@ -116,11 +113,17 @@
|
||||
#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) \
|
||||
( ((3 - dt) + 1) * LC3_NS(dt, sr) )
|
||||
( ((dt == LC3_DT_2M5 ? 8 : \
|
||||
dt == LC3_DT_5M ? 4 : \
|
||||
dt == LC3_DT_7M5 ? 3 : 2) + 1) * LC3_NS(dt, sr) )
|
||||
|
||||
|
||||
/**
|
||||
|
||||
30
src/energy.c
30
src/energy.c
@@ -26,30 +26,17 @@
|
||||
bool lc3_energy_compute(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *e)
|
||||
{
|
||||
static const int n1_table[LC3_NUM_DT][LC3_NUM_SRATE] = {
|
||||
[LC3_DT_7M5] = { 56, 34, 27, 24, 22 },
|
||||
[LC3_DT_10M] = { 49, 28, 23, 20, 18 },
|
||||
};
|
||||
/* Mean the square of coefficients within each band */
|
||||
|
||||
/* First bands are 1 coefficient width */
|
||||
int nb = lc3_num_bands[dt][sr];
|
||||
const uint16_t *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
int n1 = n1_table[dt][sr];
|
||||
float e_sum[2] = { 0, 0 };
|
||||
int iband;
|
||||
int iband_h = nb - (const int []){
|
||||
[LC3_DT_2M5] = 2, [LC3_DT_5M ] = 3,
|
||||
[LC3_DT_7M5] = 4, [LC3_DT_10M] = 2 }[dt];
|
||||
|
||||
for (iband = 0; iband < n1; iband++) {
|
||||
*e = x[iband] * x[iband];
|
||||
e_sum[0] += *(e++);
|
||||
}
|
||||
|
||||
/* Mean the square of coefficients within each band,
|
||||
* note that 7.5ms 8KHz frame has more bands than samples */
|
||||
|
||||
int nb = LC3_MIN(LC3_NUM_BANDS, LC3_NS(dt, sr));
|
||||
int iband_h = nb - 2*(2 - dt);
|
||||
const int *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
for (int i = lim[iband]; iband < nb; iband++) {
|
||||
for (int iband = 0, i = lim[iband]; iband < nb; iband++) {
|
||||
int ie = lim[iband+1];
|
||||
int n = ie - i;
|
||||
|
||||
@@ -61,9 +48,6 @@ bool lc3_energy_compute(
|
||||
e_sum[iband >= iband_h] += *(e++);
|
||||
}
|
||||
|
||||
for (; iband < LC3_NUM_BANDS; iband++)
|
||||
*(e++) = 0;
|
||||
|
||||
/* Return the near nyquist flag */
|
||||
|
||||
return e_sum[1] > 30 * e_sum[0];
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Energy estimation per band
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_ENERGY_H
|
||||
#define __LC3_ENERGY_H
|
||||
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Mathematics function approximation
|
||||
*/
|
||||
|
||||
#ifndef __LC3_FASTMATH_H
|
||||
#define __LC3_FASTMATH_H
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@ struct side_data {
|
||||
*/
|
||||
static enum lc3_dt resolve_dt(int us)
|
||||
{
|
||||
return us == 7500 ? LC3_DT_7M5 :
|
||||
return us == 2500 ? LC3_DT_2M5 :
|
||||
us == 5000 ? LC3_DT_5M :
|
||||
us == 7500 ? LC3_DT_7M5 :
|
||||
us == 10000 ? LC3_DT_10M : LC3_NUM_DT;
|
||||
}
|
||||
|
||||
@@ -269,7 +271,7 @@ static void analyze(struct lc3_encoder *encoder,
|
||||
|
||||
/* --- Spectral --- */
|
||||
|
||||
float e[LC3_NUM_BANDS];
|
||||
float e[LC3_MAX_BANDS];
|
||||
|
||||
lc3_mdct_forward(dt, sr_pcm, sr, xs, xd, xf);
|
||||
|
||||
@@ -534,7 +536,8 @@ static int decode(struct lc3_decoder *decoder,
|
||||
if ((ret = lc3_spec_get_side(&bits, dt, sr, &side->spec)) < 0)
|
||||
return ret;
|
||||
|
||||
lc3_tns_get_data(&bits, dt, side->bw, nbytes, &side->tns);
|
||||
if ((ret = lc3_tns_get_data(&bits, dt, side->bw, nbytes, &side->tns)) < 0)
|
||||
return ret;
|
||||
|
||||
side->pitch_present = lc3_get_bit(&bits);
|
||||
|
||||
|
||||
51
src/ltpf.c
51
src/ltpf.c
@@ -457,7 +457,7 @@ LC3_HOT static int argmax_weighted(
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate from pitch detected value (3.3.9.8)
|
||||
* Interpolate from pitch detected value
|
||||
* x, n [-2..-1] Previous, [0..n] Current input
|
||||
* d The phase of interpolation (0 to 3)
|
||||
* return The interpolated vector
|
||||
@@ -492,7 +492,7 @@ LC3_HOT static void interpolate(const int16_t *x, int n, int d, int16_t *y)
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate autocorrelation (3.3.9.7)
|
||||
* Interpolate autocorrelation
|
||||
* x [-4..-1] Previous, [0..4] Current input
|
||||
* d The phase of interpolation (-3 to 3)
|
||||
* return The interpolated value
|
||||
@@ -522,7 +522,7 @@ LC3_HOT static float interpolate_corr(const float *x, int d)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pitch detection algorithm (3.3.9.5-6)
|
||||
* Pitch detection algorithm
|
||||
* ltpf Context of analysis
|
||||
* x, n [-114..-17] Previous, [0..n-1] Current 6.4KHz samples
|
||||
* tc Return the pitch-lag estimation
|
||||
@@ -530,8 +530,8 @@ LC3_HOT static float interpolate_corr(const float *x, int d)
|
||||
*
|
||||
* The `x` vector is aligned on 32 bits
|
||||
*/
|
||||
static bool detect_pitch(
|
||||
struct lc3_ltpf_analysis *ltpf, const int16_t *x, int n, int *tc)
|
||||
static bool detect_pitch(struct lc3_ltpf_analysis *ltpf,
|
||||
const int16_t *x, int n, int *tc)
|
||||
{
|
||||
float rm1, rm2;
|
||||
float r[98];
|
||||
@@ -562,7 +562,7 @@ static bool detect_pitch(
|
||||
}
|
||||
|
||||
/**
|
||||
* Pitch-lag parameter (3.3.9.7)
|
||||
* Pitch-lag parameter
|
||||
* x, n [-232..-28] Previous, [0..n-1] Current 12.8KHz samples, Q14
|
||||
* tc Pitch-lag estimation
|
||||
* pitch The pitch value, in fixed .4
|
||||
@@ -615,7 +615,7 @@ bool lc3_ltpf_analyse(
|
||||
/* --- Resampling to 12.8 KHz --- */
|
||||
|
||||
int z_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8);
|
||||
int n_12k8 = dt == LC3_DT_7M5 ? 96 : 128;
|
||||
int n_12k8 = (1 + dt) * 32;
|
||||
|
||||
memmove(ltpf->x_12k8, ltpf->x_12k8 + n_12k8,
|
||||
(z_12k8 - n_12k8) * sizeof(*ltpf->x_12k8));
|
||||
@@ -624,7 +624,7 @@ bool lc3_ltpf_analyse(
|
||||
|
||||
resample_12k8[sr](<pf->hp50, x, x_12k8, n_12k8);
|
||||
|
||||
x_12k8 -= (dt == LC3_DT_7M5 ? 44 : 24);
|
||||
x_12k8 -= (dt == LC3_DT_7M5 ? 44 : 24);
|
||||
|
||||
/* --- Resampling to 6.4 KHz --- */
|
||||
|
||||
@@ -638,6 +638,13 @@ bool lc3_ltpf_analyse(
|
||||
|
||||
resample_6k4(x_12k8, x_6k4, n_6k4);
|
||||
|
||||
/* --- Enlarge for small frame size --- */
|
||||
|
||||
if (dt == LC3_DT_2M5) {
|
||||
x_12k8 -= n_12k8, x_6k4 -= n_6k4;
|
||||
n_12k8 += n_12k8; n_6k4 += n_6k4;
|
||||
}
|
||||
|
||||
/* --- Pitch detection --- */
|
||||
|
||||
int tc, pitch = 0;
|
||||
@@ -817,6 +824,11 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
pitch = (pitch * LC3_SRATE_KHZ(sr) * 10 + 64) / 128;
|
||||
|
||||
int nbits = (nbytes*8 * 10000 + (dt_us/2)) / dt_us;
|
||||
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);
|
||||
bool active = data && data->active && g_idx < 4;
|
||||
|
||||
@@ -832,30 +844,31 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
/* --- Transition handling --- */
|
||||
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int nt = ns / (3 + dt);
|
||||
float x0[MAX_FILTER_WIDTH];
|
||||
int nt = ns / (1 + dt);
|
||||
float x0[2][MAX_FILTER_WIDTH];
|
||||
|
||||
memcpy(x0[0], ltpf->x, (w-1) * sizeof(float));
|
||||
memcpy(ltpf->x, x + ns - (w-1), (w-1) * sizeof(float));
|
||||
|
||||
if (active)
|
||||
memcpy(x0, x + nt-(w-1), (w-1) * sizeof(float));
|
||||
memcpy(x0[1], x + nt-(w-1), (w-1) * sizeof(float));
|
||||
|
||||
if (!ltpf->active && active)
|
||||
synthesize[sr](xh, nh, pitch/4, ltpf->x, x, nt, c, 1);
|
||||
synthesize[sr](xh, nh, pitch/4, x0[0], x, nt, c, 1);
|
||||
else if (ltpf->active && !active)
|
||||
synthesize[sr](xh, nh, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
|
||||
synthesize[sr](xh, nh, ltpf->pitch/4, x0[0], x, nt, ltpf->c, -1);
|
||||
else if (ltpf->active && active && ltpf->pitch == pitch)
|
||||
synthesize[sr](xh, nh, pitch/4, ltpf->x, x, nt, c, 0);
|
||||
synthesize[sr](xh, nh, pitch/4, x0[0], x, nt, c, 0);
|
||||
else if (ltpf->active && active) {
|
||||
synthesize[sr](xh, nh, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
|
||||
synthesize[sr](xh, nh, ltpf->pitch/4, x0[0], x, nt, ltpf->c, -1);
|
||||
synthesize[sr](xh, nh, pitch/4,
|
||||
(x <= xh ? x + nh : x) - (w-1), x, nt, c, 1);
|
||||
}
|
||||
|
||||
/* --- Remainder --- */
|
||||
|
||||
memcpy(ltpf->x, x + ns - (w-1), (w-1) * sizeof(float));
|
||||
|
||||
if (active)
|
||||
synthesize[sr](xh, nh, pitch/4, x0, x + nt, ns-nt, c, 0);
|
||||
if (active && ns > nt)
|
||||
synthesize[sr](xh, nh, pitch/4, x0[1], x + nt, ns-nt, c, 0);
|
||||
|
||||
/* --- Update state --- */
|
||||
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Long Term Postfilter
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_LTPF_H
|
||||
#define __LC3_LTPF_H
|
||||
|
||||
|
||||
@@ -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 = 40, 80, 160 n3 = 0, n2 = [3..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 n3 = 1, n2 = [1..4]
|
||||
* 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. */
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Compute LD-MDCT (Low Delay Modified Discret Cosinus Transform)
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_MDCT_H
|
||||
#define __LC3_MDCT_H
|
||||
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Packet Loss Concealment
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_PLC_H
|
||||
#define __LC3_PLC_H
|
||||
|
||||
|
||||
47
src/sns.c
47
src/sns.c
@@ -157,7 +157,7 @@ LC3_HOT static void compute_scale_factors(
|
||||
/* Pre-emphasis gain table :
|
||||
* Ge[b] = 10 ^ (b * g_tilt) / 630 , b = [0..63] */
|
||||
|
||||
static const float ge_table[LC3_NUM_SRATE][LC3_NUM_BANDS] = {
|
||||
static const float ge_table[LC3_NUM_SRATE][LC3_MAX_BANDS] = {
|
||||
|
||||
[LC3_SRATE_8K] = { /* g_tilt = 14 */
|
||||
1.00000000e+00, 1.05250029e+00, 1.10775685e+00, 1.16591440e+00,
|
||||
@@ -250,17 +250,22 @@ LC3_HOT static void compute_scale_factors(
|
||||
7.19685673e+02, 8.03085722e+02, 8.96150502e+02, 1.00000000e+03 },
|
||||
};
|
||||
|
||||
float e[LC3_NUM_BANDS];
|
||||
float e[LC3_MAX_BANDS];
|
||||
|
||||
/* --- Copy and padding --- */
|
||||
|
||||
int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
|
||||
int n2 = LC3_NUM_BANDS - nb;
|
||||
int nb = lc3_num_bands[dt][sr];
|
||||
int n4 = nb < 32 ? 32 % nb : 0;
|
||||
int n2 = nb < 32 ? nb - n4 : LC3_MAX_BANDS - nb;
|
||||
|
||||
for (int i2 = 0; i2 < n2; i2++)
|
||||
e[2*i2 + 0] = e[2*i2 + 1] = eb[i2];
|
||||
for (int i4 = 0; i4 < n4; i4++)
|
||||
e[4*i4 + 0] = e[4*i4 + 1] =
|
||||
e[4*i4 + 2] = e[4*i4 + 3] = eb[i4];
|
||||
|
||||
memcpy(e + 2*n2, eb + n2, (nb - n2) * sizeof(float));
|
||||
for (int i2 = n4; i2 < n4+n2; i2++)
|
||||
e[2*(n4+i2) + 0] = e[2*(n4+i2) + 1] = eb[i2];
|
||||
|
||||
memcpy(e + 4*n4 + 2*n2, eb + n4 + n2, (nb - n4 - n2) * sizeof(float));
|
||||
|
||||
/* --- Smoothing, pre-emphasis and logarithm --- */
|
||||
|
||||
@@ -269,7 +274,7 @@ LC3_HOT static void compute_scale_factors(
|
||||
float e0 = e[0], e1 = e[0], e2;
|
||||
float e_sum = 0;
|
||||
|
||||
for (int i = 0; i < LC3_NUM_BANDS-1; ) {
|
||||
for (int i = 0; i < LC3_MAX_BANDS-1; ) {
|
||||
e[i] = (e0 * 0.25f + e1 * 0.5f + (e2 = e[i+1]) * 0.25f) * ge[i];
|
||||
e_sum += e[i++];
|
||||
|
||||
@@ -280,12 +285,12 @@ LC3_HOT static void compute_scale_factors(
|
||||
e_sum += e[i++];
|
||||
}
|
||||
|
||||
e[LC3_NUM_BANDS-1] = (e0 * 0.25f + e1 * 0.75f) * ge[LC3_NUM_BANDS-1];
|
||||
e_sum += e[LC3_NUM_BANDS-1];
|
||||
e[LC3_MAX_BANDS-1] = (e0 * 0.25f + e1 * 0.75f) * ge[LC3_MAX_BANDS-1];
|
||||
e_sum += e[LC3_MAX_BANDS-1];
|
||||
|
||||
float noise_floor = fmaxf(e_sum * (1e-4f / 64), 0x1p-32f);
|
||||
|
||||
for (int i = 0; i < LC3_NUM_BANDS; i++)
|
||||
for (int i = 0; i < LC3_MAX_BANDS; i++)
|
||||
e[i] = fast_log2f(fmaxf(e[i], noise_floor)) * 0.5f;
|
||||
|
||||
/* --- Grouping & scaling --- */
|
||||
@@ -680,7 +685,7 @@ LC3_HOT static void spectral_shaping(enum lc3_dt dt, enum lc3_srate sr,
|
||||
{
|
||||
/* --- Interpolate scale factors --- */
|
||||
|
||||
float scf[LC3_NUM_BANDS];
|
||||
float scf[LC3_MAX_BANDS];
|
||||
float s0, s1 = inv ? -scf_q[0] : scf_q[0];
|
||||
|
||||
scf[0] = scf[1] = s1;
|
||||
@@ -694,18 +699,22 @@ LC3_HOT static void spectral_shaping(enum lc3_dt dt, enum lc3_srate sr,
|
||||
scf[62] = s1 + 0.125f * (s1 - s0);
|
||||
scf[63] = s1 + 0.375f * (s1 - s0);
|
||||
|
||||
int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
|
||||
int n2 = LC3_NUM_BANDS - nb;
|
||||
int nb = lc3_num_bands[dt][sr];
|
||||
int n4 = nb < 32 ? 32 % nb : 0;
|
||||
int n2 = nb < 32 ? nb - n4 : LC3_MAX_BANDS - nb;
|
||||
|
||||
for (int i2 = 0; i2 < n2; i2++)
|
||||
scf[i2] = 0.5f * (scf[2*i2] + scf[2*i2+1]);
|
||||
for (int i4 = 0; i4 < n4; i4++)
|
||||
scf[i4] = 0.25f * (scf[4*i4+0] + scf[4*i4+1] +
|
||||
scf[4*i4+2] + scf[4*i4+3]);
|
||||
|
||||
if (n2 > 0)
|
||||
memmove(scf + n2, scf + 2*n2, (nb - n2) * sizeof(float));
|
||||
for (int i2 = n4; i2 < n4+n2; i2++)
|
||||
scf[i2] = 0.5f * (scf[2*(n4+i2)] + scf[2*(n4+i2)+1]);
|
||||
|
||||
memmove(scf + n4 + n2, scf + 4*n4 + 2*n2, (nb - n4 - n2) * sizeof(float));
|
||||
|
||||
/* --- Spectral shaping --- */
|
||||
|
||||
const int *lim = lc3_band_lim[dt][sr];
|
||||
const uint16_t *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
for (int i = 0, ib = 0; ib < nb; ib++) {
|
||||
float g_sns = fast_exp2f(-scf[ib]);
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Spectral Noise Shaping
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_SNS_H
|
||||
#define __LC3_SNS_H
|
||||
|
||||
|
||||
14
src/spec.c
14
src/spec.c
@@ -666,13 +666,13 @@ LC3_HOT static void get_lsb(lc3_bits_t *bits,
|
||||
LC3_HOT static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const uint16_t *xq, int nq, const float *x)
|
||||
{
|
||||
int bw_stop = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw);
|
||||
int w = 2 + dt;
|
||||
int bw_stop = 20 * (1 + dt) * (1 + bw);
|
||||
int w = 1 + (dt >= LC3_DT_7M5) + (dt>= LC3_DT_10M);
|
||||
|
||||
float sum = 0;
|
||||
int i, n = 0, z = 0;
|
||||
|
||||
for (i = 6*(3 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
for (i = 6 * (1 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
z = xq[i] ? 0 : z + 1;
|
||||
if (z > 2*w)
|
||||
sum += fabsf(x[i - w]), n++;
|
||||
@@ -682,7 +682,7 @@ LC3_HOT static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
if (++z > 2*w)
|
||||
sum += fabsf(x[i - w]), n++;
|
||||
|
||||
int nf = n ? 8 - (int)((16 * sum) / n + 0.5f) : 0;
|
||||
int nf = n ? 8 - (int)((16 * sum) / n + 0.5f) : 8;
|
||||
|
||||
return LC3_CLIP(nf, 0, 7);
|
||||
}
|
||||
@@ -697,13 +697,13 @@ 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 = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw);
|
||||
int w = 2 + dt;
|
||||
int bw_stop = 20 * (1 + dt) * (1 + bw);
|
||||
int w = 1 + (dt >= LC3_DT_7M5) + (dt>= LC3_DT_10M);
|
||||
|
||||
float s = g * (float)(8 - nf) / 16;
|
||||
int i, z = 0;
|
||||
|
||||
for (i = 6*(3 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
for (i = 6 * (1 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
z = x[i] ? 0 : z + 1;
|
||||
if (z > 2*w) {
|
||||
nf_seed = (13849 + nf_seed*31821) & 0xffff;
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Spectral coefficients encoding/decoding
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_SPEC_H
|
||||
#define __LC3_SPEC_H
|
||||
|
||||
|
||||
1802
src/tables.c
1802
src/tables.c
File diff suppressed because it is too large
Load Diff
@@ -42,9 +42,10 @@ extern const float *lc3_mdct_win[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
* Limits of bands
|
||||
*/
|
||||
|
||||
#define LC3_NUM_BANDS 64
|
||||
#define LC3_MAX_BANDS 64
|
||||
|
||||
extern const int lc3_band_lim[LC3_NUM_DT][LC3_NUM_SRATE][LC3_NUM_BANDS+1];
|
||||
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];
|
||||
|
||||
|
||||
/**
|
||||
|
||||
148
src/tns.c
148
src/tns.c
@@ -31,7 +31,7 @@
|
||||
*/
|
||||
static bool resolve_lpc_weighting(enum lc3_dt dt, int nbytes)
|
||||
{
|
||||
return nbytes < (dt == LC3_DT_7M5 ? 360/8 : 480/8);
|
||||
return nbytes * 8 < 120 * (int)(1 + dt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,24 +52,42 @@ LC3_HOT static inline float dot(const float *a, const float *b, int n)
|
||||
/**
|
||||
* LPC Coefficients
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* maxorder Maximum order of filter
|
||||
* x Spectral coefficients
|
||||
* gain, a Output the prediction gains and LPC coefficients
|
||||
*/
|
||||
LC3_HOT static void compute_lpc_coeffs(
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw, int maxorder,
|
||||
const float *x, float *gain, float (*a)[9])
|
||||
{
|
||||
static const int sub_7m5_nb[] = { 9, 26, 43, 60 };
|
||||
static const int sub_7m5_wb[] = { 9, 46, 83, 120 };
|
||||
static const int sub_7m5_sswb[] = { 9, 66, 123, 180 };
|
||||
static const int sub_7m5_swb[] = { 9, 46, 82, 120, 159, 200, 240 };
|
||||
static const int sub_7m5_fb[] = { 9, 56, 103, 150, 200, 250, 300 };
|
||||
|
||||
static const int sub_10m_nb[] = { 12, 34, 57, 80 };
|
||||
static const int sub_10m_wb[] = { 12, 61, 110, 160 };
|
||||
static const int sub_10m_sswb[] = { 12, 88, 164, 240 };
|
||||
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 };
|
||||
#if !LC3_NPLUS
|
||||
|
||||
static const int sub_2m5_nb[] = { 3, 10, 20 };
|
||||
static const int sub_2m5_wb[] = { 3, 20, 40 };
|
||||
static const int sub_2m5_sswb[] = { 3, 30, 60 };
|
||||
static const int sub_2m5_swb[] = { 3, 40, 80 };
|
||||
static const int sub_2m5_fb[] = { 3, 50, 100 };
|
||||
|
||||
static const int sub_5m_nb[] = { 6, 23, 40 };
|
||||
static const int sub_5m_wb[] = { 6, 43, 80 };
|
||||
static const int sub_5m_sswb[] = { 6, 63, 120 };
|
||||
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 */
|
||||
|
||||
static const int sub_7m5_nb[] = { 9, 26, 43, 60 };
|
||||
static const int sub_7m5_wb[] = { 9, 46, 83, 120 };
|
||||
static const int sub_7m5_sswb[] = { 9, 66, 123, 180 };
|
||||
static const int sub_7m5_swb[] = { 9, 46, 82, 120, 159, 200, 240 };
|
||||
static const int sub_7m5_fb[] = { 9, 56, 103, 150, 200, 250, 300 };
|
||||
|
||||
static const int sub_10m_nb[] = { 12, 34, 57, 80 };
|
||||
static const int sub_10m_wb[] = { 12, 61, 110, 160 };
|
||||
static const int sub_10m_sswb[] = { 12, 88, 164, 240 };
|
||||
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 --- */
|
||||
|
||||
@@ -79,32 +97,53 @@ LC3_HOT static void compute_lpc_coeffs(
|
||||
8.81323137e-01
|
||||
};
|
||||
|
||||
const int *sub = (const int * const [LC3_NUM_DT][LC3_NUM_SRATE]){
|
||||
{ sub_7m5_nb, sub_7m5_wb, sub_7m5_sswb, sub_7m5_swb, sub_7m5_fb },
|
||||
{ sub_10m_nb, sub_10m_wb, sub_10m_sswb, sub_10m_swb, sub_10m_fb },
|
||||
const int *sub = (const int * const [LC3_NUM_DT][LC3_NUM_BANDWIDTH]){
|
||||
|
||||
#if !LC3_NPLUS
|
||||
|
||||
[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 },
|
||||
|
||||
#endif /* !LC3_NPLUS */
|
||||
|
||||
[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 },
|
||||
|
||||
}[dt][bw];
|
||||
|
||||
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int nsubdivisions = 2 + (dt >= LC3_DT_7M5);
|
||||
|
||||
const float *xs, *xe = x + *sub;
|
||||
float r[2][9];
|
||||
|
||||
for (int f = 0; f < nfilters; f++) {
|
||||
float c[9][3];
|
||||
float c[9][3] = { 0 };
|
||||
|
||||
for (int s = 0; s < 3; s++) {
|
||||
for (int s = 0; s < nsubdivisions; s++) {
|
||||
xs = xe, xe = x + *(++sub);
|
||||
|
||||
for (int k = 0; k < 9; k++)
|
||||
for (int k = 0; k <= maxorder; k++)
|
||||
c[k][s] = dot(xs, xs + k, (xe - xs) - k);
|
||||
}
|
||||
|
||||
float e0 = c[0][0], e1 = c[0][1], e2 = c[0][2];
|
||||
r[f][0] = nsubdivisions;
|
||||
if (nsubdivisions == 2) {
|
||||
float e0 = c[0][0], e1 = c[0][1];
|
||||
for (int k = 1; k <= maxorder; k++)
|
||||
r[f][k] = e0 == 0 || e1 == 0 ? 0 :
|
||||
(c[k][0]/e0 + c[k][1]/e1) * lag_window[k];
|
||||
|
||||
r[f][0] = 3;
|
||||
for (int k = 1; k < 9; k++)
|
||||
r[f][k] = e0 == 0 || e1 == 0 || e2 == 0 ? 0 :
|
||||
(c[k][0]/e0 + c[k][1]/e1 + c[k][2]/e2) * lag_window[k];
|
||||
} else {
|
||||
float e0 = c[0][0], e1 = c[0][1], e2 = c[0][2];
|
||||
for (int k = 1; k <= maxorder; k++)
|
||||
r[f][k] = e0 == 0 || e1 == 0 || e2 == 0 ? 0 :
|
||||
(c[k][0]/e0 + c[k][1]/e1 + c[k][2]/e2) * lag_window[k];
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Levinson-Durbin recursion --- */
|
||||
@@ -116,7 +155,7 @@ LC3_HOT static void compute_lpc_coeffs(
|
||||
gain[f] = err;
|
||||
|
||||
a0[0] = 1;
|
||||
for (int k = 1; k < 9; ) {
|
||||
for (int k = 1; k <= maxorder; ) {
|
||||
|
||||
rc = -r[f][k];
|
||||
for (int i = 1; i < k; i++)
|
||||
@@ -160,21 +199,22 @@ LC3_HOT static void lpc_weighting(float pred_gain, float *a)
|
||||
|
||||
/**
|
||||
* LPC reflection
|
||||
* a LPC coefficients
|
||||
* a, maxorder LPC coefficients, and maximum order (4 or 8)
|
||||
* rc Output refelection coefficients
|
||||
*/
|
||||
LC3_HOT static void lpc_reflection(const float *a, float *rc)
|
||||
LC3_HOT static void lpc_reflection(
|
||||
const float *a, int maxorder, float *rc)
|
||||
{
|
||||
float e, b[2][7], *b0, *b1;
|
||||
|
||||
rc[7] = a[1+7];
|
||||
e = 1 - rc[7] * rc[7];
|
||||
rc[maxorder-1] = a[maxorder];
|
||||
e = 1 - rc[maxorder-1] * rc[maxorder-1];
|
||||
|
||||
b1 = b[1];
|
||||
for (int i = 0; i < 7; i++)
|
||||
b1[i] = (a[1+i] - rc[7] * a[7-i]) / e;
|
||||
for (int i = 0; i < maxorder-1; i++)
|
||||
b1[i] = (a[1+i] - rc[maxorder-1] * a[(maxorder-1)-i]) / e;
|
||||
|
||||
for (int k = 6; k > 0; k--) {
|
||||
for (int k = maxorder-2; k > 0; k--) {
|
||||
b0 = b1, b1 = b[k & 1];
|
||||
|
||||
rc[k] = b0[k];
|
||||
@@ -189,11 +229,11 @@ LC3_HOT static void lpc_reflection(const float *a, float *rc)
|
||||
|
||||
/**
|
||||
* Quantization of RC coefficients
|
||||
* rc Refelection coefficients
|
||||
* rc_order Return order of coefficients
|
||||
* rc, maxorder Refelection coefficients, and maximum order (4 or 8)
|
||||
* order Return order of coefficients
|
||||
* rc_i Return quantized coefficients
|
||||
*/
|
||||
static void quantize_rc(const float *rc, int *rc_order, int *rc_q)
|
||||
static void quantize_rc(const float *rc, int maxorder, int *order, int *rc_q)
|
||||
{
|
||||
/* Quantization table, sin(delta * (i + 0.5)), delta = Pi / 17 */
|
||||
|
||||
@@ -202,9 +242,9 @@ static void quantize_rc(const float *rc, int *rc_order, int *rc_q)
|
||||
7.39008917e-01, 8.50217136e-01, 9.32472229e-01, 9.82973100e-01
|
||||
};
|
||||
|
||||
*rc_order = 8;
|
||||
*order = maxorder;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int i = 0; i < maxorder; i++) {
|
||||
float rc_m = fabsf(rc[i]);
|
||||
|
||||
rc_q[i] = 4 * (rc_m >= q_thr[4]);
|
||||
@@ -213,17 +253,16 @@ static void quantize_rc(const float *rc, int *rc_order, int *rc_q)
|
||||
if (rc[i] < 0)
|
||||
rc_q[i] = -rc_q[i];
|
||||
|
||||
*rc_order = rc_q[i] != 0 ? 8 : *rc_order - 1;
|
||||
*order = rc_q[i] != 0 ? maxorder : *order - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquantization of RC coefficients
|
||||
* rc_q Quantized coefficients
|
||||
* rc_order Order of coefficients
|
||||
* rc_q, order Quantized coefficients, and order
|
||||
* rc Return refelection coefficients
|
||||
*/
|
||||
static void unquantize_rc(const int *rc_q, int rc_order, float rc[8])
|
||||
static void unquantize_rc(const int *rc_q, int order, float rc[8])
|
||||
{
|
||||
/* Quantization table, sin(delta * i), delta = Pi / 17 */
|
||||
|
||||
@@ -235,7 +274,7 @@ static void unquantize_rc(const int *rc_q, int rc_order, float rc[8])
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rc_order; i++) {
|
||||
for (i = 0; i < order; i++) {
|
||||
float rc_m = q_inv[LC3_ABS(rc_q[i])];
|
||||
rc[i] = rc_q[i] < 0 ? -rc_m : rc_m;
|
||||
}
|
||||
@@ -256,9 +295,9 @@ LC3_HOT static void forward_filtering(
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const int rc_order[2], float (* const rc)[8], float *x)
|
||||
{
|
||||
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
|
||||
int i0, ie = 3*(3 + dt);
|
||||
int i0, ie = 3*(1 + dt);
|
||||
|
||||
float s[8] = { 0 };
|
||||
|
||||
@@ -297,9 +336,9 @@ LC3_HOT static void inverse_filtering(
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const int rc_order[2], float (* const rc)[8], float *x)
|
||||
{
|
||||
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
|
||||
int i0, ie = 3*(3 + dt);
|
||||
int i0, ie = 3*(1 + dt);
|
||||
|
||||
float s[8] = { 0 };
|
||||
|
||||
@@ -349,10 +388,11 @@ void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
float pred_gain[2], a[2][9];
|
||||
float rc[2][8];
|
||||
|
||||
data->nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
|
||||
data->nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
int maxorder = dt <= LC3_DT_5M ? 4 : 8;
|
||||
|
||||
compute_lpc_coeffs(dt, bw, x, pred_gain, a);
|
||||
compute_lpc_coeffs(dt, bw, maxorder, x, pred_gain, a);
|
||||
|
||||
for (int f = 0; f < data->nfilters; f++) {
|
||||
|
||||
@@ -363,9 +403,9 @@ void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
if (data->lpc_weighting && pred_gain[f] < 2.f)
|
||||
lpc_weighting(pred_gain[f], a[f]);
|
||||
|
||||
lpc_reflection(a[f], rc[f]);
|
||||
lpc_reflection(a[f], maxorder, rc[f]);
|
||||
|
||||
quantize_rc(rc[f], &data->rc_order[f], data->rc[f]);
|
||||
quantize_rc(rc[f], maxorder, &data->rc_order[f], data->rc[f]);
|
||||
unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
|
||||
}
|
||||
|
||||
@@ -435,10 +475,10 @@ void lc3_tns_put_data(lc3_bits_t *bits, const struct lc3_tns_data *data)
|
||||
/**
|
||||
* Get bitstream data
|
||||
*/
|
||||
void lc3_tns_get_data(lc3_bits_t *bits,
|
||||
int lc3_tns_get_data(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data)
|
||||
{
|
||||
data->nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
data->nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
|
||||
data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
|
||||
|
||||
for (int f = 0; f < data->nfilters; f++) {
|
||||
@@ -449,9 +489,13 @@ void lc3_tns_get_data(lc3_bits_t *bits,
|
||||
|
||||
data->rc_order[f] += lc3_get_symbol(bits,
|
||||
lc3_tns_order_models + data->lpc_weighting);
|
||||
if (dt <= LC3_DT_5M && data->rc_order[f] > 4)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < data->rc_order[f]; i++)
|
||||
data->rc[f][i] = (int)lc3_get_symbol(bits,
|
||||
lc3_tns_coeffs_models + i) - 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
10
src/tns.h
10
src/tns.h
@@ -16,13 +16,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Temporal Noise Shaping
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_TNS_H
|
||||
#define __LC3_TNS_H
|
||||
|
||||
@@ -82,8 +75,9 @@ void lc3_tns_put_data(lc3_bits_t *bits, const lc3_tns_data_t *data);
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* nbytes Size in bytes of the frame
|
||||
* data Bitstream data
|
||||
* return 0: Ok -1: Invalid bitstream data
|
||||
*/
|
||||
void lc3_tns_get_data(lc3_bits_t *bits,
|
||||
int lc3_tns_get_data(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user