mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
g723_1: add comfort noise generation
This commit is contained in:
parent
040405b59e
commit
04fc5c6bde
@ -35,6 +35,8 @@
|
||||
#include "celp_filters.h"
|
||||
#include "g723_1_data.h"
|
||||
|
||||
#define CNG_RANDOM_SEED 12345
|
||||
|
||||
/**
|
||||
* G723.1 frame types
|
||||
*/
|
||||
@ -84,6 +86,7 @@ typedef struct g723_1_context {
|
||||
int erased_frames;
|
||||
|
||||
int16_t prev_lsp[LPC_ORDER];
|
||||
int16_t sid_lsp[LPC_ORDER];
|
||||
int16_t prev_excitation[PITCH_MAX];
|
||||
int16_t excitation[PITCH_MAX + FRAME_LEN + 4];
|
||||
int16_t synth_mem[LPC_ORDER];
|
||||
@ -91,6 +94,7 @@ typedef struct g723_1_context {
|
||||
int iir_mem[LPC_ORDER];
|
||||
|
||||
int random_seed;
|
||||
int cng_random_seed;
|
||||
int interp_index;
|
||||
int interp_gain;
|
||||
int sid_gain;
|
||||
@ -99,7 +103,7 @@ typedef struct g723_1_context {
|
||||
int pf_gain;
|
||||
int postfilter;
|
||||
|
||||
int16_t audio[FRAME_LEN + LPC_ORDER + PITCH_MAX];
|
||||
int16_t audio[FRAME_LEN + LPC_ORDER + PITCH_MAX + 4];
|
||||
} G723_1_Context;
|
||||
|
||||
static av_cold int g723_1_decode_init(AVCodecContext *avctx)
|
||||
@ -116,6 +120,10 @@ static av_cold int g723_1_decode_init(AVCodecContext *avctx)
|
||||
avctx->coded_frame = &p->frame;
|
||||
|
||||
memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(*p->prev_lsp));
|
||||
memcpy(p->sid_lsp, dc_lsp, LPC_ORDER * sizeof(*p->sid_lsp));
|
||||
|
||||
p->cng_random_seed = CNG_RANDOM_SEED;
|
||||
p->past_frame_type = SID_FRAME;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -983,6 +991,201 @@ static void formant_postfilter(G723_1_Context *p, int16_t *lpc,
|
||||
}
|
||||
}
|
||||
|
||||
static int sid_gain_to_lsp_index(int gain)
|
||||
{
|
||||
if (gain < 0x10)
|
||||
return gain << 6;
|
||||
else if (gain < 0x20)
|
||||
return gain - 8 << 7;
|
||||
else
|
||||
return gain - 20 << 8;
|
||||
}
|
||||
|
||||
static inline int cng_rand(int *state, int base)
|
||||
{
|
||||
*state = (*state * 521 + 259) & 0xFFFF;
|
||||
return (*state & 0x7FFF) * base >> 15;
|
||||
}
|
||||
|
||||
static int estimate_sid_gain(G723_1_Context *p)
|
||||
{
|
||||
int i, shift, seg, seg2, t, val, val_add, x, y;
|
||||
|
||||
shift = 16 - p->cur_gain * 2;
|
||||
if (shift > 0)
|
||||
t = p->sid_gain << shift;
|
||||
else
|
||||
t = p->sid_gain >> -shift;
|
||||
x = t * cng_filt[0] >> 16;
|
||||
|
||||
if (x >= cng_bseg[2])
|
||||
return 0x3F;
|
||||
|
||||
if (x >= cng_bseg[1]) {
|
||||
shift = 4;
|
||||
seg = 3;
|
||||
} else {
|
||||
shift = 3;
|
||||
seg = (x >= cng_bseg[0]);
|
||||
}
|
||||
seg2 = FFMIN(seg, 3);
|
||||
|
||||
val = 1 << shift;
|
||||
val_add = val >> 1;
|
||||
for (i = 0; i < shift; i++) {
|
||||
t = seg * 32 + (val << seg2);
|
||||
t *= t;
|
||||
if (x >= t)
|
||||
val += val_add;
|
||||
else
|
||||
val -= val_add;
|
||||
val_add >>= 1;
|
||||
}
|
||||
|
||||
t = seg * 32 + (val << seg2);
|
||||
y = t * t - x;
|
||||
if (y <= 0) {
|
||||
t = seg * 32 + (val + 1 << seg2);
|
||||
t = t * t - x;
|
||||
val = (seg2 - 1 << 4) + val;
|
||||
if (t >= y)
|
||||
val++;
|
||||
} else {
|
||||
t = seg * 32 + (val - 1 << seg2);
|
||||
t = t * t - x;
|
||||
val = (seg2 - 1 << 4) + val;
|
||||
if (t >= y)
|
||||
val--;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void generate_noise(G723_1_Context *p)
|
||||
{
|
||||
int i, j, idx, t;
|
||||
int off[SUBFRAMES];
|
||||
int signs[SUBFRAMES / 2 * 11], pos[SUBFRAMES / 2 * 11];
|
||||
int tmp[SUBFRAME_LEN * 2];
|
||||
int16_t *vector_ptr;
|
||||
int64_t sum;
|
||||
int b0, c, delta, x, shift;
|
||||
|
||||
p->pitch_lag[0] = cng_rand(&p->cng_random_seed, 21) + 123;
|
||||
p->pitch_lag[1] = cng_rand(&p->cng_random_seed, 19) + 123;
|
||||
|
||||
for (i = 0; i < SUBFRAMES; i++) {
|
||||
p->subframe[i].ad_cb_gain = cng_rand(&p->cng_random_seed, 50) + 1;
|
||||
p->subframe[i].ad_cb_lag = cng_adaptive_cb_lag[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < SUBFRAMES / 2; i++) {
|
||||
t = cng_rand(&p->cng_random_seed, 1 << 13);
|
||||
off[i * 2] = t & 1;
|
||||
off[i * 2 + 1] = ((t >> 1) & 1) + SUBFRAME_LEN;
|
||||
t >>= 2;
|
||||
for (j = 0; j < 11; j++) {
|
||||
signs[i * 11 + j] = (t & 1) * 2 - 1 << 14;
|
||||
t >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
for (i = 0; i < SUBFRAMES; i++) {
|
||||
for (j = 0; j < SUBFRAME_LEN / 2; j++)
|
||||
tmp[j] = j;
|
||||
t = SUBFRAME_LEN / 2;
|
||||
for (j = 0; j < pulses[i]; j++, idx++) {
|
||||
int idx2 = cng_rand(&p->cng_random_seed, t);
|
||||
|
||||
pos[idx] = tmp[idx2] * 2 + off[i];
|
||||
tmp[idx2] = tmp[--t];
|
||||
}
|
||||
}
|
||||
|
||||
vector_ptr = p->audio + LPC_ORDER;
|
||||
memcpy(vector_ptr, p->prev_excitation,
|
||||
PITCH_MAX * sizeof(*p->excitation));
|
||||
for (i = 0; i < SUBFRAMES; i += 2) {
|
||||
gen_acb_excitation(vector_ptr, vector_ptr,
|
||||
p->pitch_lag[i >> 1], &p->subframe[i],
|
||||
p->cur_rate);
|
||||
gen_acb_excitation(vector_ptr + SUBFRAME_LEN,
|
||||
vector_ptr + SUBFRAME_LEN,
|
||||
p->pitch_lag[i >> 1], &p->subframe[i + 1],
|
||||
p->cur_rate);
|
||||
|
||||
t = 0;
|
||||
for (j = 0; j < SUBFRAME_LEN * 2; j++)
|
||||
t |= FFABS(vector_ptr[j]);
|
||||
t = FFMIN(t, 0x7FFF);
|
||||
if (!t) {
|
||||
shift = 0;
|
||||
} else {
|
||||
shift = -10 + av_log2(t);
|
||||
if (shift < -2)
|
||||
shift = -2;
|
||||
}
|
||||
sum = 0;
|
||||
if (shift < 0) {
|
||||
for (j = 0; j < SUBFRAME_LEN * 2; j++) {
|
||||
t = vector_ptr[j] << -shift;
|
||||
sum += t * t;
|
||||
tmp[j] = t;
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < SUBFRAME_LEN * 2; j++) {
|
||||
t = vector_ptr[j] >> shift;
|
||||
sum += t * t;
|
||||
tmp[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
b0 = 0;
|
||||
for (j = 0; j < 11; j++)
|
||||
b0 += tmp[pos[(i / 2) * 11 + j]] * signs[(i / 2) * 11 + j];
|
||||
b0 = b0 * 2 * 2979LL + (1 << 29) >> 30; // approximated division by 11
|
||||
|
||||
c = p->cur_gain * (p->cur_gain * SUBFRAME_LEN >> 5);
|
||||
if (shift * 2 + 3 >= 0)
|
||||
c >>= shift * 2 + 3;
|
||||
else
|
||||
c <<= -(shift * 2 + 3);
|
||||
c = (av_clipl_int32(sum << 1) - c) * 2979LL >> 15;
|
||||
|
||||
delta = b0 * b0 * 2 - c;
|
||||
if (delta <= 0) {
|
||||
x = -b0;
|
||||
} else {
|
||||
delta = square_root(delta);
|
||||
x = delta - b0;
|
||||
t = delta + b0;
|
||||
if (FFABS(t) < FFABS(x))
|
||||
x = -t;
|
||||
}
|
||||
shift++;
|
||||
if (shift < 0)
|
||||
x >>= -shift;
|
||||
else
|
||||
x <<= shift;
|
||||
x = av_clip(x, -10000, 10000);
|
||||
|
||||
for (j = 0; j < 11; j++) {
|
||||
idx = (i / 2) * 11 + j;
|
||||
vector_ptr[pos[idx]] = av_clip_int16(vector_ptr[pos[idx]] +
|
||||
(x * signs[idx] >> 15));
|
||||
}
|
||||
|
||||
/* copy decoded data to serve as a history for the next decoded subframes */
|
||||
memcpy(vector_ptr + PITCH_MAX, vector_ptr,
|
||||
sizeof(*vector_ptr) * SUBFRAME_LEN * 2);
|
||||
vector_ptr += SUBFRAME_LEN * 2;
|
||||
}
|
||||
/* Save the excitation for the next frame */
|
||||
memcpy(p->prev_excitation, p->audio + LPC_ORDER + FRAME_LEN,
|
||||
PITCH_MAX * sizeof(*p->excitation));
|
||||
}
|
||||
|
||||
static int g723_1_decode_frame(AVCodecContext *avctx, void *data,
|
||||
int *got_frame_ptr, AVPacket *avpkt)
|
||||
{
|
||||
@ -1107,14 +1310,23 @@ static int g723_1_decode_frame(AVCodecContext *avctx, void *data,
|
||||
PITCH_MAX * sizeof(*p->excitation));
|
||||
}
|
||||
}
|
||||
p->cng_random_seed = CNG_RANDOM_SEED;
|
||||
} else {
|
||||
memset(out, 0, FRAME_LEN * 2);
|
||||
av_log(avctx, AV_LOG_WARNING,
|
||||
"G.723.1: Comfort noise generation not supported yet\n");
|
||||
if (p->cur_frame_type == SID_FRAME) {
|
||||
p->sid_gain = sid_gain_to_lsp_index(p->subframe[0].amp_index);
|
||||
inverse_quant(p->sid_lsp, p->prev_lsp, p->lsp_index, 0);
|
||||
} else if (p->past_frame_type == ACTIVE_FRAME) {
|
||||
p->sid_gain = estimate_sid_gain(p);
|
||||
}
|
||||
|
||||
*got_frame_ptr = 1;
|
||||
*(AVFrame *)data = p->frame;
|
||||
return frame_size[dec_mode];
|
||||
if (p->past_frame_type == ACTIVE_FRAME)
|
||||
p->cur_gain = p->sid_gain;
|
||||
else
|
||||
p->cur_gain = (p->cur_gain * 7 + p->sid_gain) >> 3;
|
||||
generate_noise(p);
|
||||
lsp_interpolate(lpc, p->sid_lsp, p->prev_lsp);
|
||||
/* Save the lsp_vector for the next frame */
|
||||
memcpy(p->prev_lsp, p->sid_lsp, LPC_ORDER * sizeof(*p->prev_lsp));
|
||||
}
|
||||
|
||||
p->past_frame_type = p->cur_frame_type;
|
||||
|
@ -1191,4 +1191,10 @@ static const int16_t postfilter_tbl[2][LPC_ORDER] = {
|
||||
{ 24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845 }
|
||||
};
|
||||
|
||||
static const int cng_adaptive_cb_lag[4] = { 1, 0, 1, 3 };
|
||||
|
||||
static const int cng_filt[4] = { 273, 998, 499, 333 };
|
||||
|
||||
static const int cng_bseg[3] = { 2048, 18432, 231233 };
|
||||
|
||||
#endif /* AVCODEC_G723_1_DATA_H */
|
||||
|
@ -27,6 +27,12 @@ fate-g723_1-dec-5: CMD = framecrc -postfilter 1 -i $(SAMPLES)/g723_1/pathd63p.tc
|
||||
FATE_G723_1 += fate-g723_1-dec-6
|
||||
fate-g723_1-dec-6: CMD = framecrc -postfilter 1 -i $(SAMPLES)/g723_1/tamed63p.tco
|
||||
|
||||
FATE_G723_1 += fate-g723_1-dec-7
|
||||
fate-g723_1-dec-7: CMD = framecrc -postfilter 1 -i $(SAMPLES)/g723_1/dtx63b.tco
|
||||
|
||||
FATE_G723_1 += fate-g723_1-dec-8
|
||||
fate-g723_1-dec-8: CMD = framecrc -postfilter 1 -i $(SAMPLES)/g723_1/dtx63e.tco
|
||||
|
||||
FATE_SAMPLES_AVCONV += $(FATE_G723_1)
|
||||
fate-g723_1: $(FATE_G723_1)
|
||||
|
||||
|
12
tests/ref/fate/g723_1-dec-7
Normal file
12
tests/ref/fate/g723_1-dec-7
Normal file
@ -0,0 +1,12 @@
|
||||
#tb 0: 1/8000
|
||||
0, 0, 0, 240, 480, 0x35e4a1fd
|
||||
0, 240, 240, 240, 480, 0x2f7bdd60
|
||||
0, 480, 480, 240, 480, 0x0407e499
|
||||
0, 720, 720, 240, 480, 0x5f5ef209
|
||||
0, 960, 960, 240, 480, 0xe936e8d1
|
||||
0, 1200, 1200, 240, 480, 0x0896ddba
|
||||
0, 1440, 1440, 240, 480, 0xa885ea94
|
||||
0, 1680, 1680, 240, 480, 0x40bff3d0
|
||||
0, 1920, 1920, 240, 480, 0xe05ce4c3
|
||||
0, 2160, 2160, 240, 480, 0x80c4f790
|
||||
0, 2400, 2400, 240, 480, 0x65d5e8f9
|
121
tests/ref/fate/g723_1-dec-8
Normal file
121
tests/ref/fate/g723_1-dec-8
Normal file
@ -0,0 +1,121 @@
|
||||
#tb 0: 1/8000
|
||||
0, 0, 0, 240, 480, 0x17930e0f
|
||||
0, 240, 240, 240, 480, 0x7c7f4247
|
||||
0, 480, 480, 240, 480, 0xbf3489e5
|
||||
0, 720, 720, 240, 480, 0x24319fc9
|
||||
0, 960, 960, 240, 480, 0xb327eec0
|
||||
0, 1200, 1200, 240, 480, 0xc2ddcbca
|
||||
0, 1440, 1440, 240, 480, 0xeebad740
|
||||
0, 1680, 1680, 240, 480, 0x77fcb933
|
||||
0, 1920, 1920, 240, 480, 0x9677c5b7
|
||||
0, 2160, 2160, 240, 480, 0xb49dcb9e
|
||||
0, 2400, 2400, 240, 480, 0x0e78d7e6
|
||||
0, 2640, 2640, 240, 480, 0xf752dc3e
|
||||
0, 2880, 2880, 240, 480, 0xc95af091
|
||||
0, 3120, 3120, 240, 480, 0xa25de399
|
||||
0, 3360, 3360, 240, 480, 0x34e7e0da
|
||||
0, 3600, 3600, 240, 480, 0x6c84e3f4
|
||||
0, 3840, 3840, 240, 480, 0x2c7dda20
|
||||
0, 4080, 4080, 240, 480, 0x00a5f112
|
||||
0, 4320, 4320, 240, 480, 0x943ddd89
|
||||
0, 4560, 4560, 240, 480, 0x4ad4ebac
|
||||
0, 4800, 4800, 240, 480, 0xa4ff0aa8
|
||||
0, 5040, 5040, 240, 480, 0xc0f805f2
|
||||
0, 5280, 5280, 240, 480, 0x859ce987
|
||||
0, 5520, 5520, 240, 480, 0x9ebcd0de
|
||||
0, 5760, 5760, 240, 480, 0x3de2db0b
|
||||
0, 6000, 6000, 240, 480, 0x0affea9c
|
||||
0, 6240, 6240, 240, 480, 0xcb1bf81e
|
||||
0, 6480, 6480, 240, 480, 0x8a72d71d
|
||||
0, 6720, 6720, 240, 480, 0x583cd5cd
|
||||
0, 6960, 6960, 240, 480, 0x4be7dc7b
|
||||
0, 7200, 7200, 240, 480, 0xb08108c0
|
||||
0, 7440, 7440, 240, 480, 0xd0b3ed59
|
||||
0, 7680, 7680, 240, 480, 0x7d33f822
|
||||
0, 7920, 7920, 240, 480, 0x199c0111
|
||||
0, 8160, 8160, 240, 480, 0x7d29f2a8
|
||||
0, 8400, 8400, 240, 480, 0x424dec5e
|
||||
0, 8640, 8640, 240, 480, 0x946cf258
|
||||
0, 8880, 8880, 240, 480, 0xd429da7a
|
||||
0, 9120, 9120, 240, 480, 0x0f11df46
|
||||
0, 9360, 9360, 240, 480, 0xf4dce502
|
||||
0, 9600, 9600, 240, 480, 0x01c1de78
|
||||
0, 9840, 9840, 240, 480, 0xd1d3da59
|
||||
0, 10080, 10080, 240, 480, 0x5822f3ec
|
||||
0, 10320, 10320, 240, 480, 0xadd5fe67
|
||||
0, 10560, 10560, 240, 480, 0xdcf5f2c3
|
||||
0, 10800, 10800, 240, 480, 0x5176e39b
|
||||
0, 11040, 11040, 240, 480, 0xf947e0b1
|
||||
0, 11280, 11280, 240, 480, 0x33b1eb36
|
||||
0, 11520, 11520, 240, 480, 0x57bce9bd
|
||||
0, 11760, 11760, 240, 480, 0x806eec1f
|
||||
0, 12000, 12000, 240, 480, 0x0a60f94a
|
||||
0, 12240, 12240, 240, 480, 0x9eddf27d
|
||||
0, 12480, 12480, 240, 480, 0x3d28ef2f
|
||||
0, 12720, 12720, 240, 480, 0x52f0e562
|
||||
0, 12960, 12960, 240, 480, 0xf2d6c8a0
|
||||
0, 13200, 13200, 240, 480, 0xfa0df4a1
|
||||
0, 13440, 13440, 240, 480, 0x9cccfda9
|
||||
0, 13680, 13680, 240, 480, 0xa7c1e528
|
||||
0, 13920, 13920, 240, 480, 0xe130e8f9
|
||||
0, 14160, 14160, 240, 480, 0x80f6eabe
|
||||
0, 14400, 14400, 240, 480, 0x9bbb027e
|
||||
0, 14640, 14640, 240, 480, 0x33cdea7f
|
||||
0, 14880, 14880, 240, 480, 0x84d8e761
|
||||
0, 15120, 15120, 240, 480, 0xb99ce457
|
||||
0, 15360, 15360, 240, 480, 0x5dc1e324
|
||||
0, 15600, 15600, 240, 480, 0xc914e6c3
|
||||
0, 15840, 15840, 240, 480, 0x8e77f5c2
|
||||
0, 16080, 16080, 240, 480, 0x3997034d
|
||||
0, 16320, 16320, 240, 480, 0x820cfd49
|
||||
0, 16560, 16560, 240, 480, 0x8ad5f24c
|
||||
0, 16800, 16800, 240, 480, 0xe21be71c
|
||||
0, 17040, 17040, 240, 480, 0x516ae8c8
|
||||
0, 17280, 17280, 240, 480, 0x595bdc3d
|
||||
0, 17520, 17520, 240, 480, 0x8a4bee79
|
||||
0, 17760, 17760, 240, 480, 0x307fed64
|
||||
0, 18000, 18000, 240, 480, 0xe71cf219
|
||||
0, 18240, 18240, 240, 480, 0xdb0be1a1
|
||||
0, 18480, 18480, 240, 480, 0x7947dfbd
|
||||
0, 18720, 18720, 240, 480, 0x5d90fbf0
|
||||
0, 18960, 18960, 240, 480, 0xa449fc55
|
||||
0, 19200, 19200, 240, 480, 0x45b2f979
|
||||
0, 19440, 19440, 240, 480, 0x2b2be378
|
||||
0, 19680, 19680, 240, 480, 0x2d2edf42
|
||||
0, 19920, 19920, 240, 480, 0x568ee04f
|
||||
0, 20160, 20160, 240, 480, 0x66f0debe
|
||||
0, 20400, 20400, 240, 480, 0xc943eab7
|
||||
0, 20640, 20640, 240, 480, 0xc9ade3c9
|
||||
0, 20880, 20880, 240, 480, 0x6971f92d
|
||||
0, 21120, 21120, 240, 480, 0x48d0ecbc
|
||||
0, 21360, 21360, 240, 480, 0xf641dc98
|
||||
0, 21600, 21600, 240, 480, 0xbb18e167
|
||||
0, 21840, 21840, 240, 480, 0x72ce0968
|
||||
0, 22080, 22080, 240, 480, 0x15bee6f6
|
||||
0, 22320, 22320, 240, 480, 0x93d5e91f
|
||||
0, 22560, 22560, 240, 480, 0x7aee010b
|
||||
0, 22800, 22800, 240, 480, 0x9e82dc87
|
||||
0, 23040, 23040, 240, 480, 0x4ee6f547
|
||||
0, 23280, 23280, 240, 480, 0x3072d102
|
||||
0, 23520, 23520, 240, 480, 0x74d4fb04
|
||||
0, 23760, 23760, 240, 480, 0xc670f958
|
||||
0, 24000, 24000, 240, 480, 0x3965c41f
|
||||
0, 24240, 24240, 240, 480, 0x6a2de869
|
||||
0, 24480, 24480, 240, 480, 0xa757f44b
|
||||
0, 24720, 24720, 240, 480, 0x94a5168c
|
||||
0, 24960, 24960, 240, 480, 0xef0f0c28
|
||||
0, 25200, 25200, 240, 480, 0x3770ebb3
|
||||
0, 25440, 25440, 240, 480, 0x4343de6f
|
||||
0, 25680, 25680, 240, 480, 0x3ec8d816
|
||||
0, 25920, 25920, 240, 480, 0x1661e3d3
|
||||
0, 26160, 26160, 240, 480, 0x077cd9fd
|
||||
0, 26400, 26400, 240, 480, 0xb5ece07e
|
||||
0, 26640, 26640, 240, 480, 0xf303e151
|
||||
0, 26880, 26880, 240, 480, 0x95e4d019
|
||||
0, 27120, 27120, 240, 480, 0x4bd0ddc0
|
||||
0, 27360, 27360, 240, 480, 0x6cebd341
|
||||
0, 27600, 27600, 240, 480, 0xea3fea9e
|
||||
0, 27840, 27840, 240, 480, 0x5ad30c3f
|
||||
0, 28080, 28080, 240, 480, 0x218c02a5
|
||||
0, 28320, 28320, 240, 480, 0x662decd0
|
||||
0, 28560, 28560, 240, 480, 0x6865e2f2
|
Loading…
Reference in New Issue
Block a user