[FFmpeg-soc] G.723.1 Encoder: Harmonic noise shaping

Mohamed Naufal naufal11 at gmail.com
Tue Aug 17 23:07:13 CEST 2010


---
 libavcodec/g723_1.c      |  106 +++++++++++++++++++++++++++++++++++++++++++++-
 libavcodec/g723_1_data.h |    8 ++++
 2 files changed, 113 insertions(+), 1 deletions(-)

diff --git a/libavcodec/g723_1.c b/libavcodec/g723_1.c
index 9b6ef57..d6f5ad1 100755
--- a/libavcodec/g723_1.c
+++ b/libavcodec/g723_1.c
@@ -1402,7 +1402,7 @@ static void lsp_quantize(int16_t *lsp, int16_t
*prev_lsp, uint8_t *lsp_index)
 }

 /**
- * Formant perceptual weighting filter.
+ * Apply the formant perceptual weighting filter.
  *
  * @param flt_coef filter coefficients
  * @param unq_lpc  unquantized lpc vector
@@ -1503,16 +1503,109 @@ update:
     return index;
 }

+/**
+ * Compute harmonic noise filter parameters.
+ *
+ * @param buf       perceptually weighted speech
+ * @param pitch_lag open loop pitch period
+ * @param hf        harmonic filter parameters
+ */
+static void comp_harmonic_coeff(int16_t *buf, int16_t pitch_lag, HFParam *hf)
+{
+    int ccr, eng, max_ccr, max_eng;
+    int exp, max, diff;
+    int energy[15];
+    int i, j;
+
+    for (i = 0, j = pitch_lag - 3; j <= pitch_lag + 3; i++, j++) {
+        /* Compute residual energy */
+        energy[i << 1] = dot_product(buf - j, buf - j, SUBFRAME_LEN, 0);
+        /* Compute correlation */
+        energy[(i << 1) + 1] = dot_product(buf, buf - j, SUBFRAME_LEN, 0);
+    }
+
+    /* Compute target energy */
+    energy[14] = dot_product(buf, buf, SUBFRAME_LEN, 0);
+
+    /* Normalize */
+    max = 0;
+    for (i = 0; i < 15; i++)
+        max = FFMAX(max, FFABS(energy[i]));
+
+    exp = normalize_bits_int32(max);
+    for (i = 0; i < 15; i++) {
+        energy[i] = av_clipl_int32((int64_t)(energy[i] << exp) +
+                                   (1 << 15)) >> 16;
+    }
+
+    hf->index = -1;
+    hf->gain  =  0;
+    max_ccr   =  1;
+    max_eng   =  0x7fff;
+
+    /* Compute the coefficients */
+    for (i = 0; i <= 6; i++) {
+        eng = energy[i << 1];
+        ccr = energy[(i << 1) + 1];
+
+        if (ccr <= 0)
+            continue;
+
+        ccr = (ccr * ccr + (1 << 14)) >> 15;
+        diff = ccr * max_eng - eng * max_ccr;
+        if (diff > 0) {
+            max_ccr   = ccr;
+            max_eng   = eng;
+            hf->index = i;
+        }
+    }
+
+    if (hf->index == -1) {
+        hf->index = pitch_lag;
+        return;
+    }
+
+    eng = energy[14] * max_eng;
+    eng = (eng >> 2) + (eng >> 3);
+    ccr = energy[(hf->index << 1) + 1] * energy[(hf->index << 1) + 1];
+    if (eng < ccr) {
+        eng = energy[(hf->index << 1) + 1];
+
+        if (eng >= max_eng)
+            hf->gain = 0x2800;
+        else
+            hf->gain = ((eng << 15) / max_eng * 0x2800 + (1 << 14)) >> 15;
+    }
+    hf->index += pitch_lag - 3;
+}
+
+/**
+ * Apply the harmonic noise shaping filter.
+ *
+ * @param hf filter parameters
+ */
+static void harmonic_filter(HFParam *hf, int16_t *src, int16_t *dest)
+{
+    int i;
+
+    for (i = 0; i < SUBFRAME_LEN; i++) {
+        int64_t temp = hf->gain * src[i - hf->index] << 1;
+        dest[i] = av_clipl_int32((src[i] << 16) - temp + (1 << 15)) >> 16;
+    }
+}
+
 static int g723_1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
                                int buf_size, void *data)
 {
     G723_1_Context *p = avctx->priv_data;
+    HFParam hf[4];
     int16_t unq_lpc[LPC_ORDER * SUBFRAMES];
     int16_t cur_lsp[LPC_ORDER];
     int16_t weighted_lpc[LPC_ORDER * SUBFRAMES << 1];
     int16_t vector[FRAME_LEN + PITCH_MAX];

     int16_t *in = data;
+    int i, j;

     highpass_filter(in, &p->fir_mem[0], &p->iir_mem[0]);
     comp_lpc_coeff(in, p->prev_data, unq_lpc);
@@ -1538,6 +1631,17 @@ static int g723_1_encode_frame(AVCodecContext
*avctx, unsigned char *buf,

     p->pitch_lag[0] = estimate_pitch(vector, PITCH_MAX);
     p->pitch_lag[1] = estimate_pitch(vector, PITCH_MAX + HALF_FRAME_LEN);
+
+    for (i = PITCH_MAX, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++)
+        comp_harmonic_coeff(vector + i, p->pitch_lag[j >> 1], hf + j);
+
+    memcpy(vector, p->prev_weight_sig, sizeof(int16_t) * PITCH_MAX);
+    memcpy(vector + PITCH_MAX, in, sizeof(int16_t) * FRAME_LEN);
+    memcpy(p->prev_weight_sig, vector + FRAME_LEN, sizeof(int16_t) *
PITCH_MAX);
+
+    for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++)
+        harmonic_filter(hf + j, vector + PITCH_MAX + i, in + i);
+
     return 0;
 }

diff --git a/libavcodec/g723_1_data.h b/libavcodec/g723_1_data.h
index 1e23bcb..ea1a86d 100644
--- a/libavcodec/g723_1_data.h
+++ b/libavcodec/g723_1_data.h
@@ -82,6 +82,14 @@ typedef struct {
 } PPFParam;

 /**
+ * Harmonic filter parameters
+ */
+typedef struct {
+    int index;
+    int gain;
+} HFParam;
+
+/**
  * Postfilter gain weighting factors scaled by 2^15
  */
 static const int16_t ppf_gain_weight[2] = {0x1800, 0x2000};
-- 
1.7.0.2


More information about the FFmpeg-soc mailing list