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
29
39
41 {
45 return 0;
46 }
47
48
50 {
53
66
68
69 return 0;
70 }
71
72
73 /**
74 * Quantize a value by searching a sorted table for the element with the
75 * nearest value
76 *
77 * @param value value to quantize
78 * @param table array containing the quantization table
79 * @param size size of the quantization table
80 * @return index of the quantization table corresponding to the element with the
81 * nearest value
82 */
84 {
85 unsigned int low = 0,
high =
size - 1;
86
87 while (1) {
90
95 } else {
97 }
98 }
99 }
100
101
102 /**
103 * Orthogonalize a vector to another vector
104 *
105 * @param v vector to orthogonalize
106 * @param u vector against which orthogonalization is performed
107 */
109 {
111 float num = 0, den = 0;
112
116 }
117 num /= den;
120 }
121
122
123 /**
124 * Calculate match score and gain of an LPC-filtered vector with respect to
125 * input data, possibly orthogonalizing it to up to two other vectors.
126 *
127 * @param work array used to calculate the filtered vector
128 * @param coefs coefficients of the LPC filter
129 * @param vect original vector
130 * @param ortho1 first vector against which orthogonalization is performed
131 * @param ortho2 second vector against which orthogonalization is performed
132 * @param data input data
133 * @param score pointer to variable where match score is returned
134 * @param gain pointer to variable where gain is returned
135 */
137 const float *ortho1, const float *ortho2,
138 const float *
data,
float *score,
float *gain)
139 {
142
144 if (ortho1)
146 if (ortho2)
152 }
154 *score = 0;
155 return;
156 }
159 }
160
161
162 /**
163 * Create a vector from the adaptive codebook at a given lag value
164 *
165 * @param vect array where vector is stored
166 * @param cb adaptive codebook
167 * @param lag lag value
168 */
170 {
172
178 vect[lag +
i] =
cb[
i];
179 }
180
181
182 /**
183 * Search the adaptive codebook for the best entry and gain and remove its
184 * contribution from input data
185 *
186 * @param adapt_cb array from which the adaptive codebook is extracted
187 * @param work array used to calculate LPC-filtered vectors
188 * @param coefs coefficients of the LPC filter
189 * @param data input data
190 * @return index of the best entry of the adaptive codebook
191 */
193 const float *coefs,
float *
data)
194 {
196 float score, gain, best_score,
av_uninit(best_gain);
198
199 gain = best_score = 0;
203 if (score > best_score) {
204 best_score = score;
206 best_gain = gain;
207 }
208 }
209 if (!best_score)
210 return 0;
211
212 /**
213 * Re-calculate the filtered vector from the vector with maximum match score
214 * and remove its contribution from input data.
215 */
221 }
222
223
224 /**
225 * Find the best vector of a fixed codebook by applying an LPC filter to
226 * codebook entries, possibly orthogonalizing them to up to two other vectors
227 * and matching the results with input data.
228 *
229 * @param work array used to calculate the filtered vectors
230 * @param coefs coefficients of the LPC filter
231 * @param cb fixed codebook
232 * @param ortho1 first vector against which orthogonalization is performed
233 * @param ortho2 second vector against which orthogonalization is performed
234 * @param data input data
235 * @param idx pointer to variable where the index of the best codebook entry is
236 * returned
237 * @param gain pointer to variable where the gain of the best codebook entry is
238 * returned
239 */
242 const float *ortho2,
float *
data,
int *idx,
243 float *gain)
244 {
246 float g, score, best_score;
248
249 *idx = *gain = best_score = 0;
254 if (score > best_score) {
255 best_score = score;
258 }
259 }
260 }
261
262
263 /**
264 * Search the two fixed codebooks for the best entry and gain
265 *
266 * @param work array used to calculate LPC-filtered vectors
267 * @param coefs coefficients of the LPC filter
268 * @param data input data
269 * @param cba_idx index of the best entry of the adaptive codebook
270 * @param cb1_idx pointer to variable where the index of the best entry of the
271 * first fixed codebook is returned
272 * @param cb2_idx pointer to variable where the index of the best entry of the
273 * second fixed codebook is returned
274 */
276 int cba_idx, int *cb1_idx, int *cb2_idx)
277 {
279 float gain;
282
283 /**
284 * The filtered vector from the adaptive codebook can be retrieved from
285 * work, because this function is called just after adaptive_cb_search().
286 */
287 if (cba_idx)
288 memcpy(cba_vect,
work,
sizeof(cba_vect));
289
291 data, cb1_idx, &gain);
292
293 /**
294 * Re-calculate the filtered vector from the vector with maximum match score
295 * and remove its contribution from input data.
296 */
297 if (gain) {
301 if (cba_idx)
305 memcpy(cb1_vect,
work,
sizeof(cb1_vect));
306 ortho_cb1 = 1;
307 } else
308 ortho_cb1 = 0;
309
311 ortho_cb1 ? cb1_vect :
NULL,
data, cb2_idx, &gain);
312 }
313
314
315 /**
316 * Encode a subblock of the current frame
317 *
318 * @param ractx encoder context
319 * @param sblock_data input data of the subblock
320 * @param lpc_coefs coefficients of the LPC filter
321 * @param rms RMS of the reflection coefficients
322 * @param pb pointer to PutBitContext of the current frame
323 */
325 const int16_t *sblock_data,
326 const int16_t *lpc_coefs, unsigned int rms,
328 {
332 int cba_idx, cb1_idx, cb2_idx, gain;
334 unsigned m[3];
336 float error, best_error;
337
340 coefs[
i] = lpc_coefs[
i] * (1/4096.0);
341 }
342
343 /**
344 * Calculate the zero-input response of the LPC filter and subtract it from
345 * input data.
346 */
352 }
353
354 /**
355 * Codebook search is performed without taking into account the contribution
356 * of the previous subblock, since it has been just subtracted from input
357 * data.
358 */
360
363 if (cba_idx) {
364 /**
365 * The filtered vector from the adaptive codebook can be retrieved from
366 * work, see implementation of adaptive_cb_search().
367 */
369
372 }
377 }
386 best_error = FLT_MAX;
387 gain = 0;
388 for (n = 0; n < 256; n++) {
390 (1/4096.0);
392 (1/4096.0);
394 if (cba_idx) {
396 (1/4096.0);
401 (
data[
i] - sblock_data[
i]);
402 }
403 } else {
407 (
data[
i] - sblock_data[
i]);
408 }
409 }
410 if (
error < best_error) {
412 gain = n;
413 }
414 }
420 gain);
421 }
422
423
426 {
427 static const uint8_t
sizes[
LPC_ORDER] = {64, 32, 32, 16, 16, 8, 8, 8, 8, 4};
428 static const uint8_t bit_sizes[
LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2};
435 int lpc_refl[
LPC_ORDER];
/**< reflection coefficients of the frame */
436 unsigned int refl_rms[
NBLOCKS];
/**< RMS of the reflection coefficients */
438 int energy = 0;
440
442 return 0;
443
446
447 /**
448 * Since the LPC coefficients are calculated on a frame centered over the
449 * fourth subframe, to encode a given frame, data from the next frame is
450 * needed. In each call to this function, the previous frame (whose data are
451 * saved in the encoder context) is encoded, and data from the current frame
452 * are saved in the encoder context to be used in the next function call.
453 */
456 energy += (lpc_data[
i] * lpc_data[
i]) >> 4;
457 }
459 int j;
462 energy += (lpc_data[
i] * lpc_data[
i]) >> 4;
463 }
464 }
468 32)];
469
476
477 /**
478 * TODO: apply perceptual weighting of the input speech through bandwidth
479 * expansion of the LPC filter.
480 */
481
483 /**
484 * The filter is unstable: use the coefficients of the previous frame.
485 */
488 /* the filter is still unstable. set reflection coeffs to zero. */
489 memset(lpc_refl, 0, sizeof(lpc_refl));
490 }
491 }
497 }
501 refl_rms[1] =
ff_interp(ractx, block_coefs[1], 2,
502 energy <= ractx->old_energy,
504 refl_rms[2] =
ff_interp(ractx, block_coefs[2], 3, 0, energy);
510 block_coefs[
i], refl_rms[
i], &pb);
515
516 /* copy input samples to current block for processing in next call */
519 for (;
i <
frame->nb_samples;
i++)
521
524 } else
528
529 /* Get the next frame pts/duration */
532
533 *got_packet_ptr = 1;
534 return 0;
535 }
536
537
539 .
p.
name =
"real_144",
552 };