Libav 0.7.1
|
00001 /* 00002 * various filters for ACELP-based codecs 00003 * 00004 * Copyright (c) 2008 Vladimir Voroshilov 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * Libav is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with Libav; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include <inttypes.h> 00024 00025 #include "avcodec.h" 00026 #include "acelp_filters.h" 00027 00028 const int16_t ff_acelp_interp_filter[61] = { /* (0.15) */ 00029 29443, 28346, 25207, 20449, 14701, 8693, 00030 3143, -1352, -4402, -5865, -5850, -4673, 00031 -2783, -672, 1211, 2536, 3130, 2991, 00032 2259, 1170, 0, -1001, -1652, -1868, 00033 -1666, -1147, -464, 218, 756, 1060, 00034 1099, 904, 550, 135, -245, -514, 00035 -634, -602, -451, -231, 0, 191, 00036 308, 340, 296, 198, 78, -36, 00037 -120, -163, -165, -132, -79, -19, 00038 34, 73, 91, 89, 70, 38, 00039 0, 00040 }; 00041 00042 void ff_acelp_interpolate(int16_t* out, const int16_t* in, 00043 const int16_t* filter_coeffs, int precision, 00044 int frac_pos, int filter_length, int length) 00045 { 00046 int n, i; 00047 00048 assert(frac_pos >= 0 && frac_pos < precision); 00049 00050 for (n = 0; n < length; n++) { 00051 int idx = 0; 00052 int v = 0x4000; 00053 00054 for (i = 0; i < filter_length;) { 00055 00056 /* The reference G.729 and AMR fixed point code performs clipping after 00057 each of the two following accumulations. 00058 Since clipping affects only the synthetic OVERFLOW test without 00059 causing an int type overflow, it was moved outside the loop. */ 00060 00061 /* R(x):=ac_v[-k+x] 00062 v += R(n-i)*ff_acelp_interp_filter(t+6i) 00063 v += R(n+i+1)*ff_acelp_interp_filter(6-t+6i) */ 00064 00065 v += in[n + i] * filter_coeffs[idx + frac_pos]; 00066 idx += precision; 00067 i++; 00068 v += in[n - i] * filter_coeffs[idx - frac_pos]; 00069 } 00070 if (av_clip_int16(v >> 15) != (v >> 15)) 00071 av_log(NULL, AV_LOG_WARNING, "overflow that would need cliping in ff_acelp_interpolate()\n"); 00072 out[n] = v >> 15; 00073 } 00074 } 00075 00076 void ff_acelp_interpolatef(float *out, const float *in, 00077 const float *filter_coeffs, int precision, 00078 int frac_pos, int filter_length, int length) 00079 { 00080 int n, i; 00081 00082 for (n = 0; n < length; n++) { 00083 int idx = 0; 00084 float v = 0; 00085 00086 for (i = 0; i < filter_length;) { 00087 v += in[n + i] * filter_coeffs[idx + frac_pos]; 00088 idx += precision; 00089 i++; 00090 v += in[n - i] * filter_coeffs[idx - frac_pos]; 00091 } 00092 out[n] = v; 00093 } 00094 } 00095 00096 00097 void ff_acelp_high_pass_filter(int16_t* out, int hpf_f[2], 00098 const int16_t* in, int length) 00099 { 00100 int i; 00101 int tmp; 00102 00103 for (i = 0; i < length; i++) { 00104 tmp = (hpf_f[0]* 15836LL) >> 13; 00105 tmp += (hpf_f[1]* -7667LL) >> 13; 00106 tmp += 7699 * (in[i] - 2*in[i-1] + in[i-2]); 00107 00108 /* With "+0x800" rounding, clipping is needed 00109 for ALGTHM and SPEECH tests. */ 00110 out[i] = av_clip_int16((tmp + 0x800) >> 12); 00111 00112 hpf_f[1] = hpf_f[0]; 00113 hpf_f[0] = tmp; 00114 } 00115 } 00116 00117 void ff_acelp_apply_order_2_transfer_function(float *out, const float *in, 00118 const float zero_coeffs[2], 00119 const float pole_coeffs[2], 00120 float gain, float mem[2], int n) 00121 { 00122 int i; 00123 float tmp; 00124 00125 for (i = 0; i < n; i++) { 00126 tmp = gain * in[i] - pole_coeffs[0] * mem[0] - pole_coeffs[1] * mem[1]; 00127 out[i] = tmp + zero_coeffs[0] * mem[0] + zero_coeffs[1] * mem[1]; 00128 00129 mem[1] = mem[0]; 00130 mem[0] = tmp; 00131 } 00132 } 00133 00134 void ff_tilt_compensation(float *mem, float tilt, float *samples, int size) 00135 { 00136 float new_tilt_mem = samples[size - 1]; 00137 int i; 00138 00139 for (i = size - 1; i > 0; i--) 00140 samples[i] -= tilt * samples[i - 1]; 00141 00142 samples[0] -= tilt * *mem; 00143 *mem = new_tilt_mem; 00144 } 00145