ffmpeg / libavcodec / qcelpdec.c @ 39ded680
History  View  Annotate  Download (9.73 KB)
1 
/*


2 
* QCELP decoder

3 
* Copyright (c) 2007 Reynaldo H. Verdejo Pinochet

4 
*

5 
* This file is part of FFmpeg.

6 
*

7 
* FFmpeg is free software; you can redistribute it and/or

8 
* modify it under the terms of the GNU Lesser General Public

9 
* License as published by the Free Software Foundation; either

10 
* version 2.1 of the License, or (at your option) any later version.

11 
*

12 
* FFmpeg is distributed in the hope that it will be useful,

13 
* but WITHOUT ANY WARRANTY; without even the implied warranty of

14 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

15 
* Lesser General Public License for more details.

16 
*

17 
* You should have received a copy of the GNU Lesser General Public

18 
* License along with FFmpeg; if not, write to the Free Software

19 
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 021101301 USA

20 
*/

21 
/**

22 
* @file qcelpdec.c

23 
* QCELP decoder

24 
* @author Reynaldo H. Verdejo Pinochet

25 
*/

26  
27 
#include <stddef.h> 
28  
29 
#include "avcodec.h" 
30 
#include "bitstream.h" 
31  
32 
#include "qcelp.h" 
33 
#include "qcelpdata.h" 
34  
35 
#include "celp_math.h" 
36 
#include "celp_filters.h" 
37  
38 
#undef NDEBUG

39 
#include <assert.h> 
40  
41 
static void weighted_vector_sumf(float *out, 
42 
const float *in_a, 
43 
const float *in_b, 
44 
float weight_coeff_a,

45 
float weight_coeff_b,

46 
int length) {

47 
int i;

48  
49 
for (i = 0; i < length; i++) 
50 
out[i] = weight_coeff_a * in_a[i] 
51 
+ weight_coeff_b * in_b[i]; 
52 
} 
53  
54 
/**

55 
* Initialize the speech codec according to the specification.

56 
*

57 
* TIA/EIA/IS733 2.4.9

58 
*/

59 
static av_cold int qcelp_decode_init(AVCodecContext *avctx) { 
60 
QCELPContext *q = avctx>priv_data; 
61 
int i;

62  
63 
avctx>sample_fmt = SAMPLE_FMT_FLT; 
64  
65 
for (i = 0; i < 10; i++) 
66 
q>prev_lspf[i] = (i + 1) / 11.; 
67  
68 
return 0; 
69 
} 
70  
71 
/**

72 
* Computes the scaled codebook vector Cdn From INDEX and GAIN

73 
* for all rates.

74 
*

75 
* The specification lacks some information here.

76 
*

77 
* TIA/EIA/IS733 has an omission on the codebook index determination

78 
* formula for RATE_FULL and RATE_HALF frames at section 2.4.8.1.1. It says

79 
* you have to subtract the decoded index parameter from the given scaled

80 
* codebook vector index 'n' to get the desired circular codebook index, but

81 
* it does not mention that you have to clamp 'n' to [09] in order to get

82 
* RIcompliant results.

83 
*

84 
* The reason for this mistake seems to be the fact they forgot to mention you

85 
* have to do these calculations per codebook subframe and adjust given

86 
* equation values accordingly.

87 
*

88 
* @param q the context

89 
* @param gain array holding the 4 pitch subframe gain values

90 
* @param cdn_vector array for the generated scaled codebook vector

91 
*/

92 
static void compute_svector(const QCELPContext *q, 
93 
const float *gain, 
94 
float *cdn_vector) {

95 
int i, j, k;

96 
uint16_t cbseed, cindex; 
97 
float *rnd, tmp_gain, fir_filter_value;

98  
99 
switch (q>framerate) {

100 
case RATE_FULL:

101 
for (i = 0; i < 16; i++) { 
102 
tmp_gain = gain[i] * QCELP_RATE_FULL_CODEBOOK_RATIO; 
103 
cindex = q>cindex[i]; 
104 
for (j = 0; j < 10; j++) 
105 
*cdn_vector++ = tmp_gain * qcelp_rate_full_codebook[cindex++ & 127];

106 
} 
107 
break;

108 
case RATE_HALF:

109 
for (i = 0; i < 4; i++) { 
110 
tmp_gain = gain[i] * QCELP_RATE_HALF_CODEBOOK_RATIO; 
111 
cindex = q>cindex[i]; 
112 
for (j = 0; j < 40; j++) 
113 
*cdn_vector++ = tmp_gain * qcelp_rate_half_codebook[cindex++ & 127];

114 
} 
115 
break;

116 
case RATE_QUARTER:

117 
cbseed = (0x0003 & q>lspv[4])<<14  
118 
(0x003F & q>lspv[3])<< 8  
119 
(0x0060 & q>lspv[2])<< 1  
120 
(0x0007 & q>lspv[1])<< 3  
121 
(0x0038 & q>lspv[0])>> 3 ; 
122 
rnd = q>rnd_fir_filter_mem + 20;

123 
for (i = 0; i < 8; i++) { 
124 
tmp_gain = gain[i] * (QCELP_SQRT1887 / 32768.0); 
125 
for (k = 0; k < 20; k++) { 
126 
cbseed = 521 * cbseed + 259; 
127 
*rnd = (int16_t)cbseed; 
128  
129 
// FIR filter

130 
fir_filter_value = 0.0; 
131 
for (j = 0; j < 10; j++) 
132 
fir_filter_value += qcelp_rnd_fir_coefs[j ] * (rnd[j ] + rnd[20+j]);

133 
fir_filter_value += qcelp_rnd_fir_coefs[10] * rnd[10]; 
134  
135 
*cdn_vector++ = tmp_gain * fir_filter_value; 
136 
rnd++; 
137 
} 
138 
} 
139 
memcpy(q>rnd_fir_filter_mem, q>rnd_fir_filter_mem + 160, 20 * sizeof(float)); 
140 
break;

141 
case RATE_OCTAVE:

142 
cbseed = q>first16bits; 
143 
for (i = 0; i < 8; i++) { 
144 
tmp_gain = gain[i] * (QCELP_SQRT1887 / 32768.0); 
145 
for (j = 0; j < 20; j++) { 
146 
cbseed = 521 * cbseed + 259; 
147 
*cdn_vector++ = tmp_gain * (int16_t)cbseed; 
148 
} 
149 
} 
150 
break;

151 
case I_F_Q:

152 
cbseed = 44; // random codebook index 
153 
for (i = 0; i < 4; i++) { 
154 
tmp_gain = gain[i] * QCELP_RATE_FULL_CODEBOOK_RATIO; 
155 
for (j = 0; j < 40; j++) 
156 
*cdn_vector++ = tmp_gain * qcelp_rate_full_codebook[cbseed++ & 127];

157 
} 
158 
break;

159 
} 
160 
} 
161  
162 
/**

163 
* Apply generic gain control.

164 
*

165 
* @param v_out output vector

166 
* @param v_in gaincontrolled vector

167 
* @param v_ref vector to control gain of

168 
*

169 
* FIXME: If v_ref is a zero vector, it energy is zero

170 
* and the behavior of the gain control is

171 
* undefined in the specs.

172 
*

173 
* TIA/EIA/IS733 2.4.8.32/3/4/5, 2.4.8.6

174 
*/

175 
static void apply_gain_ctrl(float *v_out, 
176 
const float *v_ref, 
177 
const float *v_in) { 
178 
int i, j, len;

179 
float scalefactor;

180  
181 
for (i = 0, j = 0; i < 4; i++) { 
182 
scalefactor = ff_dot_productf(v_in + j, v_in + j, 40);

183 
if (scalefactor)

184 
scalefactor = sqrt(ff_dot_productf(v_ref + j, v_ref + j, 40) / scalefactor);

185 
else

186 
av_log_missing_feature(NULL, "Zero energy for gain control", 1); 
187 
for (len = j + 40; j < len; j++) 
188 
v_out[j] = scalefactor * v_in[j]; 
189 
} 
190 
} 
191  
192 
/**

193 
* Apply filter in pitchsubframe steps.

194 
*

195 
* @param memory buffer for the previous state of the filter

196 
*  must be able to contain 303 elements

197 
*  the 143 first elements are from the previous state

198 
*  the next 160 are for output

199 
* @param v_in input filter vector

200 
* @param gain persubframe gain array, each element is between 0.0 and 2.0

201 
* @param lag persubframe lag array, each element is

202 
*  between 16 and 143 if its corresponding pfrac is 0,

203 
*  between 16 and 139 otherwise

204 
* @param pfrac persubframe boolean array, 1 if the lag is fractional, 0 otherwise

205 
*

206 
* @return filter output vector

207 
*/

208 
static const float *do_pitchfilter(float memory[303], 
209 
const float v_in[160], 
210 
const float gain[4], 
211 
const uint8_t *lag,

212 
const uint8_t pfrac[4]) { 
213 
int i, j;

214 
float *v_lag, *v_out;

215 
const float *v_len; 
216  
217 
v_out = memory + 143; // Output vector starts at memory[143]. 
218  
219 
for (i = 0; i < 4; i++) 
220 
if (gain[i]) {

221 
v_lag = memory + 143 + 40 * i  lag[i]; 
222 
for (v_len = v_in + 40; v_in < v_len; v_in++) { 
223 
if (pfrac[i]) { // If it is a fractional lag... 
224 
for (j = 0, *v_out = 0.; j < 4; j++) 
225 
*v_out += qcelp_hammsinc_table[j] * (v_lag[j4] + v_lag[3j]); 
226 
} else

227 
*v_out = *v_lag; 
228  
229 
*v_out = *v_in + gain[i] * *v_out; 
230  
231 
v_lag++; 
232 
v_out++; 
233 
} 
234 
} else {

235 
memcpy(v_out, v_in, 40 * sizeof(float)); 
236 
v_in += 40;

237 
v_out += 40;

238 
} 
239  
240 
memmove(memory, memory + 160, 143 * sizeof(float)); 
241 
return memory + 143; 
242 
} 
243  
244 
/**

245 
* Interpolates LSP frequencies and computes LPC coefficients

246 
* for a given framerate & pitch subframe.

247 
*

248 
* TIA/EIA/IS733 2.4.3.3.4

249 
*

250 
* @param q the context

251 
* @param curr_lspf LSP frequencies vector of the current frame

252 
* @param lpc float vector for the resulting LPC

253 
* @param subframe_num frame number in decoded stream

254 
*/

255 
void interpolate_lpc(QCELPContext *q,

256 
const float *curr_lspf, 
257 
float *lpc,

258 
const int subframe_num) { 
259 
float interpolated_lspf[10]; 
260 
float weight;

261  
262 
if (q>framerate >= RATE_QUARTER) {

263 
weight = 0.25 * (subframe_num + 1); 
264 
} else if (q>framerate == RATE_OCTAVE && !subframe_num) { 
265 
weight = 0.625; 
266 
} else {

267 
weight = 1.0; 
268 
} 
269  
270 
if (weight != 1.0) { 
271 
weighted_vector_sumf(interpolated_lspf, curr_lspf, q>prev_lspf, weight, 1.0  weight, 10); 
272 
qcelp_lspf2lpc(interpolated_lspf, lpc); 
273 
} else if (q>framerate >= RATE_QUARTER  (q>framerate == I_F_Q && !subframe_num)) 
274 
qcelp_lspf2lpc(curr_lspf, lpc); 
275 
} 
276  
277 
static int buf_size2framerate(const int buf_size) { 
278 
switch (buf_size) {

279 
case 35: 
280 
return RATE_FULL;

281 
case 17: 
282 
return RATE_HALF;

283 
case 8: 
284 
return RATE_QUARTER;

285 
case 4: 
286 
return RATE_OCTAVE;

287 
case 1: 
288 
return SILENCE;

289 
} 
290 
return 1; 
291 
} 
292  
293 
static void warn_insufficient_frame_quality(AVCodecContext *avctx, 
294 
const char *message) { 
295 
av_log(avctx, AV_LOG_WARNING, "Frame #%d, IFQ: %s\n", avctx>frame_number, message);

296 
} 
297  
298 
AVCodec qcelp_decoder = 
299 
{ 
300 
.name = "qcelp",

301 
.type = CODEC_TYPE_AUDIO, 
302 
.id = CODEC_ID_QCELP, 
303 
.init = qcelp_decode_init, 
304 
.decode = qcelp_decode_frame, 
305 
.priv_data_size = sizeof(QCELPContext),

306 
.long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"),

307 
}; 