CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/at3_standalone/atrac3plusdec.cpp
Views: 1401
1
/*
2
* ATRAC3+ compatible decoder
3
*
4
* Copyright (c) 2010-2013 Maxim Poliakovski
5
*
6
* This file is part of FFmpeg.
7
*
8
* FFmpeg is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* FFmpeg is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with FFmpeg; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
*/
22
23
/**
24
* @file
25
* Sony ATRAC3+ compatible decoder.
26
*
27
* Container formats used to store its data:
28
* RIFF WAV (.at3) and Sony OpenMG (.oma, .aa3).
29
*
30
* Technical description of this codec can be found here:
31
* http://wiki.multimedia.cx/index.php?title=ATRAC3plus
32
*
33
* Kudos to Benjamin Larsson and Michael Karcher
34
* for their precious technical help!
35
*/
36
37
#include <stdint.h>
38
#include <string.h>
39
40
#include "float_dsp.h"
41
#include "get_bits.h"
42
#include "compat.h"
43
#include "atrac.h"
44
#include "mem.h"
45
#include "atrac3plus.h"
46
47
struct ATRAC3PContext {
48
GetBitContext gb;
49
50
DECLARE_ALIGNED(32, float, samples)[2][ATRAC3P_FRAME_SAMPLES]; ///< quantized MDCT spectrum
51
DECLARE_ALIGNED(32, float, mdct_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the IMDCT
52
DECLARE_ALIGNED(32, float, time_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the gain compensation
53
DECLARE_ALIGNED(32, float, outp_buf)[2][ATRAC3P_FRAME_SAMPLES];
54
55
AtracGCContext gainc_ctx; ///< gain compensation context
56
FFTContext mdct_ctx;
57
FFTContext ipqf_dct_ctx; ///< IDCT context used by IPQF
58
59
Atrac3pChanUnitCtx *ch_units; ///< global channel units
60
61
int num_channel_blocks; ///< number of channel blocks
62
uint8_t channel_blocks[5]; ///< channel configuration descriptor
63
64
int block_align;
65
};
66
67
void atrac3p_free(ATRAC3PContext *ctx)
68
{
69
av_freep(&ctx->ch_units);
70
ff_mdct_end(&ctx->mdct_ctx);
71
ff_mdct_end(&ctx->ipqf_dct_ctx);
72
av_freep(&ctx);
73
}
74
75
static int set_channel_params(ATRAC3PContext *ctx, int channels) {
76
memset(ctx->channel_blocks, 0, sizeof(ctx->channel_blocks));
77
switch (channels) {
78
case 1:
79
ctx->num_channel_blocks = 1;
80
ctx->channel_blocks[0] = CH_UNIT_MONO;
81
break;
82
case 2:
83
ctx->num_channel_blocks = 1;
84
ctx->channel_blocks[0] = CH_UNIT_STEREO;
85
break;
86
case 3:
87
ctx->num_channel_blocks = 2;
88
ctx->channel_blocks[0] = CH_UNIT_STEREO;
89
ctx->channel_blocks[1] = CH_UNIT_MONO;
90
break;
91
case 4:
92
ctx->num_channel_blocks = 3;
93
ctx->channel_blocks[0] = CH_UNIT_STEREO;
94
ctx->channel_blocks[1] = CH_UNIT_MONO;
95
ctx->channel_blocks[2] = CH_UNIT_MONO;
96
break;
97
case 6:
98
ctx->num_channel_blocks = 4;
99
ctx->channel_blocks[0] = CH_UNIT_STEREO;
100
ctx->channel_blocks[1] = CH_UNIT_MONO;
101
ctx->channel_blocks[2] = CH_UNIT_STEREO;
102
ctx->channel_blocks[3] = CH_UNIT_MONO;
103
break;
104
case 7:
105
ctx->num_channel_blocks = 5;
106
ctx->channel_blocks[0] = CH_UNIT_STEREO;
107
ctx->channel_blocks[1] = CH_UNIT_MONO;
108
ctx->channel_blocks[2] = CH_UNIT_STEREO;
109
ctx->channel_blocks[3] = CH_UNIT_MONO;
110
ctx->channel_blocks[4] = CH_UNIT_MONO;
111
break;
112
case 8:
113
ctx->num_channel_blocks = 5;
114
ctx->channel_blocks[0] = CH_UNIT_STEREO;
115
ctx->channel_blocks[1] = CH_UNIT_MONO;
116
ctx->channel_blocks[2] = CH_UNIT_STEREO;
117
ctx->channel_blocks[3] = CH_UNIT_STEREO;
118
ctx->channel_blocks[4] = CH_UNIT_MONO;
119
break;
120
default:
121
av_log(AV_LOG_ERROR,
122
"Unsupported channel count: %d!\n", channels);
123
return AVERROR_INVALIDDATA;
124
}
125
return 0;
126
}
127
128
ATRAC3PContext *atrac3p_alloc(int channels, int *block_align) {
129
int i, ch, ret;
130
131
ATRAC3PContext *ctx = (ATRAC3PContext *)av_mallocz(sizeof(ATRAC3PContext));
132
ctx->block_align = *block_align;
133
134
if (!*block_align) {
135
// No block align was passed in, using the default.
136
*block_align = 0x000002e8;
137
}
138
139
ff_atrac3p_init_vlcs();
140
141
/* initialize IPQF */
142
ff_mdct_init(&ctx->ipqf_dct_ctx, 5, 1, 32.0 / 32768.0);
143
144
ff_atrac3p_init_imdct(&ctx->mdct_ctx);
145
146
ff_atrac_init_gain_compensation(&ctx->gainc_ctx, 6, 2);
147
148
ff_atrac3p_init_wave_synth();
149
150
if ((ret = set_channel_params(ctx, channels)) < 0) {
151
atrac3p_free(ctx);
152
return nullptr;
153
}
154
155
ctx->ch_units = (Atrac3pChanUnitCtx *)av_mallocz_array(ctx->num_channel_blocks, sizeof(*ctx->ch_units));
156
157
if (!ctx->ch_units) {
158
atrac3p_free(ctx);
159
return nullptr;
160
}
161
162
for (i = 0; i < ctx->num_channel_blocks; i++) {
163
for (ch = 0; ch < 2; ch++) {
164
ctx->ch_units[i].channels[ch].ch_num = ch;
165
ctx->ch_units[i].channels[ch].wnd_shape = &ctx->ch_units[i].channels[ch].wnd_shape_hist[0][0];
166
ctx->ch_units[i].channels[ch].wnd_shape_prev = &ctx->ch_units[i].channels[ch].wnd_shape_hist[1][0];
167
ctx->ch_units[i].channels[ch].gain_data = &ctx->ch_units[i].channels[ch].gain_data_hist[0][0];
168
ctx->ch_units[i].channels[ch].gain_data_prev = &ctx->ch_units[i].channels[ch].gain_data_hist[1][0];
169
ctx->ch_units[i].channels[ch].tones_info = &ctx->ch_units[i].channels[ch].tones_info_hist[0][0];
170
ctx->ch_units[i].channels[ch].tones_info_prev = &ctx->ch_units[i].channels[ch].tones_info_hist[1][0];
171
}
172
173
ctx->ch_units[i].waves_info = &ctx->ch_units[i].wave_synth_hist[0];
174
ctx->ch_units[i].waves_info_prev = &ctx->ch_units[i].wave_synth_hist[1];
175
}
176
177
return ctx;
178
}
179
180
static void decode_residual_spectrum(Atrac3pChanUnitCtx *ctx,
181
float out[2][ATRAC3P_FRAME_SAMPLES],
182
int num_channels)
183
{
184
int i, sb, ch, qu, nspeclines, RNG_index;
185
float *dst, q;
186
int16_t *src;
187
/* calculate RNG table index for each subband */
188
int sb_RNG_index[ATRAC3P_SUBBANDS] = { 0 };
189
190
if (ctx->mute_flag) {
191
for (ch = 0; ch < num_channels; ch++)
192
memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch]));
193
return;
194
}
195
196
for (qu = 0, RNG_index = 0; qu < ctx->used_quant_units; qu++)
197
RNG_index += ctx->channels[0].qu_sf_idx[qu] +
198
ctx->channels[1].qu_sf_idx[qu];
199
200
for (sb = 0; sb < ctx->num_coded_subbands; sb++, RNG_index += 128)
201
sb_RNG_index[sb] = RNG_index & 0x3FC;
202
203
/* inverse quant and power compensation */
204
for (ch = 0; ch < num_channels; ch++) {
205
/* clear channel's residual spectrum */
206
memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch]));
207
208
for (qu = 0; qu < ctx->used_quant_units; qu++) {
209
src = &ctx->channels[ch].spectrum[av_atrac3p_qu_to_spec_pos[qu]];
210
dst = &out[ch][av_atrac3p_qu_to_spec_pos[qu]];
211
nspeclines = av_atrac3p_qu_to_spec_pos[qu + 1] -
212
av_atrac3p_qu_to_spec_pos[qu];
213
214
if (ctx->channels[ch].qu_wordlen[qu] > 0) {
215
q = av_atrac3p_sf_tab[ctx->channels[ch].qu_sf_idx[qu]] *
216
av_atrac3p_mant_tab[ctx->channels[ch].qu_wordlen[qu]];
217
for (i = 0; i < nspeclines; i++)
218
dst[i] = src[i] * q;
219
}
220
}
221
222
for (sb = 0; sb < ctx->num_coded_subbands; sb++)
223
ff_atrac3p_power_compensation(ctx, ch, &out[ch][0],
224
sb_RNG_index[sb], sb);
225
}
226
227
if (ctx->unit_type == CH_UNIT_STEREO) {
228
for (sb = 0; sb < ctx->num_coded_subbands; sb++) {
229
if (ctx->swap_channels[sb]) {
230
for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++)
231
FFSWAP(float, out[0][sb * ATRAC3P_SUBBAND_SAMPLES + i],
232
out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]);
233
}
234
235
/* flip coefficients' sign if requested */
236
if (ctx->negate_coeffs[sb])
237
for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++)
238
out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i] = -(out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]);
239
}
240
}
241
}
242
243
static void reconstruct_frame(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit,
244
int num_channels)
245
{
246
int ch, sb;
247
248
for (ch = 0; ch < num_channels; ch++) {
249
for (sb = 0; sb < ch_unit->num_subbands; sb++) {
250
/* inverse transform and windowing */
251
ff_atrac3p_imdct(&ctx->mdct_ctx,
252
&ctx->samples[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
253
&ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
254
(ch_unit->channels[ch].wnd_shape_prev[sb] << 1) +
255
ch_unit->channels[ch].wnd_shape[sb], sb);
256
257
/* gain compensation and overlapping */
258
ff_atrac_gain_compensation(&ctx->gainc_ctx,
259
&ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
260
&ch_unit->prev_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES],
261
&ch_unit->channels[ch].gain_data_prev[sb],
262
&ch_unit->channels[ch].gain_data[sb],
263
ATRAC3P_SUBBAND_SAMPLES,
264
&ctx->time_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES]);
265
}
266
267
/* zero unused subbands in both output and overlapping buffers */
268
memset(&ch_unit->prev_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES],
269
0,
270
(ATRAC3P_SUBBANDS - ch_unit->num_subbands) *
271
ATRAC3P_SUBBAND_SAMPLES *
272
sizeof(ch_unit->prev_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES]));
273
memset(&ctx->time_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES],
274
0,
275
(ATRAC3P_SUBBANDS - ch_unit->num_subbands) *
276
ATRAC3P_SUBBAND_SAMPLES *
277
sizeof(ctx->time_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES]));
278
279
/* resynthesize and add tonal signal */
280
if (ch_unit->waves_info->tones_present ||
281
ch_unit->waves_info_prev->tones_present) {
282
for (sb = 0; sb < ch_unit->num_subbands; sb++)
283
if (ch_unit->channels[ch].tones_info[sb].num_wavs ||
284
ch_unit->channels[ch].tones_info_prev[sb].num_wavs) {
285
ff_atrac3p_generate_tones(ch_unit, ch, sb,
286
&ctx->time_buf[ch][sb * 128]);
287
}
288
}
289
290
/* subband synthesis and acoustic signal output */
291
ff_atrac3p_ipqf(&ctx->ipqf_dct_ctx, &ch_unit->ipqf_ctx[ch],
292
&ctx->time_buf[ch][0], &ctx->outp_buf[ch][0]);
293
}
294
295
/* swap window shape and gain control buffers. */
296
for (ch = 0; ch < num_channels; ch++) {
297
FFSWAP(uint8_t *, ch_unit->channels[ch].wnd_shape,
298
ch_unit->channels[ch].wnd_shape_prev);
299
FFSWAP(AtracGainInfo *, ch_unit->channels[ch].gain_data,
300
ch_unit->channels[ch].gain_data_prev);
301
FFSWAP(Atrac3pWavesData *, ch_unit->channels[ch].tones_info,
302
ch_unit->channels[ch].tones_info_prev);
303
}
304
305
FFSWAP(Atrac3pWaveSynthParams *, ch_unit->waves_info, ch_unit->waves_info_prev);
306
}
307
308
int atrac3p_decode_frame(ATRAC3PContext *ctx, float *out_data[2], int *nb_samples, const uint8_t *indata, int indata_size)
309
{
310
int i, ret, ch_unit_id, ch_block = 0, out_ch_index = 0, channels_to_process;
311
float **samples_p = out_data;
312
313
*nb_samples = 0;
314
315
if ((ret = init_get_bits8(&ctx->gb, indata, indata_size)) < 0)
316
return ret;
317
318
if (get_bits1(&ctx->gb)) {
319
av_log(AV_LOG_ERROR, "Invalid start bit!");
320
return AVERROR_INVALIDDATA;
321
}
322
323
while (get_bits_left(&ctx->gb) >= 2 &&
324
(ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) {
325
if (ch_unit_id == CH_UNIT_EXTENSION) {
326
avpriv_report_missing_feature("Channel unit extension");
327
return AVERROR_PATCHWELCOME;
328
}
329
if (ch_block >= ctx->num_channel_blocks ||
330
ctx->channel_blocks[ch_block] != ch_unit_id) {
331
av_log(AV_LOG_ERROR,
332
"Frame data doesn't match channel configuration!");
333
return AVERROR_INVALIDDATA;
334
}
335
336
ctx->ch_units[ch_block].unit_type = ch_unit_id;
337
channels_to_process = ch_unit_id + 1;
338
339
if ((ret = ff_atrac3p_decode_channel_unit(&ctx->gb,
340
&ctx->ch_units[ch_block],
341
channels_to_process)) < 0)
342
return ret;
343
344
decode_residual_spectrum(&ctx->ch_units[ch_block], ctx->samples,
345
channels_to_process);
346
reconstruct_frame(ctx, &ctx->ch_units[ch_block],
347
channels_to_process);
348
349
for (i = 0; i < channels_to_process; i++)
350
memcpy(samples_p[out_ch_index + i], ctx->outp_buf[i],
351
ATRAC3P_FRAME_SAMPLES * sizeof(**samples_p));
352
353
ch_block++;
354
out_ch_index += channels_to_process;
355
}
356
357
*nb_samples = ATRAC3P_FRAME_SAMPLES;
358
return FFMIN(ctx->block_align, indata_size);
359
}
360
361
void atrac3p_flush_buffers(ATRAC3PContext *ctx) {
362
// TODO: Not sure what should be zeroed here.
363
}
364
365