[FFmpeg-soc] [soc]: r1502 - amr/amrnbfloatdec.c

superdump subversion at mplayerhq.hu
Tue Dec 4 00:48:44 CET 2007


Author: superdump
Date: Tue Dec  4 00:48:44 2007
New Revision: 1502

Log:
Synthesis (hopefully without too many mistakes) and float to 16-bit int
conversion


Modified:
   amr/amrnbfloatdec.c

Modified: amr/amrnbfloatdec.c
==============================================================================
--- amr/amrnbfloatdec.c	(original)
+++ amr/amrnbfloatdec.c	Tue Dec  4 00:48:44 2007
@@ -34,12 +34,12 @@
 #include "avcodec.h"
 #include "bitstream.h"
 #include "common.h"
+#include "dsputil.h"
 #include "amrnbfloatdata.h"
 
 typedef struct AMRContext {
 
     GetBitContext                        gb;
-    int16_t                  *sample_buffer;
 
     int16_t                       *amr_prms; ///< pointer to the decoded amr parameters (lsf coefficients, codebook indices, etc)
     int                 bad_frame_indicator; ///< bad frame ? 1 : 0
@@ -76,24 +76,36 @@ typedef struct AMRContext {
     uint8_t           ir_filter_strength[2]; ///< impulse response filter strength; 0 - strong, 1 - medium, 2 - none
     float                        *ir_filter; ///< pointer to impulse response filter data
 
+    DSPContext                          dsp;
+    float                          add_bias;
+    float                          mul_bias;
+    DECLARE_ALIGNED_16(float,    samples_in[LP_FILTER_ORDER + AMR_BLOCK_SIZE]); ///< floating point samples
+    DECLARE_ALIGNED_16(int16_t, samples_out[LP_FILTER_ORDER + AMR_BLOCK_SIZE]); ///< 16-bit signed int samples
+
 } AMRContext;
 
 
 static int amrnb_decode_init(AVCodecContext *avctx) {
     AMRContext *p = avctx->priv_data;
 
-    // allocate and zero the 16-bit mono sample buffer
-    p->sample_buffer = av_mallocz(sizeof(int16_t)*AMR_BLOCK_SIZE);
     // allocate and zero the amr parameters
     p->amr_prms = av_mallocz(sizeof(int16_t)*PRMS_MODE_122);
 
-    /* Check if the allocation was successful */
-    if(p->sample_buffer == NULL)
-        return -1;
     // Check amr_prms allocation
     if(p->amr_prms == NULL)
         return -1;
 
+    dsputil_init(&p->dsp, avctx);
+
+    // set bias values for float to 16-bit int conversion
+    if(p->dsp.float_to_int16 == ff_float_to_int16_c) {
+        p->add_bias = 385.0;
+        p->mul_bias = 1.0;
+    }else {
+        p->add_bias = 0.0;
+        p->mul_bias = 32767.0;
+    }
+
     // p->excitation always points to the same position in p->excitation_buf
     p->excitation = &p->excitation_buf[PITCH_LAG_MAX + LP_FILTER_ORDER + 1];
 
@@ -906,6 +918,74 @@ static void convolve_circ(float *fixed_v
 /*** end of pre-processing functions ***/
 
 
+/*** synthesis functions ***/
+
+/**
+ * Conduct 10th order linear predictive coding synthesis
+ *
+ * @param p             pointer to the AMRContext
+ * @param excitation    pointer to the excitation vector
+ * @param lpc           pointer to the LPC coefficients
+ * @param samples       pointer to the output speech samples
+ * @param overflow      16-bit overflow flag
+ */
+
+static void synthesis(AMRContext *p, float *excitation, float *lpc, float *samples, uint8_t overflow) {
+    int i, j;
+
+    // if an overflow has been detected, the pitch vector is scaled down by a
+    // factor of 4
+    if(overflow) {
+        for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+            p->pitch_vector[i] /= 4.0;
+        }
+    }
+
+    // construct the excitation vector
+    for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+        excitation[i] = p->pitch_gain*p->pitch_vector[i] + p->fixed_gain*p->fixed_vector[i];
+    }
+
+    // if an overflow has been detected, pitch vector contribution emphasis and
+    // adaptive gain control are skipped
+    if(p->pitch_gain > 0.5 && !overflow) {
+        float excitation_temp[AMR_SUBFRAME_SIZE];
+        float pitch_factor = (p->cur_frame_mode == MODE_122 ? 0.25 : 0.5)*p->beta*p->pitch_gain;
+        float eta, temp1 = 0.0, temp2 = 0.0;
+
+        for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+            // emphasise pitch vector contribution
+            excitation_temp[i] = excitation[i] + pitch_factor*p->pitch_vector[i];
+            // find gain scale
+            temp1 +=      excitation[i]*excitation[i];
+            temp2 += excitation_temp[i]*excitation_temp[i];
+        }
+
+        // adaptive gain control by gain scaling
+        eta = sqrt(temp1/temp2);
+        for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+            excitation[i] = eta*excitation_temp[i];
+        }
+    }
+
+    for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+        float sample_temp = 0.0;
+        for(j=0; j<LP_FILTER_ORDER; j++) {
+            sample_temp -= lpc[j]*samples[i-j];
+        }
+        samples[i] = excitation[i] + sample_temp;
+    }
+
+    // Check for overflows
+    for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+        if(FFABS(samples[i])>1.0)
+            synthesis(excitation, lpc, samples, 1);
+    }
+}
+
+/*** end of synthesis functions ***/
+
+
 static int amrnb_decode_frame(AVCodecContext *avctx,
         void *data, int *data_size, uint8_t *buf, int buf_size) {
 
@@ -1114,6 +1194,18 @@ static int amrnb_decode_frame(AVCodecCon
 
 /*** end of pre-processing ***/
 
+/*** synthesis ***/
+
+        synthesis(p, p->excitation, p->lpc[subframe], p->samples_in, 0);
+
+/*** end of synthesis ***/
+
+        // convert float samples to 16-bit integer
+        for(i=0; i<AMR_SUBFRAME_SIZE; i++) {
+            p->samples_in[i] += p->add_bias;
+        }
+        p->dsp.float_to_int16(p->samples_out, p->samples_in, AMR_SUBFRAME_SIZE);
+
     }
 
     /* Report how many samples we got */
@@ -1146,3 +1238,4 @@ AVCodec amrnb_decoder =
     .close = amrnb_decode_close,
     .decode = amrnb_decode_frame,
 };
+



More information about the FFmpeg-soc mailing list