2 * RealAudio 2.0 (28.8K)
3 * Copyright (c) 2003 The FFmpeg Project
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
22 #include "libavutil/channel_layout.h"
23 #include "libavutil/float_dsp.h"
24 #include "libavutil/internal.h"
27 #define BITSTREAM_READER_LE
31 #include "celp_filters.h"
33 #define MAX_BACKWARD_FILTER_ORDER 36
34 #define MAX_BACKWARD_FILTER_LEN 40
35 #define MAX_BACKWARD_FILTER_NONREC 35
37 #define RA288_BLOCK_SIZE 5
38 #define RA288_BLOCKS_PER_FRAME 32
41 AVFloatDSPContext fdsp
;
42 DECLARE_ALIGNED(32, float, sp_lpc
)[FFALIGN(36, 16)]; ///< LPC coefficients for speech data (spec: A)
43 DECLARE_ALIGNED(32, float, gain_lpc
)[FFALIGN(10, 16)]; ///< LPC coefficients for gain (spec: GB)
45 /** speech data history (spec: SB).
46 * Its first 70 coefficients are updated only at backward filtering.
50 /// speech part of the gain autocorrelation (spec: REXP)
53 /** log-gain history (spec: SBLG).
54 * Its first 28 coefficients are updated only at backward filtering.
58 /// recursive part of the gain autocorrelation (spec: REXPLG)
62 static av_cold
int ra288_decode_init(AVCodecContext
*avctx
)
64 RA288Context
*ractx
= avctx
->priv_data
;
67 avctx
->channel_layout
= AV_CH_LAYOUT_MONO
;
68 avctx
->sample_fmt
= AV_SAMPLE_FMT_FLT
;
70 if (avctx
->block_align
<= 0) {
71 av_log(avctx
, AV_LOG_ERROR
, "unsupported block align\n");
72 return AVERROR_PATCHWELCOME
;
75 avpriv_float_dsp_init(&ractx
->fdsp
, avctx
->flags
& CODEC_FLAG_BITEXACT
);
80 static void convolve(float *tgt
, const float *src
, int len
, int n
)
83 tgt
[n
] = avpriv_scalarproduct_float_c(src
, src
- n
, len
);
87 static void decode(RA288Context
*ractx
, float gain
, int cb_coef
)
92 float *block
= ractx
->sp_hist
+ 70 + 36; // current block
93 float *gain_block
= ractx
->gain_hist
+ 28;
95 memmove(ractx
->sp_hist
+ 70, ractx
->sp_hist
+ 75, 36*sizeof(*block
));
97 /* block 46 of G.728 spec */
99 for (i
=0; i
< 10; i
++)
100 sum
-= gain_block
[9-i
] * ractx
->gain_lpc
[i
];
102 /* block 47 of G.728 spec */
103 sum
= av_clipf(sum
, 0, 60);
105 /* block 48 of G.728 spec */
106 /* exp(sum * 0.1151292546497) == pow(10.0,sum/20) */
107 sumsum
= exp(sum
* 0.1151292546497) * gain
* (1.0/(1<<23));
109 for (i
=0; i
< 5; i
++)
110 buffer
[i
] = codetable
[cb_coef
][i
] * sumsum
;
112 sum
= avpriv_scalarproduct_float_c(buffer
, buffer
, 5);
114 sum
= FFMAX(sum
, 5.0 / (1<<24));
116 /* shift and store */
117 memmove(gain_block
, gain_block
+ 1, 9 * sizeof(*gain_block
));
119 gain_block
[9] = 10 * log10(sum
) + (10*log10(((1<<24)/5.)) - 32);
121 ff_celp_lp_synthesis_filterf(block
, ractx
->sp_lpc
, buffer
, 5, 36);
125 * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification.
127 * @param order filter order
128 * @param n input length
129 * @param non_rec number of non-recursive samples
130 * @param out filter output
131 * @param hist pointer to the input history of the filter
132 * @param out pointer to the non-recursive part of the output
133 * @param out2 pointer to the recursive part of the output
134 * @param window pointer to the windowing function table
136 static void do_hybrid_window(RA288Context
*ractx
,
137 int order
, int n
, int non_rec
, float *out
,
138 float *hist
, float *out2
, const float *window
)
141 float buffer1
[MAX_BACKWARD_FILTER_ORDER
+ 1];
142 float buffer2
[MAX_BACKWARD_FILTER_ORDER
+ 1];
143 LOCAL_ALIGNED(32, float, work
, [FFALIGN(MAX_BACKWARD_FILTER_ORDER
+
144 MAX_BACKWARD_FILTER_LEN
+
145 MAX_BACKWARD_FILTER_NONREC
, 16)]);
147 av_assert2(order
>=0);
149 ractx
->fdsp
.vector_fmul(work
, window
, hist
, FFALIGN(order
+ n
+ non_rec
, 16));
151 convolve(buffer1
, work
+ order
, n
, order
);
152 convolve(buffer2
, work
+ order
+ n
, non_rec
, order
);
154 for (i
=0; i
<= order
; i
++) {
155 out2
[i
] = out2
[i
] * 0.5625 + buffer1
[i
];
156 out
[i
] = out2
[i
] + buffer2
[i
];
159 /* Multiply by the white noise correcting factor (WNCF). */
160 *out
*= 257.0 / 256.0;
164 * Backward synthesis filter, find the LPC coefficients from past speech data.
166 static void backward_filter(RA288Context
*ractx
,
167 float *hist
, float *rec
, const float *window
,
168 float *lpc
, const float *tab
,
169 int order
, int n
, int non_rec
, int move_size
)
171 float temp
[MAX_BACKWARD_FILTER_ORDER
+1];
173 do_hybrid_window(ractx
, order
, n
, non_rec
, temp
, hist
, rec
, window
);
175 if (!compute_lpc_coefs(temp
, order
, lpc
, 0, 1, 1))
176 ractx
->fdsp
.vector_fmul(lpc
, lpc
, tab
, FFALIGN(order
, 16));
178 memmove(hist
, hist
+ n
, move_size
*sizeof(*hist
));
181 static int ra288_decode_frame(AVCodecContext
* avctx
, void *data
,
182 int *got_frame_ptr
, AVPacket
*avpkt
)
184 AVFrame
*frame
= data
;
185 const uint8_t *buf
= avpkt
->data
;
186 int buf_size
= avpkt
->size
;
189 RA288Context
*ractx
= avctx
->priv_data
;
192 if (buf_size
< avctx
->block_align
) {
193 av_log(avctx
, AV_LOG_ERROR
,
194 "Error! Input buffer is too small [%d<%d]\n",
195 buf_size
, avctx
->block_align
);
196 return AVERROR_INVALIDDATA
;
199 /* get output buffer */
200 frame
->nb_samples
= RA288_BLOCK_SIZE
* RA288_BLOCKS_PER_FRAME
;
201 if ((ret
= ff_get_buffer(avctx
, frame
, 0)) < 0)
203 out
= (float *)frame
->data
[0];
205 init_get_bits8(&gb
, buf
, avctx
->block_align
);
207 for (i
=0; i
< RA288_BLOCKS_PER_FRAME
; i
++) {
208 float gain
= amptable
[get_bits(&gb
, 3)];
209 int cb_coef
= get_bits(&gb
, 6 + (i
&1));
211 decode(ractx
, gain
, cb_coef
);
213 memcpy(out
, &ractx
->sp_hist
[70 + 36], RA288_BLOCK_SIZE
* sizeof(*out
));
214 out
+= RA288_BLOCK_SIZE
;
217 backward_filter(ractx
, ractx
->sp_hist
, ractx
->sp_rec
, syn_window
,
218 ractx
->sp_lpc
, syn_bw_tab
, 36, 40, 35, 70);
220 backward_filter(ractx
, ractx
->gain_hist
, ractx
->gain_rec
, gain_window
,
221 ractx
->gain_lpc
, gain_bw_tab
, 10, 8, 20, 28);
227 return avctx
->block_align
;
230 AVCodec ff_ra_288_decoder
= {
232 .long_name
= NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"),
233 .type
= AVMEDIA_TYPE_AUDIO
,
234 .id
= AV_CODEC_ID_RA_288
,
235 .priv_data_size
= sizeof(RA288Context
),
236 .init
= ra288_decode_init
,
237 .decode
= ra288_decode_frame
,
238 .capabilities
= CODEC_CAP_DR1
,