2 * RealAudio 2.0 (28.8K)
3 * Copyright (c) 2003 the ffmpeg project
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/channel_layout.h"
23 #include "libavutil/float_dsp.h"
26 #define BITSTREAM_READER_LE
30 #include "celp_filters.h"
32 #define MAX_BACKWARD_FILTER_ORDER 36
33 #define MAX_BACKWARD_FILTER_LEN 40
34 #define MAX_BACKWARD_FILTER_NONREC 35
36 #define RA288_BLOCK_SIZE 5
37 #define RA288_BLOCKS_PER_FRAME 32
42 AVFloatDSPContext fdsp
;
43 DECLARE_ALIGNED(32, float, sp_lpc
)[FFALIGN(36, 16)]; ///< LPC coefficients for speech data (spec: A)
44 DECLARE_ALIGNED(32, float, gain_lpc
)[FFALIGN(10, 16)]; ///< LPC coefficients for gain (spec: GB)
46 /** speech data history (spec: SB).
47 * Its first 70 coefficients are updated only at backward filtering.
51 /// speech part of the gain autocorrelation (spec: REXP)
54 /** log-gain history (spec: SBLG).
55 * Its first 28 coefficients are updated only at backward filtering.
59 /// recursive part of the gain autocorrelation (spec: REXPLG)
63 static av_cold
int ra288_decode_init(AVCodecContext
*avctx
)
65 RA288Context
*ractx
= avctx
->priv_data
;
68 avctx
->channel_layout
= AV_CH_LAYOUT_MONO
;
69 avctx
->sample_fmt
= AV_SAMPLE_FMT_FLT
;
71 avpriv_float_dsp_init(&ractx
->fdsp
, avctx
->flags
& CODEC_FLAG_BITEXACT
);
73 avcodec_get_frame_defaults(&ractx
->frame
);
74 avctx
->coded_frame
= &ractx
->frame
;
79 static void convolve(float *tgt
, const float *src
, int len
, int n
)
82 tgt
[n
] = ff_scalarproduct_float_c(src
, src
- n
, len
);
86 static void decode(RA288Context
*ractx
, float gain
, int cb_coef
)
91 float *block
= ractx
->sp_hist
+ 70 + 36; // current block
92 float *gain_block
= ractx
->gain_hist
+ 28;
94 memmove(ractx
->sp_hist
+ 70, ractx
->sp_hist
+ 75, 36*sizeof(*block
));
96 /* block 46 of G.728 spec */
98 for (i
=0; i
< 10; i
++)
99 sum
-= gain_block
[9-i
] * ractx
->gain_lpc
[i
];
101 /* block 47 of G.728 spec */
102 sum
= av_clipf(sum
, 0, 60);
104 /* block 48 of G.728 spec */
105 /* exp(sum * 0.1151292546497) == pow(10.0,sum/20) */
106 sumsum
= exp(sum
* 0.1151292546497) * gain
* (1.0/(1<<23));
108 for (i
=0; i
< 5; i
++)
109 buffer
[i
] = codetable
[cb_coef
][i
] * sumsum
;
111 sum
= ff_scalarproduct_float_c(buffer
, buffer
, 5) * ((1 << 24) / 5.);
115 /* shift and store */
116 memmove(gain_block
, gain_block
+ 1, 9 * sizeof(*gain_block
));
118 gain_block
[9] = 10 * log10(sum
) - 32;
120 ff_celp_lp_synthesis_filterf(block
, ractx
->sp_lpc
, buffer
, 5, 36);
124 * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification.
126 * @param order filter order
127 * @param n input length
128 * @param non_rec number of non-recursive samples
129 * @param out filter output
130 * @param hist pointer to the input history of the filter
131 * @param out pointer to the non-recursive part of the output
132 * @param out2 pointer to the recursive part of the output
133 * @param window pointer to the windowing function table
135 static void do_hybrid_window(RA288Context
*ractx
,
136 int order
, int n
, int non_rec
, float *out
,
137 float *hist
, float *out2
, const float *window
)
140 float buffer1
[MAX_BACKWARD_FILTER_ORDER
+ 1];
141 float buffer2
[MAX_BACKWARD_FILTER_ORDER
+ 1];
142 LOCAL_ALIGNED(32, float, work
, [FFALIGN(MAX_BACKWARD_FILTER_ORDER
+
143 MAX_BACKWARD_FILTER_LEN
+
144 MAX_BACKWARD_FILTER_NONREC
, 16)]);
146 ractx
->fdsp
.vector_fmul(work
, window
, hist
, FFALIGN(order
+ n
+ non_rec
, 16));
148 convolve(buffer1
, work
+ order
, n
, order
);
149 convolve(buffer2
, work
+ order
+ n
, non_rec
, order
);
151 for (i
=0; i
<= order
; i
++) {
152 out2
[i
] = out2
[i
] * 0.5625 + buffer1
[i
];
153 out
[i
] = out2
[i
] + buffer2
[i
];
156 /* Multiply by the white noise correcting factor (WNCF). */
161 * Backward synthesis filter, find the LPC coefficients from past speech data.
163 static void backward_filter(RA288Context
*ractx
,
164 float *hist
, float *rec
, const float *window
,
165 float *lpc
, const float *tab
,
166 int order
, int n
, int non_rec
, int move_size
)
168 float temp
[MAX_BACKWARD_FILTER_ORDER
+1];
170 do_hybrid_window(ractx
, order
, n
, non_rec
, temp
, hist
, rec
, window
);
172 if (!compute_lpc_coefs(temp
, order
, lpc
, 0, 1, 1))
173 ractx
->fdsp
.vector_fmul(lpc
, lpc
, tab
, FFALIGN(order
, 16));
175 memmove(hist
, hist
+ n
, move_size
*sizeof(*hist
));
178 static int ra288_decode_frame(AVCodecContext
* avctx
, void *data
,
179 int *got_frame_ptr
, AVPacket
*avpkt
)
181 const uint8_t *buf
= avpkt
->data
;
182 int buf_size
= avpkt
->size
;
185 RA288Context
*ractx
= avctx
->priv_data
;
188 if (buf_size
< avctx
->block_align
) {
189 av_log(avctx
, AV_LOG_ERROR
,
190 "Error! Input buffer is too small [%d<%d]\n",
191 buf_size
, avctx
->block_align
);
192 return AVERROR_INVALIDDATA
;
195 /* get output buffer */
196 ractx
->frame
.nb_samples
= RA288_BLOCK_SIZE
* RA288_BLOCKS_PER_FRAME
;
197 if ((ret
= ff_get_buffer(avctx
, &ractx
->frame
)) < 0) {
198 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
201 out
= (float *)ractx
->frame
.data
[0];
203 init_get_bits(&gb
, buf
, avctx
->block_align
* 8);
205 for (i
=0; i
< RA288_BLOCKS_PER_FRAME
; i
++) {
206 float gain
= amptable
[get_bits(&gb
, 3)];
207 int cb_coef
= get_bits(&gb
, 6 + (i
&1));
209 decode(ractx
, gain
, cb_coef
);
211 memcpy(out
, &ractx
->sp_hist
[70 + 36], RA288_BLOCK_SIZE
* sizeof(*out
));
212 out
+= RA288_BLOCK_SIZE
;
215 backward_filter(ractx
, ractx
->sp_hist
, ractx
->sp_rec
, syn_window
,
216 ractx
->sp_lpc
, syn_bw_tab
, 36, 40, 35, 70);
218 backward_filter(ractx
, ractx
->gain_hist
, ractx
->gain_rec
, gain_window
,
219 ractx
->gain_lpc
, gain_bw_tab
, 10, 8, 20, 28);
224 *(AVFrame
*)data
= ractx
->frame
;
226 return avctx
->block_align
;
229 AVCodec ff_ra_288_decoder
= {
231 .type
= AVMEDIA_TYPE_AUDIO
,
232 .id
= AV_CODEC_ID_RA_288
,
233 .priv_data_size
= sizeof(RA288Context
),
234 .init
= ra288_decode_init
,
235 .decode
= ra288_decode_frame
,
236 .capabilities
= CODEC_CAP_DR1
,
237 .long_name
= NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"),