ra288.c
Go to the documentation of this file.
1 /*
2  * RealAudio 2.0 (28.8K)
3  * Copyright (c) 2003 the ffmpeg project
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 
23 #include "libavutil/float_dsp.h"
24 #include "libavutil/internal.h"
25 #include "avcodec.h"
26 #include "internal.h"
27 #define BITSTREAM_READER_LE
28 #include "get_bits.h"
29 #include "ra288.h"
30 #include "lpc.h"
31 #include "celp_filters.h"
32 
33 #define MAX_BACKWARD_FILTER_ORDER 36
34 #define MAX_BACKWARD_FILTER_LEN 40
35 #define MAX_BACKWARD_FILTER_NONREC 35
36 
37 #define RA288_BLOCK_SIZE 5
38 #define RA288_BLOCKS_PER_FRAME 32
39 
40 typedef struct {
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)
44 
45  /** speech data history (spec: SB).
46  * Its first 70 coefficients are updated only at backward filtering.
47  */
48  float sp_hist[111];
49 
50  /// speech part of the gain autocorrelation (spec: REXP)
51  float sp_rec[37];
52 
53  /** log-gain history (spec: SBLG).
54  * Its first 28 coefficients are updated only at backward filtering.
55  */
56  float gain_hist[38];
57 
58  /// recursive part of the gain autocorrelation (spec: REXPLG)
59  float gain_rec[11];
60 } RA288Context;
61 
63 {
64  RA288Context *ractx = avctx->priv_data;
65 
66  avctx->channels = 1;
69 
70  if (avctx->block_align <= 0) {
71  av_log(avctx, AV_LOG_ERROR, "unsupported block align\n");
72  return AVERROR_PATCHWELCOME;
73  }
74 
76 
77  return 0;
78 }
79 
80 static void convolve(float *tgt, const float *src, int len, int n)
81 {
82  for (; n >= 0; n--)
83  tgt[n] = avpriv_scalarproduct_float_c(src, src - n, len);
84 
85 }
86 
87 static void decode(RA288Context *ractx, float gain, int cb_coef)
88 {
89  int i;
90  double sumsum;
91  float sum, buffer[5];
92  float *block = ractx->sp_hist + 70 + 36; // current block
93  float *gain_block = ractx->gain_hist + 28;
94 
95  memmove(ractx->sp_hist + 70, ractx->sp_hist + 75, 36*sizeof(*block));
96 
97  /* block 46 of G.728 spec */
98  sum = 32.;
99  for (i=0; i < 10; i++)
100  sum -= gain_block[9-i] * ractx->gain_lpc[i];
101 
102  /* block 47 of G.728 spec */
103  sum = av_clipf(sum, 0, 60);
104 
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));
108 
109  for (i=0; i < 5; i++)
110  buffer[i] = codetable[cb_coef][i] * sumsum;
111 
112  sum = avpriv_scalarproduct_float_c(buffer, buffer, 5);
113 
114  sum = FFMAX(sum, 5. / (1<<24));
115 
116  /* shift and store */
117  memmove(gain_block, gain_block + 1, 9 * sizeof(*gain_block));
118 
119  gain_block[9] = 10 * log10(sum) + (10*log10(((1<<24)/5.)) - 32);
120 
121  ff_celp_lp_synthesis_filterf(block, ractx->sp_lpc, buffer, 5, 36);
122 }
123 
124 /**
125  * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification.
126  *
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
135  */
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)
139 {
140  int i;
141  float buffer1[MAX_BACKWARD_FILTER_ORDER + 1];
142  float buffer2[MAX_BACKWARD_FILTER_ORDER + 1];
146 
147  av_assert2(order>=0);
148 
149  ractx->fdsp.vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 16));
150 
151  convolve(buffer1, work + order , n , order);
152  convolve(buffer2, work + order + n, non_rec, order);
153 
154  for (i=0; i <= order; i++) {
155  out2[i] = out2[i] * 0.5625 + buffer1[i];
156  out [i] = out2[i] + buffer2[i];
157  }
158 
159  /* Multiply by the white noise correcting factor (WNCF). */
160  *out *= 257./256.;
161 }
162 
163 /**
164  * Backward synthesis filter, find the LPC coefficients from past speech data.
165  */
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)
170 {
171  float temp[MAX_BACKWARD_FILTER_ORDER+1];
172 
173  do_hybrid_window(ractx, order, n, non_rec, temp, hist, rec, window);
174 
175  if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1))
176  ractx->fdsp.vector_fmul(lpc, lpc, tab, FFALIGN(order, 16));
177 
178  memmove(hist, hist + n, move_size*sizeof(*hist));
179 }
180 
181 static int ra288_decode_frame(AVCodecContext * avctx, void *data,
182  int *got_frame_ptr, AVPacket *avpkt)
183 {
184  AVFrame *frame = data;
185  const uint8_t *buf = avpkt->data;
186  int buf_size = avpkt->size;
187  float *out;
188  int i, ret;
189  RA288Context *ractx = avctx->priv_data;
190  GetBitContext gb;
191 
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;
197  }
198 
199  /* get output buffer */
201  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
202  return ret;
203  out = (float *)frame->data[0];
204 
205  init_get_bits(&gb, buf, avctx->block_align * 8);
206 
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));
210 
211  decode(ractx, gain, cb_coef);
212 
213  memcpy(out, &ractx->sp_hist[70 + 36], RA288_BLOCK_SIZE * sizeof(*out));
214  out += RA288_BLOCK_SIZE;
215 
216  if ((i & 7) == 3) {
217  backward_filter(ractx, ractx->sp_hist, ractx->sp_rec, syn_window,
218  ractx->sp_lpc, syn_bw_tab, 36, 40, 35, 70);
219 
220  backward_filter(ractx, ractx->gain_hist, ractx->gain_rec, gain_window,
221  ractx->gain_lpc, gain_bw_tab, 10, 8, 20, 28);
222  }
223  }
224 
225  *got_frame_ptr = 1;
226 
227  return avctx->block_align;
228 }
229 
231  .name = "real_288",
232  .type = AVMEDIA_TYPE_AUDIO,
233  .id = AV_CODEC_ID_RA_288,
234  .priv_data_size = sizeof(RA288Context),
237  .capabilities = CODEC_CAP_DR1,
238  .long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"),
239 };
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs, const float *in, int buffer_length, int filter_length)
LP synthesis filter.
Definition: celp_filters.c:84
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
static void backward_filter(RA288Context *ractx, float *hist, float *rec, const float *window, float *lpc, const float *tab, int order, int n, int non_rec, int move_size)
Backward synthesis filter, find the LPC coefficients from past speech data.
Definition: ra288.c:166
must be printed separately If there s no standard function for printing the type you the WRITE_1D_FUNC_ARGV macro is a very quick way to create one See libavcodec dv_tablegen c for an example The h file This file should the initialization functions should not do and instead of the variable declarations the generated *_tables h file should be included Since that will be generated in the build the path must be i e not Makefile changes To make the automatic table creation work
Definition: tablegen.txt:45
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:240
#define MAX_BACKWARD_FILTER_ORDER
Definition: ra288.c:33
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
#define DECLARE_ALIGNED(n, t, v)
Definition: mem.h:59
static void decode(RA288Context *ractx, float gain, int cb_coef)
Definition: ra288.c:87
int block_align
number of bytes per packet if constant and known or 0 Used by some WAV based audio codecs...
static const float amptable[8]
Definition: ra288.h:28
#define FFALIGN(x, a)
Definition: common.h:63
AVFloatDSPContext fdsp
Definition: ra288.c:41
float avpriv_scalarproduct_float_c(const float *v1, const float *v2, int len)
Return the scalar product of two vectors.
Definition: float_dsp.c:107
enum AVSampleFormat sample_fmt
audio sample format
#define av_cold
Definition: attributes.h:78
#define MAX_BACKWARD_FILTER_NONREC
Definition: ra288.c:35
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:63
void(* vector_fmul)(float *dst, const float *src0, const float *src1, int len)
Calculate the product of two vectors of floats and store the result in a vector of floats...
Definition: float_dsp.h:38
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
bitstream reader API header.
#define CODEC_FLAG_BITEXACT
Use only bitexact stuff (except (I)DCT).
uint8_t * data[8]
pointer to the picture/channel planes.
Definition: frame.h:87
frame
Definition: stft.m:14
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
#define MAX_BACKWARD_FILTER_LEN
Definition: ra288.c:34
Spectrum Plot time data
int flags
CODEC_FLAG_*.
void av_log(void *avcl, int level, const char *fmt,...)
Send the specified message to the log if the level is less than or equal to the current av_log_level...
Definition: log.c:246
const char * name
Name of the codec implementation.
overlapping window(triangular window to avoid too much overlapping) ovidx
static void convolve(float *tgt, const float *src, int len, int n)
Definition: ra288.c:80
#define FFMAX(a, b)
Definition: common.h:56
external API header
uint64_t channel_layout
Audio channel layout.
AVCodec ff_ra_288_decoder
Definition: ra288.c:230
common internal API header
audio channel layout utility functions
#define RA288_BLOCKS_PER_FRAME
Definition: ra288.c:38
ret
Definition: avfilter.c:821
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
1i.*Xphase exp()
static const int16_t codetable[128][5]
Definition: ra288.h:33
AVS_Value src
Definition: avisynth_c.h:523
main external API structure.
static void do_hybrid_window(RA288Context *ractx, int order, int n, int non_rec, float *out, float *hist, float *out2, const float *window)
Hybrid window filtering, see blocks 36 and 49 of the G.728 specification.
Definition: ra288.c:136
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
synthesis window for stochastic i
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:379
static int compute_lpc_coefs(const float *autoc, int max_order, float *lpc, int lpc_stride, int fail, int normalize)
Levinson-Durbin recursion.
Definition: lpc.h:151
#define RA288_BLOCK_SIZE
Definition: ra288.c:37
static av_cold int ra288_decode_init(AVCodecContext *avctx)
Definition: ra288.c:62
static int ra288_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt)
Definition: ra288.c:181
common internal api header.
#define LOCAL_ALIGNED(a, t, v,...)
the buffer and buffer reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFilterBuffer structures They must not be accessed but through references stored in AVFilterBufferRef structures Several references can point to the same buffer
int len
int channels
number of audio channels
static const struct twinvq_data tab
void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact)
Initialize a float DSP context.
Definition: float_dsp.c:118
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:127