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:
anonymix007
2023-12-13 10:56:20 -08:00
committed by Antoine Soulier
parent a75f187e00
commit 149cb6537e
43 changed files with 3095 additions and 1628 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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];

View File

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

View File

@@ -16,10 +16,6 @@
*
******************************************************************************/
/**
* LC3 - Mathematics function approximation
*/
#ifndef __LC3_FASTMATH_H
#define __LC3_FASTMATH_H

View File

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

View File

@@ -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](&ltpf->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 --- */

View File

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

View File

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

View File

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

View File

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

View File

@@ -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]);

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -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
View File

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

View File

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