g723_1: add comfort noise generation

This commit is contained in:
Kostya Shishkov 2012-08-23 19:51:11 +02:00
parent 040405b59e
commit 04fc5c6bde
5 changed files with 364 additions and 7 deletions

View File

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

View File

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

View File

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

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