1 /*
2 * Real Audio 1.0 (14.4K) encoder
3 * Copyright (c) 2010 Francesco Lavra <francescolavra@interfree.it>
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 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Real Audio 1.0 (14.4K) encoder
25 * @author Francesco Lavra <francescolavra@interfree.it>
26 */
27
28 #include <float.h>
29
36
37
39 {
43 return 0;
44 }
45
46
48 {
51
55 return -1;
56 }
66 if (ret < 0)
67 goto error;
68
70
71 return 0;
72 error:
75 }
76
77
78 /**
79 * Quantize a value by searching a sorted table for the element with the
80 * nearest value
81 *
82 * @param value value to quantize
83 * @param table array containing the quantization table
84 * @param size size of the quantization table
85 * @return index of the quantization table corresponding to the element with the
86 * nearest value
87 */
89 {
90 unsigned int low = 0, high = size - 1;
91
92 while (1) {
93 int index = (low + high) >> 1;
95
96 if (index == low)
97 return table[high] + error > value ? low : high;
98 if (error > 0) {
100 } else {
102 }
103 }
104 }
105
106
107 /**
108 * Orthogonalize a vector to another vector
109 *
110 * @param v vector to orthogonalize
111 * @param u vector against which orthogonalization is performed
112 */
114 {
115 int i;
116 float num = 0, den = 0;
117
119 num += v[i] * u[i];
120 den += u[i] * u[i];
121 }
122 num /= den;
124 v[i] -= num * u[i];
125 }
126
127
128 /**
129 * Calculate match score and gain of an LPC-filtered vector with respect to
130 * input data, possibly othogonalizing it to up to 2 other vectors
131 *
132 * @param work array used to calculate the filtered vector
133 * @param coefs coefficients of the LPC filter
134 * @param vect original vector
135 * @param ortho1 first vector against which orthogonalization is performed
136 * @param ortho2 second vector against which orthogonalization is performed
137 * @param data input data
138 * @param score pointer to variable where match score is returned
139 * @param gain pointer to variable where gain is returned
140 */
142 const float *ortho1, const float *ortho2,
143 const float *
data,
float *score,
float *gain)
144 {
146 int i;
147
149 if (ortho1)
151 if (ortho2)
153 c = g = 0;
155 g += work[i] * work[i];
156 c += data[i] * work[i];
157 }
158 if (c <= 0) {
159 *score = 0;
160 return;
161 }
164 }
165
166
167 /**
168 * Create a vector from the adaptive codebook at a given lag value
169 *
170 * @param vect array where vector is stored
171 * @param cb adaptive codebook
172 * @param lag lag value
173 */
175 {
176 int i;
177
180 vect[i] = cb[i];
183 vect[lag + i] = cb[i];
184 }
185
186
187 /**
188 * Search the adaptive codebook for the best entry and gain and remove its
189 * contribution from input data
190 *
191 * @param adapt_cb array from which the adaptive codebook is extracted
192 * @param work array used to calculate LPC-filtered vectors
193 * @param coefs coefficients of the LPC filter
194 * @param data input data
195 * @return index of the best entry of the adaptive codebook
196 */
198 const float *coefs,
float *
data)
199 {
201 float score, gain, best_score,
av_uninit(best_gain);
203
204 gain = best_score = 0;
208 if (score > best_score) {
209 best_score = score;
210 best_vect = i;
211 best_gain = gain;
212 }
213 }
214 if (!best_score)
215 return 0;
216
217 /**
218 * Re-calculate the filtered vector from the vector with maximum match score
219 * and remove its contribution from input data.
220 */
224 data[i] -= best_gain * work[i];
225 return best_vect - BLOCKSIZE / 2 + 1;
226 }
227
228
229 /**
230 * Find the best vector of a fixed codebook by applying an LPC filter to
231 * codebook entries, possibly othogonalizing them to up to 2 other vectors and
232 * matching the results with input data
233 *
234 * @param work array used to calculate the filtered vectors
235 * @param coefs coefficients of the LPC filter
236 * @param cb fixed codebook
237 * @param ortho1 first vector against which orthogonalization is performed
238 * @param ortho2 second vector against which orthogonalization is performed
239 * @param data input data
240 * @param idx pointer to variable where the index of the best codebook entry is
241 * returned
242 * @param gain pointer to variable where the gain of the best codebook entry is
243 * returned
244 */
247 const float *ortho2,
float *
data,
int *idx,
248 float *gain)
249 {
250 int i, j;
251 float g, score, best_score;
253
254 *idx = *gain = best_score = 0;
259 if (score > best_score) {
260 best_score = score;
261 *idx = i;
263 }
264 }
265 }
266
267
268 /**
269 * Search the two fixed codebooks for the best entry and gain
270 *
271 * @param work array used to calculate LPC-filtered vectors
272 * @param coefs coefficients of the LPC filter
273 * @param data input data
274 * @param cba_idx index of the best entry of the adaptive codebook
275 * @param cb1_idx pointer to variable where the index of the best entry of the
276 * first fixed codebook is returned
277 * @param cb2_idx pointer to variable where the index of the best entry of the
278 * second fixed codebook is returned
279 */
281 int cba_idx, int *cb1_idx, int *cb2_idx)
282 {
283 int i, ortho_cb1;
284 float gain;
287
288 /**
289 * The filtered vector from the adaptive codebook can be retrieved from
290 * work, because this function is called just after adaptive_cb_search().
291 */
292 if (cba_idx)
293 memcpy(cba_vect, work, sizeof(cba_vect));
294
296 data, cb1_idx, &gain);
297
298 /**
299 * Re-calculate the filtered vector from the vector with maximum match score
300 * and remove its contribution from input data.
301 */
302 if (gain) {
306 if (cba_idx)
309 data[i] -= gain * work[i];
310 memcpy(cb1_vect, work, sizeof(cb1_vect));
311 ortho_cb1 = 1;
312 } else
313 ortho_cb1 = 0;
314
316 ortho_cb1 ? cb1_vect : NULL, data, cb2_idx, &gain);
317 }
318
319
320 /**
321 * Encode a subblock of the current frame
322 *
323 * @param ractx encoder context
324 * @param sblock_data input data of the subblock
325 * @param lpc_coefs coefficients of the LPC filter
326 * @param rms RMS of the reflection coefficients
327 * @param pb pointer to PutBitContext of the current frame
328 */
330 const int16_t *sblock_data,
331 const int16_t *lpc_coefs, unsigned int rms,
333 {
338 int cba_idx, cb1_idx, cb2_idx, gain;
342 float error, best_error;
343
346 coefs[i] = lpc_coefs[i] * (1/4096.0);
347 }
348
349 /**
350 * Calculate the zero-input response of the LPC filter and subtract it from
351 * input data.
352 */
354 LPC_ORDER);
356 zero[i] = work[LPC_ORDER + i];
357 data[i] = sblock_data[i] - zero[i];
358 }
359
360 /**
361 * Codebook search is performed without taking into account the contribution
362 * of the previous subblock, since it has been just subtracted from input
363 * data.
364 */
365 memset(work, 0, LPC_ORDER * sizeof(*work));
366
368 data);
369 if (cba_idx) {
370 /**
371 * The filtered vector from the adaptive codebook can be retrieved from
372 * work, see implementation of adaptive_cb_search().
373 */
374 memcpy(cba, work + LPC_ORDER, sizeof(cba));
375
377 m[0] = (
ff_irms(cba_vect) * rms) >> 12;
378 }
379 fixed_cb_search(work + LPC_ORDER, coefs, data, cba_idx, &cb1_idx, &cb2_idx);
383 }
385 LPC_ORDER);
386 memcpy(cb1, work + LPC_ORDER, sizeof(cb1));
389 LPC_ORDER);
390 memcpy(cb2, work + LPC_ORDER, sizeof(cb2));
392 best_error = FLT_MAX;
393 gain = 0;
394 for (n = 0; n < 256; n++) {
396 (1/4096.0);
398 (1/4096.0);
399 error = 0;
400 if (cba_idx) {
402 (1/4096.0);
404 data[i] = zero[i] + g[0] * cba[i] + g[1] * cb1[i] +
405 g[2] * cb2[i];
406 error += (data[i] - sblock_data[i]) *
407 (data[i] - sblock_data[i]);
408 }
409 } else {
411 data[i] = zero[i] + g[1] * cb1[i] + g[2] * cb2[i];
412 error += (data[i] - sblock_data[i]) *
413 (data[i] - sblock_data[i]);
414 }
415 }
416 if (error < best_error) {
417 best_error = error;
419 }
420 }
426 gain);
427 }
428
429
432 {
441 int lpc_refl[
LPC_ORDER];
/**< reflection coefficients of the frame */
442 unsigned int refl_rms[
NBLOCKS];
/**< RMS of the reflection coefficients */
443 const int16_t *samples = frame ? (
const int16_t *)frame->
data[0] : NULL;
444 int energy = 0;
446
448 return 0;
449
452
453 /**
454 * Since the LPC coefficients are calculated on a frame centered over the
455 * fourth subframe, to encode a given frame, data from the next frame is
456 * needed. In each call to this function, the previous frame (whose data are
457 * saved in the encoder context) is encoded, and data from the current frame
458 * are saved in the encoder context to be used in the next function call.
459 */
462 energy += (lpc_data[i] * lpc_data[i]) >> 4;
463 }
464 if (frame) {
465 int j;
467 lpc_data[i] = samples[j] >> 2;
468 energy += (lpc_data[i] * lpc_data[i]) >> 4;
469 }
470 }
472 memset(&lpc_data[i], 0, (
NBLOCKS * BLOCKSIZE - i) *
sizeof(*lpc_data));
474 32)];
475
480 block_coefs[
NBLOCKS - 1][i] = -(lpc_coefs[LPC_ORDER - 1][i] <<
481 (12 - shift[LPC_ORDER - 1]));
482
483 /**
484 * TODO: apply perceptual weighting of the input speech through bandwidth
485 * expansion of the LPC filter.
486 */
487
489 /**
490 * The filter is unstable: use the coefficients of the previous frame.
491 */
494 /* the filter is still unstable. set reflection coeffs to zero. */
495 memset(lpc_refl, 0, sizeof(lpc_refl));
496 }
497 }
503 }
507 refl_rms[1] =
ff_interp(ractx, block_coefs[1], 2,
508 energy <= ractx->old_energy,
510 refl_rms[2] =
ff_interp(ractx, block_coefs[2], 3, 0, energy);
516 block_coefs[i], refl_rms[i], &pb);
521
522 /* copy input samples to current block for processing in next call */
523 i = 0;
524 if (frame) {
527
530 } else
533 (NBLOCKS * BLOCKSIZE - i) *
sizeof(*ractx->
curr_block));
534
535 /* Get the next frame pts/duration */
538
540 *got_packet_ptr = 1;
541 return 0;
542 }
543
544
556 .supported_samplerates = (const int[]){ 8000, 0 },
558 };