2 * Real Audio 1.0 (14.4K) encoder
3 * Copyright (c) 2010 Francesco Lavra <francescolavra@interfree.it>
5 * This file is part of FFmpeg.
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.
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.
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
24 * Real Audio 1.0 (14.4K) encoder
25 * @author Francesco Lavra <francescolavra@interfree.it>
30 #include "libavutil/channel_layout.h"
32 #include "audio_frame_queue.h"
33 #include "celp_filters.h"
34 #include "codec_internal.h"
40 static av_cold
int ra144_encode_close(AVCodecContext
*avctx
)
42 RA144Context
*ractx
= avctx
->priv_data
;
43 ff_lpc_end(&ractx
->lpc_ctx
);
44 ff_af_queue_close(&ractx
->afq
);
49 static av_cold
int ra144_encode_init(AVCodecContext
* avctx
)
54 avctx
->frame_size
= NBLOCKS
* BLOCKSIZE
;
55 avctx
->initial_padding
= avctx
->frame_size
;
56 avctx
->bit_rate
= 8000;
57 ractx
= avctx
->priv_data
;
58 ractx
->lpc_coef
[0] = ractx
->lpc_tables
[0];
59 ractx
->lpc_coef
[1] = ractx
->lpc_tables
[1];
61 ff_audiodsp_init(&ractx
->adsp
);
62 ret
= ff_lpc_init(&ractx
->lpc_ctx
, avctx
->frame_size
, LPC_ORDER
,
63 FF_LPC_TYPE_LEVINSON
);
67 ff_af_queue_init(avctx
, &ractx
->afq
);
74 * Quantize a value by searching a sorted table for the element with the
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
83 static int quantize(int value
, const int16_t *table
, unsigned int size
)
85 unsigned int low
= 0, high
= size
- 1;
88 int index
= (low
+ high
) >> 1;
89 int error
= table
[index
] - value
;
92 return table
[high
] + error
> value
? low
: high
;
103 * Orthogonalize a vector to another vector
105 * @param v vector to orthogonalize
106 * @param u vector against which orthogonalization is performed
108 static void orthogonalize(float *v
, const float *u
)
111 float num
= 0, den
= 0;
113 for (i
= 0; i
< BLOCKSIZE
; i
++) {
118 for (i
= 0; i
< BLOCKSIZE
; i
++)
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.
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
136 static void get_match_score(float *work
, const float *coefs
, float *vect
,
137 const float *ortho1
, const float *ortho2
,
138 const float *data
, float *score
, float *gain
)
143 ff_celp_lp_synthesis_filterf(work
, coefs
, vect
, BLOCKSIZE
, LPC_ORDER
);
145 orthogonalize(work
, ortho1
);
147 orthogonalize(work
, ortho2
);
149 for (i
= 0; i
< BLOCKSIZE
; i
++) {
150 g
+= work
[i
] * work
[i
];
151 c
+= data
[i
] * work
[i
];
163 * Create a vector from the adaptive codebook at a given lag value
165 * @param vect array where vector is stored
166 * @param cb adaptive codebook
167 * @param lag lag value
169 static void create_adapt_vect(float *vect
, const int16_t *cb
, int lag
)
173 cb
+= BUFFERSIZE
- lag
;
174 for (i
= 0; i
< FFMIN(BLOCKSIZE
, lag
); i
++)
177 for (i
= 0; i
< BLOCKSIZE
- lag
; i
++)
178 vect
[lag
+ i
] = cb
[i
];
183 * Search the adaptive codebook for the best entry and gain and remove its
184 * contribution from input data
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
192 static int adaptive_cb_search(const int16_t *adapt_cb
, float *work
,
193 const float *coefs
, float *data
)
195 int i
, av_uninit(best_vect
);
196 float score
, gain
, best_score
, av_uninit(best_gain
);
197 float exc
[BLOCKSIZE
];
199 gain
= best_score
= 0;
200 for (i
= BLOCKSIZE
/ 2; i
<= BUFFERSIZE
; i
++) {
201 create_adapt_vect(exc
, adapt_cb
, i
);
202 get_match_score(work
, coefs
, exc
, NULL
, NULL
, data
, &score
, &gain
);
203 if (score
> best_score
) {
213 * Re-calculate the filtered vector from the vector with maximum match score
214 * and remove its contribution from input data.
216 create_adapt_vect(exc
, adapt_cb
, best_vect
);
217 ff_celp_lp_synthesis_filterf(work
, coefs
, exc
, BLOCKSIZE
, LPC_ORDER
);
218 for (i
= 0; i
< BLOCKSIZE
; i
++)
219 data
[i
] -= best_gain
* work
[i
];
220 return best_vect
- BLOCKSIZE
/ 2 + 1;
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.
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
237 * @param gain pointer to variable where the gain of the best codebook entry is
240 static void find_best_vect(float *work
, const float *coefs
,
241 const int8_t cb
[][BLOCKSIZE
], const float *ortho1
,
242 const float *ortho2
, float *data
, int *idx
,
246 float g
, score
, best_score
;
247 float vect
[BLOCKSIZE
];
249 *idx
= *gain
= best_score
= 0;
250 for (i
= 0; i
< FIXED_CB_SIZE
; i
++) {
251 for (j
= 0; j
< BLOCKSIZE
; j
++)
253 get_match_score(work
, coefs
, vect
, ortho1
, ortho2
, data
, &score
, &g
);
254 if (score
> best_score
) {
264 * Search the two fixed codebooks for the best entry and gain
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
275 static void fixed_cb_search(float *work
, const float *coefs
, float *data
,
276 int cba_idx
, int *cb1_idx
, int *cb2_idx
)
280 float cba_vect
[BLOCKSIZE
], cb1_vect
[BLOCKSIZE
];
281 float vect
[BLOCKSIZE
];
284 * The filtered vector from the adaptive codebook can be retrieved from
285 * work, because this function is called just after adaptive_cb_search().
288 memcpy(cba_vect
, work
, sizeof(cba_vect
));
290 find_best_vect(work
, coefs
, ff_cb1_vects
, cba_idx
? cba_vect
: NULL
, NULL
,
291 data
, cb1_idx
, &gain
);
294 * Re-calculate the filtered vector from the vector with maximum match score
295 * and remove its contribution from input data.
298 for (i
= 0; i
< BLOCKSIZE
; i
++)
299 vect
[i
] = ff_cb1_vects
[*cb1_idx
][i
];
300 ff_celp_lp_synthesis_filterf(work
, coefs
, vect
, BLOCKSIZE
, LPC_ORDER
);
302 orthogonalize(work
, cba_vect
);
303 for (i
= 0; i
< BLOCKSIZE
; i
++)
304 data
[i
] -= gain
* work
[i
];
305 memcpy(cb1_vect
, work
, sizeof(cb1_vect
));
310 find_best_vect(work
, coefs
, ff_cb2_vects
, cba_idx
? cba_vect
: NULL
,
311 ortho_cb1
? cb1_vect
: NULL
, data
, cb2_idx
, &gain
);
316 * Encode a subblock of the current frame
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
324 static void ra144_encode_subblock(RA144Context
*ractx
,
325 const int16_t *sblock_data
,
326 const int16_t *lpc_coefs
, unsigned int rms
,
329 float data
[BLOCKSIZE
] = { 0 }, work
[LPC_ORDER
+ BLOCKSIZE
];
330 float coefs
[LPC_ORDER
];
331 float zero
[BLOCKSIZE
], cba
[BLOCKSIZE
], cb1
[BLOCKSIZE
], cb2
[BLOCKSIZE
];
332 int cba_idx
, cb1_idx
, cb2_idx
, gain
;
336 float error
, best_error
;
338 for (i
= 0; i
< LPC_ORDER
; i
++) {
339 work
[i
] = ractx
->curr_sblock
[BLOCKSIZE
+ i
];
340 coefs
[i
] = lpc_coefs
[i
] * (1/4096.0);
344 * Calculate the zero-input response of the LPC filter and subtract it from
347 ff_celp_lp_synthesis_filterf(work
+ LPC_ORDER
, coefs
, data
, BLOCKSIZE
,
349 for (i
= 0; i
< BLOCKSIZE
; i
++) {
350 zero
[i
] = work
[LPC_ORDER
+ i
];
351 data
[i
] = sblock_data
[i
] - zero
[i
];
355 * Codebook search is performed without taking into account the contribution
356 * of the previous subblock, since it has been just subtracted from input
359 memset(work
, 0, LPC_ORDER
* sizeof(*work
));
361 cba_idx
= adaptive_cb_search(ractx
->adapt_cb
, work
+ LPC_ORDER
, coefs
,
365 * The filtered vector from the adaptive codebook can be retrieved from
366 * work, see implementation of adaptive_cb_search().
368 memcpy(cba
, work
+ LPC_ORDER
, sizeof(cba
));
370 ff_copy_and_dup(ractx
->buffer_a
, ractx
->adapt_cb
, cba_idx
+ BLOCKSIZE
/ 2 - 1);
371 m
[0] = (ff_irms(&ractx
->adsp
, ractx
->buffer_a
) * rms
) >> 12;
373 fixed_cb_search(work
+ LPC_ORDER
, coefs
, data
, cba_idx
, &cb1_idx
, &cb2_idx
);
374 for (i
= 0; i
< BLOCKSIZE
; i
++) {
375 cb1
[i
] = ff_cb1_vects
[cb1_idx
][i
];
376 cb2
[i
] = ff_cb2_vects
[cb2_idx
][i
];
378 ff_celp_lp_synthesis_filterf(work
+ LPC_ORDER
, coefs
, cb1
, BLOCKSIZE
,
380 memcpy(cb1
, work
+ LPC_ORDER
, sizeof(cb1
));
381 m
[1] = (ff_cb1_base
[cb1_idx
] * rms
) >> 8;
382 ff_celp_lp_synthesis_filterf(work
+ LPC_ORDER
, coefs
, cb2
, BLOCKSIZE
,
384 memcpy(cb2
, work
+ LPC_ORDER
, sizeof(cb2
));
385 m
[2] = (ff_cb2_base
[cb2_idx
] * rms
) >> 8;
386 best_error
= FLT_MAX
;
388 for (n
= 0; n
< 256; n
++) {
389 g
[1] = ((ff_gain_val_tab
[n
][1] * m
[1]) >> ff_gain_exp_tab
[n
]) *
391 g
[2] = ((ff_gain_val_tab
[n
][2] * m
[2]) >> ff_gain_exp_tab
[n
]) *
395 g
[0] = ((ff_gain_val_tab
[n
][0] * m
[0]) >> ff_gain_exp_tab
[n
]) *
397 for (i
= 0; i
< BLOCKSIZE
; i
++) {
398 data
[i
] = zero
[i
] + g
[0] * cba
[i
] + g
[1] * cb1
[i
] +
400 error
+= (data
[i
] - sblock_data
[i
]) *
401 (data
[i
] - sblock_data
[i
]);
404 for (i
= 0; i
< BLOCKSIZE
; i
++) {
405 data
[i
] = zero
[i
] + g
[1] * cb1
[i
] + g
[2] * cb2
[i
];
406 error
+= (data
[i
] - sblock_data
[i
]) *
407 (data
[i
] - sblock_data
[i
]);
410 if (error
< best_error
) {
415 put_bits(pb
, 7, cba_idx
);
416 put_bits(pb
, 8, gain
);
417 put_bits(pb
, 7, cb1_idx
);
418 put_bits(pb
, 7, cb2_idx
);
419 ff_subblock_synthesis(ractx
, lpc_coefs
, cba_idx
, cb1_idx
, cb2_idx
, rms
,
424 static int ra144_encode_frame(AVCodecContext
*avctx
, AVPacket
*avpkt
,
425 const AVFrame
*frame
, int *got_packet_ptr
)
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};
429 RA144Context
*ractx
= avctx
->priv_data
;
431 int32_t lpc_data
[NBLOCKS
* BLOCKSIZE
];
432 int32_t lpc_coefs
[LPC_ORDER
][MAX_LPC_ORDER
];
433 int shift
[LPC_ORDER
];
434 int16_t block_coefs
[NBLOCKS
][LPC_ORDER
];
435 int lpc_refl
[LPC_ORDER
]; /**< reflection coefficients of the frame */
436 unsigned int refl_rms
[NBLOCKS
]; /**< RMS of the reflection coefficients */
437 const int16_t *samples
= frame
? (const int16_t *)frame
->data
[0] : NULL
;
441 if (ractx
->last_frame
)
444 if ((ret
= ff_get_encode_buffer(avctx
, avpkt
, FRAME_SIZE
, 0)) < 0)
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.
454 for (i
= 0; i
< (2 * BLOCKSIZE
+ BLOCKSIZE
/ 2); i
++) {
455 lpc_data
[i
] = ractx
->curr_block
[BLOCKSIZE
+ BLOCKSIZE
/ 2 + i
];
456 energy
+= (lpc_data
[i
] * lpc_data
[i
]) >> 4;
460 for (j
= 0; j
< frame
->nb_samples
&& i
< NBLOCKS
* BLOCKSIZE
; i
++, j
++) {
461 lpc_data
[i
] = samples
[j
] >> 2;
462 energy
+= (lpc_data
[i
] * lpc_data
[i
]) >> 4;
465 if (i
< NBLOCKS
* BLOCKSIZE
)
466 memset(&lpc_data
[i
], 0, (NBLOCKS
* BLOCKSIZE
- i
) * sizeof(*lpc_data
));
467 energy
= ff_energy_tab
[quantize(ff_t_sqrt(energy
>> 5) >> 10, ff_energy_tab
,
470 ff_lpc_calc_coefs(&ractx
->lpc_ctx
, lpc_data
, NBLOCKS
* BLOCKSIZE
, LPC_ORDER
,
471 LPC_ORDER
, 16, lpc_coefs
, shift
, FF_LPC_TYPE_LEVINSON
,
472 0, ORDER_METHOD_EST
, 0, 12, 0);
473 for (i
= 0; i
< LPC_ORDER
; i
++)
474 block_coefs
[NBLOCKS
- 1][i
] = -lpc_coefs
[LPC_ORDER
- 1][i
]
475 * (1 << (12 - shift
[LPC_ORDER
- 1]));
478 * TODO: apply perceptual weighting of the input speech through bandwidth
479 * expansion of the LPC filter.
482 if (ff_eval_refl(lpc_refl
, block_coefs
[NBLOCKS
- 1], avctx
)) {
484 * The filter is unstable: use the coefficients of the previous frame.
486 ff_int_to_int16(block_coefs
[NBLOCKS
- 1], ractx
->lpc_coef
[1]);
487 if (ff_eval_refl(lpc_refl
, block_coefs
[NBLOCKS
- 1], avctx
)) {
488 /* the filter is still unstable. set reflection coeffs to zero. */
489 memset(lpc_refl
, 0, sizeof(lpc_refl
));
492 init_put_bits(&pb
, avpkt
->data
, avpkt
->size
);
493 for (i
= 0; i
< LPC_ORDER
; i
++) {
494 idx
= quantize(lpc_refl
[i
], ff_lpc_refl_cb
[i
], sizes
[i
]);
495 put_bits(&pb
, bit_sizes
[i
], idx
);
496 lpc_refl
[i
] = ff_lpc_refl_cb
[i
][idx
];
498 ractx
->lpc_refl_rms
[0] = ff_rms(lpc_refl
);
499 ff_eval_coefs(ractx
->lpc_coef
[0], lpc_refl
);
500 refl_rms
[0] = ff_interp(ractx
, block_coefs
[0], 1, 1, ractx
->old_energy
);
501 refl_rms
[1] = ff_interp(ractx
, block_coefs
[1], 2,
502 energy
<= ractx
->old_energy
,
503 ff_t_sqrt(energy
* ractx
->old_energy
) >> 12);
504 refl_rms
[2] = ff_interp(ractx
, block_coefs
[2], 3, 0, energy
);
505 refl_rms
[3] = ff_rescale_rms(ractx
->lpc_refl_rms
[0], energy
);
506 ff_int_to_int16(block_coefs
[NBLOCKS
- 1], ractx
->lpc_coef
[0]);
507 put_bits(&pb
, 5, quantize(energy
, ff_energy_tab
, 32));
508 for (i
= 0; i
< NBLOCKS
; i
++)
509 ra144_encode_subblock(ractx
, ractx
->curr_block
+ i
* BLOCKSIZE
,
510 block_coefs
[i
], refl_rms
[i
], &pb
);
512 ractx
->old_energy
= energy
;
513 ractx
->lpc_refl_rms
[1] = ractx
->lpc_refl_rms
[0];
514 FFSWAP(unsigned int *, ractx
->lpc_coef
[0], ractx
->lpc_coef
[1]);
516 /* copy input samples to current block for processing in next call */
519 for (; i
< frame
->nb_samples
; i
++)
520 ractx
->curr_block
[i
] = samples
[i
] >> 2;
522 if ((ret
= ff_af_queue_add(&ractx
->afq
, frame
)) < 0)
525 ractx
->last_frame
= 1;
526 memset(&ractx
->curr_block
[i
], 0,
527 (NBLOCKS
* BLOCKSIZE
- i
) * sizeof(*ractx
->curr_block
));
529 /* Get the next frame pts/duration */
530 ff_af_queue_remove(&ractx
->afq
, avctx
->frame_size
, &avpkt
->pts
,
538 const FFCodec ff_ra_144_encoder
= {
539 .p
.name
= "real_144",
540 CODEC_LONG_NAME("RealAudio 1.0 (14.4K)"),
541 .p
.type
= AVMEDIA_TYPE_AUDIO
,
542 .p
.id
= AV_CODEC_ID_RA_144
,
543 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_DELAY
|
544 AV_CODEC_CAP_SMALL_LAST_FRAME
,
545 .priv_data_size
= sizeof(RA144Context
),
546 .init
= ra144_encode_init
,
547 FF_CODEC_ENCODE_CB(ra144_encode_frame
),
548 .close
= ra144_encode_close
,
549 .p
.sample_fmts
= (const enum AVSampleFormat
[]){ AV_SAMPLE_FMT_S16
,
550 AV_SAMPLE_FMT_NONE
},
551 .p
.supported_samplerates
= (const int[]){ 8000, 0 },
552 .p
.ch_layouts
= (const AVChannelLayout
[]){ AV_CHANNEL_LAYOUT_MONO
, { 0 } },