summaryrefslogtreecommitdiff
path: root/audio_codec/libcook/gecko2codec.c (plain)
blob: df5d07713d65659bdf06a53437b5eb6294d2d272
1/* ***** BEGIN LICENSE BLOCK *****
2 * Source last modified: $Id: gecko2codec.c,v 1.8 2005/04/27 19:20:50 hubbe Exp $
3 *
4 * REALNETWORKS CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM
5 * Portions Copyright (c) 1995-2002 RealNetworks, Inc.
6 * All Rights Reserved.
7 *
8 * The contents of this file, and the files included with this file,
9 * are subject to the current version of the Real Format Source Code
10 * Porting and Optimization License, available at
11 * https://helixcommunity.org/2005/license/realformatsource (unless
12 * RealNetworks otherwise expressly agrees in writing that you are
13 * subject to a different license). You may also obtain the license
14 * terms directly from RealNetworks. You may not use this file except
15 * in compliance with the Real Format Source Code Porting and
16 * Optimization License. There are no redistribution rights for the
17 * source code of this file. Please see the Real Format Source Code
18 * Porting and Optimization License for the rights, obligations and
19 * limitations governing use of the contents of the file.
20 *
21 * RealNetworks is the developer of the Original Code and owns the
22 * copyrights in the portions it created.
23 *
24 * This file, and the files included with this file, is distributed and
25 * made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND,
26 * EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL
27 * SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT
29 * OR NON-INFRINGEMENT.
30 *
31 * Technology Compatibility Kit Test Suite(s) Location:
32 * https://rarvcode-tck.helixcommunity.org
33 *
34 * Contributor(s):
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/**************************************************************************************
39 * Fixed-point RealAudio 8 decoder
40 * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
41 * October 2003
42 *
43 * gecko2codec.c - public C API for Gecko2 decoder
44 **************************************************************************************/
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include "coder.h"
50//#include "includes.h"
51//#include <amsysdef.h>
52//#include <Drivers/include/mpeg_reg.h>
53#include "cook_decode.h"
54
55#ifndef USE_C_DECODER
56//#define ENABLE_DUMP
57//#define DBG_AMRISC
58#endif
59//#include <core/dsp.h>
60
61#ifdef ENABLE_DUMP
62#define DUMP_GAIN 0x0001
63#define DUMP_CPL 0x0002
64#define DUMP_ENV 0x0004
65#define DUMP_HUFF 0x0008
66#define DUMP_QUANT 0x0010
67#define DUMP_DECODE_INFO 0x0020
68unsigned int DumpMask = 0;
69extern const int cplband[MAXREGNS];
70#endif
71
72FILE *pDumpFile = NULL;
73unsigned int FrameCount = 0;
74
75#ifdef DBG_AMRISC
76
77// copy from ra.h
78
79#define MAXNCHAN 2
80#define NPARTS 8
81#define MAXNATS 8
82#define MAXBUF 4
83
84/*********************************** variables in lmem16 ***************************/
85#define L_DECODEINFO 0
86#define ADTSHI_OFFSET 0
87#define ADTSLO_OFFSET 1
88#define LOSTFLAG_OFFSET 2
89#define NCHANNELS_OFFSET 3
90#define NSAMPLES_OFFSET 4
91#define SAMPLERATE_OFFSET 5
92#define XFORMIDX_OFFSET 6
93#define GBMIN_OFFSET 7
94//[MAXNCHAN]
95#define XBITS_OFFSET 9
96//[MAXNCHAN][2]
97#define DGAINC_OFFSET 13
98//[MAXNCHAN][CODINGDELAY]*sizeof(L_GAINC) = 2*2*18 = 72
99#define NATS_OFFSET 0
100#define LOC_OFFSET 1
101//MAXNATS
102#define GAIN_OFFSET 9
103//MAXNATS
104#define MAXEXGAIN_OFFSET 17
105#define EXGAIN_OFFSET 85
106// 17
107//13+18*4+17 = 102
108#define L_BITREV 128
109//129
110
111/*********************************** variables in lmem24 ***************************/
112
113#define L_DECMLT 0x400
114#define L_COS4SIN4 0x800
115#define L_COS1SIN1 0x800
116#define L_TWIDTAB 0x800
117
118#define L_DECMLT_W 0x400
119//1024
120#define L_OVERLAP_W 0x800
121//256
122#define L_WINDOW 0xa00
123//256
124#define L_POW2NTAB 0xb00
125//128
126#define L_DECODEINFO_SWAP 0xb80
127//11+18*4+17 = 100
128
129/*********************************** variables in sdram ***************************/
130
131#define M_DECODE_INFO 0
132//128*MAXBUF
133//PreMultiply
134#define M_DECMLT (M_DECODE_INFO+128*MAXBUF)
135//1024*2*MAXBUF
136#define M_OVERLAP (M_DECMLT+(1024*2*MAXBUF)*3/2)
137//1024*2
138
139/*********************************** table in sdram ***************************/
140
141//PreMultiply
142#define M_COS4SIN4_1024 (M_OVERLAP+(1024*2)*3/2)
143#define M_COS4SIN4_512 (M_COS4SIN4_1024+1024*3/2)
144#define M_COS4SIN4_256 (M_COS4SIN4_512+512*3/2)
145
146//BitReverse
147#define M_BITREV_1024 (M_COS4SIN4_256+256*3/2)
148//132
149#define M_BITREV_512 (M_BITREV_1024+132)
150//68
151#define M_BITREV_256 (M_BITREV_512+68)
152//36
153
154//PostMultiply
155#define M_COS1SIN1 (M_BITREV_256+36)
156
157//R4FFT
158#define M_TWIDTABEVEN (M_COS1SIN1+(514+2)*3/2)
159//4*6
160//16*6
161//64*6
162#define M_TWIDTABODD (M_TWIDTABEVEN+((4+16+64)*6)*3/2)
163//8*6
164//32*6
165//128*6
166
167//InterpolatePCM & InterpolateOverlap
168#define M_POW2NTAB (M_TWIDTABODD+((8+32+128)*6)*3/2)
169//128
170#define M_WINDOWS_1024 (M_POW2NTAB+128*3/2)
171//1024
172#define M_WINDOWS_512 (M_WINDOWS_1024+1024*3/2)
173//512
174#define M_WINDOWS_256 (M_WINDOWS_512+512*3/2)
175//256
176
177//PCM swap
178#define M_PCM_SWAP (M_WINDOWS_256+256*3/2)
179//2048
180
181#define M_END (M_PCM_SWAP+2048)
182
183// copy from debug.h
184
185#define BP_NEW_FRAME 0x0001
186#define BP_DECODE_INFO 0x0002
187#define BP_BEFORE_INVERSE_TRANSFORM 0x0004
188#define BP_PREMULTIPLY 0x0008
189#define BP_BITREVERSE 0x0010
190#define BP_R8FIRSTPASS 0x0020
191#define BP_R4CORE 0x0040
192#define BP_POSTMULTIPLY 0x0080
193#define BP_GAIN_CHANGES 0x0100
194#define BP_PCM 0x0200
195#define BP_OVERLAP 0x0400
196#define BP_DEBUG 0x1000
197
198#define DBG_MASK 0x1fff
199
200#define BP_DUMP_LMEM16 0x8000
201#define BP_DUMP_LMEM24_1 0x4000
202#define BP_DUMP_LMEM24_2 0x2000
203
204#define TRACE_CMD 0x51c
205#define TRACE_REG0 0x51d
206#define TRACE_REG1 0x51e
207#define TRACE_REG2 0x51f
208#define TRACE_MASK 0x520
209
210#define M_LMEM16_DUMP (0x50000>>1)
211// 2KB
212#define M_LMEM24_1_DUMP (0x50800>>1)
213// 3KB
214#define M_LMEM24_2_DUMP (0x51400>>1)
215// 3KB
216
217void ra_debug_init(void)
218{
219 WRITE_MPEG_REG(TRACE_CMD, 0x0);
220 WRITE_MPEG_REG(TRACE_REG0, 0x0);
221 WRITE_MPEG_REG(TRACE_REG1, 0x0);
222 WRITE_MPEG_REG(TRACE_REG2, 0x0);
223 WRITE_MPEG_REG(TRACE_MASK, BP_NEW_FRAME);
224}
225
226void ra_debug_dump_decmlt(HGecko2Decoder hGecko2Decoder, int gb)
227{
228 Gecko2Info *gi;
229 unsigned rd;
230 unsigned ch, i;
231
232 gi = (Gecko2Info *)hGecko2Decoder;
233 rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
234 ch = READ_MPEG_REG(TRACE_REG0);
235 read_from_24bit_linear_format((M_LMEM24_1_DUMP << 1), &gi->block[rd].decmlt[ch][0], 1024);
236 for (i = 0; i < gi->nSamples; i++) {
237 if (!(i & 7)) {
238 fprintf(pDumpFile, "\n\t");
239 }
240 if (gb < 8) {
241 fprintf(pDumpFile, "%06x ", ((gi->block[rd].decmlt[ch][i] + (1 << (7 - gb))) >> (8 - gb)) & 0xffffff);
242 } else {
243 fprintf(pDumpFile, "%06x ", (gi->block[rd].decmlt[ch][i] << (gb - 8)) & 0xffffff);
244 }
245 }
246 fprintf(pDumpFile, "\n");
247}
248
249void ra_debug_dump_overlap(HGecko2Decoder hGecko2Decoder, int gb)
250{
251 Gecko2Info *gi;
252 unsigned rd;
253 unsigned ch, i;
254
255 gi = (Gecko2Info *)hGecko2Decoder;
256 rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
257 ch = READ_MPEG_REG(TRACE_REG0);
258 read_from_24bit_linear_format((M_OVERLAP << 1), gi->db.overlap[ch], 1024);
259 for (i = 0; i < gi->nSamples; i++) {
260 if (!(i & 7)) {
261 fprintf(pDumpFile, "\n\t");
262 }
263 if (gb < 8) {
264 fprintf(pDumpFile, "%06x ", ((gi->db.overlap[ch][i] + (1 << (7 - gb))) >> (8 - gb)) & 0xffffff);
265 } else {
266 fprintf(pDumpFile, "%06x ", (gi->db.overlap[ch][i] << (gb - 8)) & 0xffffff);
267 }
268 }
269 fprintf(pDumpFile, "\n");
270}
271
272unsigned dbg_frame = 0;
273void ra_debug(HGecko2Decoder hGecko2Decoder)
274{
275 static short cur_breakpoint;
276 Gecko2Info *gi;
277 unsigned rd;
278 DecodeInfo *di;
279 unsigned ch, i, j;
280 short *pcm_output;
281
282 if ((READ_MPEG_REG(TRACE_CMD) & 0x8000) == 0) {
283 return;
284 }
285
286 gi = (Gecko2Info *)hGecko2Decoder;
287 rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
288 di = &gi->block[rd];
289 ch = READ_MPEG_REG(TRACE_REG0);
290
291 cur_breakpoint = READ_MPEG_REG(TRACE_CMD) & 0x7fff;
292 if (cur_breakpoint) {
293 switch (cur_breakpoint) {
294 case BP_NEW_FRAME:
295 fprintf(pDumpFile, "\n----- Frame %d in %d-----\n", ++FrameCount, rd);
296 printf("Frame %d in %d-----\n", FrameCount, rd);
297 if (FrameCount >= dbg_frame) {
298 WRITE_MPEG_REG(TRACE_MASK, BP_NEW_FRAME | BP_DECODE_INFO/*|BP_BEFORE_INVERSE_TRANSFORM|BP_PREMULTIPLY|BP_BITREVERSE|BP_R8FIRSTPASS|BP_R4CORE*/ | BP_POSTMULTIPLY | BP_GAIN_CHANGES | BP_DEBUG);
299 }
300
301 WRITE_MPEG_REG(TRACE_CMD, 0);
302 break;
303 case BP_DECODE_INFO:
304 read_from_16bit_linear_format((M_LMEM16_DUMP << 1), (short*)&gi->block[rd], 128);
305 fprintf(pDumpFile, "decode info: %d\n", rd);
306 fprintf(pDumpFile, "\tlost_flag: %d\n", di->lostflag);
307 fprintf(pDumpFile, "\tChannels: %d\n", di->nChannels);
308 fprintf(pDumpFile, "\tSamples: %d\n", di->nSamples);
309 fprintf(pDumpFile, "\txformIdx: %d\n", di->xformIdx);
310 fprintf(pDumpFile, "\tgbMin: %d %d\n", di->gbMin[0], di->gbMin[1]);
311 fprintf(pDumpFile, "\tgbOverlap: %d %d\n", READ_MPEG_REG(MREG_AUDIO_CTRL_REG2) & 0xff, READ_MPEG_REG(MREG_AUDIO_CTRL_REG2) >> 8);
312 fprintf(pDumpFile, "\txbits: %d %d %d %d\n", di->xbits[0][0], di->xbits[0][1], di->xbits[1][0], di->xbits[1][1]);
313 fprintf(pDumpFile, "\tGain:\n");
314 for (ch = 0; ch < di->nChannels; ch++) {
315 for (j = 0; j < 2; j++) {
316 fprintf(pDumpFile, "\t\tChannel[%d][%d]: nats=%d maxExGain=%d\n", ch, j, di->dgainc[ch][j].nats, di->dgainc[ch][j].maxExGain);
317 if (di->dgainc[ch][j].nats) {
318 fprintf(pDumpFile, "\t\t\tloc: ");
319 for (i = 0; i < di->dgainc[ch][j].nats; i++) {
320 fprintf(pDumpFile, "%04x ", di->dgainc[ch][j].loc[i] & 0xffff);
321 }
322 fprintf(pDumpFile, "\n");
323
324 fprintf(pDumpFile, "\t\t\tgain:");
325 for (i = 0; i < di->dgainc[ch][j].nats; i++) {
326 fprintf(pDumpFile, "%04x ", di->dgainc[ch][j].gain[i] & 0xffff);
327 }
328 fprintf(pDumpFile, "\n");
329 }
330 }
331 }
332 WRITE_MPEG_REG(TRACE_CMD, 0);
333 break;
334 case BP_BEFORE_INVERSE_TRANSFORM:
335 fprintf(pDumpFile, "\nBefore Inverse transform:%d", READ_MPEG_REG(TRACE_REG0));
336 ra_debug_dump_decmlt(gi, 0);
337 WRITE_MPEG_REG(TRACE_CMD, 0);
338 break;
339 case BP_PREMULTIPLY:
340 fprintf(pDumpFile, "\nAfter PreMultiply:");
341 if (di->gbMin[ch] < 4) {
342 ra_debug_dump_decmlt(gi, -1);
343 } else {
344 ra_debug_dump_decmlt(gi, -1);
345 }
346 WRITE_MPEG_REG(TRACE_CMD, 0);
347 break;
348 case BP_BITREVERSE:
349 fprintf(pDumpFile, "\nAfter BitReverse:");
350 if (di->gbMin[ch] < 4) {
351 ra_debug_dump_decmlt(gi, -1);
352 } else {
353 ra_debug_dump_decmlt(gi, -1);
354 }
355 WRITE_MPEG_REG(TRACE_CMD, 0);
356 break;
357 case BP_R8FIRSTPASS:
358 fprintf(pDumpFile, "\nAfter R8FirstPass:");
359 if (di->gbMin[ch] < 4) {
360 ra_debug_dump_decmlt(gi, -1);
361 } else {
362 ra_debug_dump_decmlt(gi, -1);
363 }
364 WRITE_MPEG_REG(TRACE_CMD, 0);
365 break;
366 case BP_R4CORE:
367 fprintf(pDumpFile, "\nAfter R4Core:");
368 if (di->gbMin[ch] < 4) {
369 ra_debug_dump_decmlt(gi, -4);
370 } else {
371 ra_debug_dump_decmlt(gi, -4);
372 }
373 WRITE_MPEG_REG(TRACE_CMD, 0);
374 break;
375 case BP_POSTMULTIPLY:
376 fprintf(pDumpFile, "\nAfter PostMultiply:");
377 ra_debug_dump_decmlt(gi, -7);
378 WRITE_MPEG_REG(TRACE_CMD, 0);
379 break;
380 case BP_GAIN_CHANGES:
381 read_from_16bit_linear_format((M_LMEM16_DUMP << 1), (short*)&gi->block[rd], 128);
382 fprintf(pDumpFile, "\nAfter CalcGainChanges:");
383 fprintf(pDumpFile, "\n\tgainc0->maxExGain=%04x, gainc1->maxExGain=%04x", di->dgainc[ch][0].maxExGain & 0xffff, di->dgainc[ch][1].maxExGain & 0xffff);
384 fprintf(pDumpFile, "\n\texgain:");
385 for (i = 0; i < 2 * NPARTS + 1; i++) {
386 if ((i % NPARTS) == 0) {
387 fprintf(pDumpFile, "\n\t\t");
388 }
389 fprintf(pDumpFile, "%04x ", di->exgain[i] & 0xffff);
390 }
391 fprintf(pDumpFile, "\n");
392 WRITE_MPEG_REG(TRACE_CMD, 0);
393 break;
394 case BP_PCM:
395 pcm_output = AVMem_calloc(1024, sizeof(short));
396 ch = READ_MPEG_REG(TRACE_REG0);
397 read_from_16bit_linear_format((M_LMEM16_DUMP << 1), (short*)pcm_output, di->nSamples);
398 fprintf(pDumpFile, "PCM:\n");
399 for (i = 0; i < di->nSamples; i++) {
400 if (!(i & 31)) {
401 fprintf(pDumpFile, "\n\t");
402 }
403 fprintf(pDumpFile, "%02x ", (*(pcm_output + i) >> 8) & 0xff);
404 }
405 fprintf(pDumpFile, "\n");
406 AVMem_free(pcm_output);
407 WRITE_MPEG_REG(TRACE_CMD, 0);
408 break;
409 case BP_OVERLAP:
410 fprintf(pDumpFile, "\nOverlap:");
411 ra_debug_dump_overlap(gi, READ_MPEG_REG(MREG_AUDIO_CTRL_REG2));
412 WRITE_MPEG_REG(TRACE_CMD, 0);
413 break;
414 case BP_DEBUG:
415 fprintf(pDumpFile, "%06x %06x\n", ((READ_MPEG_REG(TRACE_REG0) << 8) | (READ_MPEG_REG(TRACE_REG1) & 0xff)), (READ_MPEG_REG(TRACE_REG2) << 8) | ((READ_MPEG_REG(TRACE_REG1) >> 8) & 0xff));
416 WRITE_MPEG_REG(TRACE_CMD, 0);
417 break;
418 default:
419 printf("breakpoint not defined\n");
420 break;
421 }
422 }
423}
424#endif
425
426/**************************************************************************************
427 * Function: Gecko2InitDecoder
428 *
429 * Description: initialize the fixed-point Gecko2 audio decoder
430 *
431 * Inputs: number of samples per frame
432 * number of channels
433 * number of frequency regions coded
434 * number of encoded bits per frame
435 * number of samples per second
436 * start region for coupling (joint stereo only)
437 * number of bits for each coupling scalefactor (joint stereo only)
438 * pointer to receive number of frames of coding delay
439 *
440 * Outputs: number of frames of coding delay (i.e. discard the PCM output from
441 * the first *codingDelay calls to Gecko2Decode())
442 *
443 * Return: instance pointer, 0 if error (malloc fails, unsupported mode, etc.)
444 *
445 * Notes: this implementation is fully reentrant and thread-safe - the
446 * HGecko2Decoder instance pointer tracks all the state variables
447 * for each instance
448 **************************************************************************************/
449HGecko2Decoder Gecko2InitDecoder(int nSamples, int nChannels, int nRegions, int nFrameBits, int sampRate,
450 int cplStart, int cplQbits, int *codingDelay)
451{
452 Gecko2Info *gi;
453
454#ifdef ENABLE_DUMP
455 pDumpFile = fopen("ra_dump.txt", "w");
456#endif
457
458 /* check parameters */
459 if (nChannels < 0 || nChannels > MAXNCHAN) {
460 return 0;
461 }
462 if (nRegions < 0 || nRegions > MAXREGNS) {
463 return 0;
464 }
465 if (nFrameBits < 0 || cplStart < 0) {
466 return 0;
467 }
468 if (cplQbits && (cplQbits < 2 || cplQbits > 6)) {
469 return 0;
470 }
471
472 gi = AllocateBuffers();
473 if (!gi) {
474 return 0;
475 }
476
477 /* if stereo, cplQbits == 0 means dual-mono, > 0 means joint stereo */
478 gi->jointStereo = (nChannels == 2) && (cplQbits > 0);
479
480 gi->nSamples = nSamples;
481 gi->nChannels = nChannels;
482 gi->nRegions = nRegions;
483 gi->nFrameBits = nFrameBits;
484 if (gi->nChannels == 2 && !gi->jointStereo) {
485 gi->nFrameBits /= 2;
486 }
487 gi->sampRate = sampRate;
488
489 gi->rd = 0;
490 gi->wr = 0;
491
492 //#ifndef USE_C_DECODER
493 // WRITE_MPEG_REG(MREG_AUDIO_CTRL_REG5, gi->rd);
494 // WRITE_MPEG_REG(MREG_AUDIO_CTRL_REG6, gi->wr);
495 //#endif
496
497 if (gi->jointStereo) {
498 /* joint stereo */
499 gi->cplStart = cplStart;
500 gi->cplQbits = cplQbits;
501 gi->rateBits = 5;
502 if (gi->nSamples > 256) {
503 gi->rateBits++;
504 }
505 if (gi->nSamples > 512) {
506 gi->rateBits++;
507 }
508 } else {
509 /* mono or dual-mono */
510 gi->cplStart = 0;
511 gi->cplQbits = 0;
512 gi->rateBits = 5;
513 }
514
515 gi->cRegions = gi->nRegions + gi->cplStart;
516 gi->nCatzns = (1 << gi->rateBits);
517 gi->lfsr[0] = gi->lfsr[1] = ('k' | 'e' << 8 | 'n' << 16 | 'c' << 24); /* well-chosen seed for dither generator */
518
519 /* validate tranform size */
520 if (gi->nSamples == 256) {
521 gi->xformIdx = 0;
522 } else if (gi->nSamples == 512) {
523 gi->xformIdx = 1;
524 } else if (gi->nSamples == 1024) {
525 gi->xformIdx = 2;
526 } else {
527 Gecko2FreeDecoder(gi);
528 return 0;
529 }
530
531 /* this is now 2, since lookahead MLT has been removed */
532 *codingDelay = CODINGDELAY;
533
534#ifdef DBG_AMRISC
535 ra_debug_init();
536#endif
537
538 return (HGecko2Decoder)gi;
539}
540
541/**************************************************************************************
542 * Function: Gecko2FreeDecoder
543 *
544 * Description: free the fixed-point Gecko2 audio decoder
545 *
546 * Inputs: HGecko2Decoder instance pointer returned by Gecko2InitDecoder()
547 *
548 * Outputs: none
549 *
550 * Return: none
551 **************************************************************************************/
552void Gecko2FreeDecoder(HGecko2Decoder hGecko2Decoder)
553{
554 Gecko2Info *gi = (Gecko2Info *)hGecko2Decoder;
555
556#ifdef ENABLE_DUMP
557 if (pDumpFile) {
558 fclose(pDumpFile);
559 }
560#endif
561
562 if (!gi) {
563 return;
564 }
565
566 FreeBuffers(gi);
567
568 return;
569}
570
571/**************************************************************************************
572 * Function: Gecko2ClearBadFrame
573 *
574 * Description: zero out pcm buffer if error decoding Gecko2 frame
575 *
576 * Inputs: pointer to initialized Gecko2Info struct
577 * pointer to pcm output buffer
578 *
579 * Outputs: zeroed out pcm buffer
580 * zeroed out data buffers (as if codec had been reinitialized)
581 *
582 * Return: none
583 **************************************************************************************/
584static void Gecko2ClearBadFrame(Gecko2Info *gi, short *outbuf)
585{
586 int i, ch;
587
588 if (!gi || gi->nSamples * gi->nChannels > MAXNSAMP * MAXNCHAN || gi->nSamples * gi->nChannels < 0) {
589 return;
590 }
591
592 /* clear PCM buffer */
593 for (i = 0; i < gi->nSamples * gi->nChannels; i++) {
594 outbuf[i] = 0;
595 }
596
597 /* clear internal data buffers */
598 for (ch = 0; ch < gi->nChannels; ch++) {
599 for (i = 0; i < gi->nSamples; i++) {
600 gi->db.decmlt[ch][i] = 0;
601 gi->db.overlap[ch][i] = 0;
602 }
603 gi->xbits[ch][0] = gi->xbits[ch][1] = 0;
604 }
605
606}
607
608void ProduceDecodeInfo(HGecko2Decoder hGecko2Decoder, unsigned timestamp)
609{
610#ifndef USE_C_DECODER
611 Gecko2Info *gi = (Gecko2Info *)hGecko2Decoder;
612 gi->wr = READ_MPEG_REG(MREG_AUDIO_CTRL_REG6);
613 gi->block[gi->wr].adts_hi = timestamp >> 16;
614 gi->block[gi->wr].adts_lo = timestamp & 0xffff;
615 gi->block[gi->wr].lostflag = gi->lostflag;
616 gi->block[gi->wr].jointflag = gi->jointStereo;
617 gi->block[gi->wr].nChannels = gi->nChannels;
618 gi->block[gi->wr].nSamples = gi->nSamples;
619 if (gi->sampRate <= 12000) {
620 gi->block[gi->wr].sampRate = 4;
621 } else if (gi->sampRate <= 24000) {
622 gi->block[gi->wr].sampRate = 2;
623 } else {
624 gi->block[gi->wr].sampRate = 1;
625 }
626 gi->block[gi->wr].xformIdx = gi->xformIdx;
627 memcpy(gi->block[gi->wr].gbMin, gi->gbMin, MAXNCHAN * sizeof(short));
628 memcpy(gi->block[gi->wr].xbits, gi->xbits, 2 * MAXNCHAN * sizeof(short));
629 CopyGainInfo(&gi->block[gi->wr].dgainc[0][0], &gi->dgainc[0][0]);
630 CopyGainInfo(&gi->block[gi->wr].dgainc[0][1], &gi->dgainc[0][1]);
631 CopyGainInfo(&gi->block[gi->wr].dgainc[1][0], &gi->dgainc[1][0]);
632 CopyGainInfo(&gi->block[gi->wr].dgainc[1][1], &gi->dgainc[1][1]);
633 gi->block[gi->wr].overlap = &gi->db.overlap;
634 write_to_16bit_linear_format((gi->wr) * 256, (short*)&gi->block[gi->wr], 128);
635 write_to_24bit_linear_format(MAXDECBUF * 256 + gi->wr * 2 * 1024 * 3, &(gi->db.decmlt[0][0]), 1024, gi->gbMin[0], 1);
636 write_to_24bit_linear_format(MAXDECBUF * 256 + gi->wr * 2 * 1024 * 3 + 1024 * 3, &(gi->db.decmlt[1][0]), 1024, gi->gbMin[1], 1);
637 gi->wr++;
638 gi->wr &= MAXDECBUF - 1;
639 WRITE_MPEG_REG(MREG_AUDIO_CTRL_REG6, gi->wr);
640#endif
641}
642
643int GetDecodeInfo(HGecko2Decoder hGecko2Decoder)
644{
645#ifndef USE_C_DECODER
646 Gecko2Info *gi = (Gecko2Info *)hGecko2Decoder;
647 gi->rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
648 gi->wr = READ_MPEG_REG(MREG_AUDIO_CTRL_REG6);
649
650 while (((gi->wr + 1) & (MAXDECBUF - 1)) == gi->rd) {
651 gi->rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
652 AVTimeDly(5);
653 if (AVTaskDelReq(OS_ID_SELF) == OS_TASK_DEL_REQ) {
654 return 0;
655 }
656 }
657#endif
658 return 1;
659}
660
661/**************************************************************************************
662 * Function: Gecko2Decode
663 *
664 * Description: decode one frame of audio data
665 *
666 * Inputs: HGecko2Decoder instance pointer returned by Gecko2InitDecoder()
667 * pointer to one encoded frame
668 * (nFrameBits / 8 bytes of data, byte-aligned)
669 * flag indicating lost frame (lostflag != 0 means lost)
670 * pointer to receive one decoded frame of PCM
671 *
672 * Outputs: one frame (nSamples * nChannels 16-bit samples) of decoded PCM
673 *
674 * Return: 0 if frame decoded okay, error code (< 0) if error
675 *
676 * Notes: to reduce memory and CPU usage, this only implements one-sided
677 * (backwards) interpolation for error concealment (no lookahead)
678 **************************************************************************************/
679int Gecko2Decode(HGecko2Decoder hGecko2Decoder, unsigned char *codebuf, int lostflag, short *outbuf, unsigned timestamp)
680{
681 int i, ch, availbits;
682 Gecko2Info *gi = (Gecko2Info *)hGecko2Decoder;
683
684#ifdef ENABLE_DUMP
685 int j;
686#endif
687
688 if (!gi) {
689 return -1;
690 }
691
692 gi->lostflag = lostflag;
693 if (GetDecodeInfo(hGecko2Decoder)) {
694 if (!gi->lostflag) {
695 /* current frame is valid, decode it */
696 if (gi->jointStereo) {
697 /* decode gain control info, coupling coefficients, and power envlope */
698 availbits = DecodeSideInfo(gi, codebuf, gi->nFrameBits, 0);
699 if (availbits < 0) {
700 Gecko2ClearBadFrame(gi, outbuf);
701 return ERR_GECKO2_INVALID_SIDEINFO;
702 }
703
704 /* reconstruct power envelope */
705 CategorizeAndExpand(gi, availbits);
706
707 /* reconstruct full MLT, including stereo decoupling */
708 gi->gbMin[0] = gi->gbMin[1] = DecodeTransform(gi, gi->db.decmlt[0], availbits, &gi->lfsr[0], 0);
709 JointDecodeMLT(gi, gi->db.decmlt[0], gi->db.decmlt[1]);
710 gi->xbits[1][1] = gi->xbits[0][1];
711 } else {
712 for (ch = 0; ch < gi->nChannels; ch++) {
713 /* decode gain control info and power envlope */
714 availbits = DecodeSideInfo(gi, codebuf + (ch * gi->nFrameBits >> 3), gi->nFrameBits, ch);
715 if (availbits < 0) {
716 Gecko2ClearBadFrame(gi, outbuf);
717 return ERR_GECKO2_INVALID_SIDEINFO;
718 }
719
720 /* reconstruct power envelope */
721 CategorizeAndExpand(gi, availbits);
722
723 /* reconstruct full MLT */
724 gi->gbMin[ch] = DecodeTransform(gi, gi->db.decmlt[ch], availbits, &gi->lfsr[ch], ch);
725
726 /* zero out non-coded regions */
727 for (i = gi->nRegions * NBINS; i < gi->nSamples; i++) {
728 gi->db.decmlt[ch][i] = 0;
729 }
730 }
731 }
732
733#ifdef ENABLE_DUMP
734 if (DumpMask & DUMP_GAIN) {
735 fprintf(pDumpFile, "Gain:\n");
736 for (ch = 0; ch < gi->nChannels; ch++) {
737 for (j = 0; j < 2; j++) {
738 fprintf(pDumpFile, "\tChannel[%d][%d]: nats=%d maxExGain=%d\n", ch, j, gi->dgainc[ch][j].nats, gi->dgainc[ch][j].maxExGain);
739 if (gi->dgainc[ch][j].nats) {
740 fprintf(pDumpFile, "\t\tloc: ");
741 for (i = 0; i < gi->dgainc[ch][j].nats; i++) {
742 fprintf(pDumpFile, "%08x ", gi->dgainc[ch][j].loc[i]);
743 }
744 fprintf(pDumpFile, "\n");
745
746 fprintf(pDumpFile, "\t\tgain:");
747 for (i = 0; i < gi->dgainc[ch][j].nats; i++) {
748 fprintf(pDumpFile, "%08x ", gi->dgainc[ch][j].gain[i]);
749 }
750 fprintf(pDumpFile, "\n");
751 }
752 }
753 }
754 }
755 if ((DumpMask & DUMP_CPL) && (gi->jointStereo)) {
756 fprintf(pDumpFile, "Couple:\n");
757 fprintf(pDumpFile, "\t");
758 for (i = cplband[gi->cplStart]; i <= cplband[gi->nRegions - 1]; i++) {
759 fprintf(pDumpFile, "%08x ", gi->db.cplindex[i]);
760 }
761 fprintf(pDumpFile, "\n");
762 }
763 if (DumpMask & DUMP_ENV) {
764 fprintf(pDumpFile, "Envelope:\n");
765 fprintf(pDumpFile, "\t");
766 for (i = 0; i < gi->cRegions; i++) {
767 fprintf(pDumpFile, "%04x ", gi->db.rmsIndex[i] & 0xffff);
768 if ((i % 10) == 9) {
769 fprintf(pDumpFile, "\n\t");
770 }
771 }
772 fprintf(pDumpFile, "\n");
773
774 for (ch = 0; ch < gi->nChannels; ch++) {
775 fprintf(pDumpFile, "\trmsMax[%d]=%08x\n", ch, gi->rmsMax[ch]);
776 }
777 }
778 if (DumpMask & DUMP_HUFF) {
779 fprintf(pDumpFile, "Huffman:\n");
780 for (ch = 0; ch < gi->nChannels; ch++) {
781 fprintf(pDumpFile, "\tgbMin[%d]=%08x\n", ch, gi->gbMin[ch]);
782 }
783 }
784 if (DumpMask & DUMP_QUANT) {
785 fprintf(pDumpFile, "Dequant:\n");
786 for (ch = 0; ch < gi->nChannels; ch++) {
787 fprintf(pDumpFile, "\tchannel %d:", ch);
788 for (i = 0; i < MAXNSAMP; i++) {
789 if (!(i & 7)) {
790 fprintf(pDumpFile, "\n\t");
791 }
792 fprintf(pDumpFile, "%06x ", ((gi->db.decmlt[ch][i] + 0x80) >> 8) & 0xffffff);
793 }
794 fprintf(pDumpFile, "\n");
795 }
796 }
797#endif // ENABLE_DUMP
798
799#ifdef USE_C_DECODER
800 /* inverse transform, without window or overlap-add */
801 for (ch = 0; ch < gi->nChannels; ch++) {
802 IMLTNoWindow(gi->xformIdx, gi->db.decmlt[ch], gi->gbMin[ch]);
803 }
804#endif
805 }
806
807 ProduceDecodeInfo(hGecko2Decoder, timestamp);
808#ifdef DBG_AMRISC
809 gi->rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
810 gi->wr = READ_MPEG_REG(MREG_AUDIO_CTRL_REG6);
811 while (gi->rd != gi->wr) {
812 ra_debug(gi);
813 gi->rd = READ_MPEG_REG(MREG_AUDIO_CTRL_REG5);
814 }
815#endif
816#ifdef USE_C_DECODER
817 for (ch = 0; ch < gi->nChannels; ch++) {
818 /* apply synthesis window, gain window, then overlap-add (interleaves stereo PCM LRLR...) */
819 if (gi->dgainc[ch][0].nats || gi->dgainc[ch][1].nats || gi->xbits[ch][0] || gi->xbits[ch][1]) {
820 DecWindowWithAttacks(gi->xformIdx, gi->db.decmlt[ch], gi->db.overlap[ch], outbuf + ch, gi->nChannels, &gi->dgainc[ch][0], &gi->dgainc[ch][1], gi->xbits[ch]);
821 } else {
822 DecWindowNoAttacks(gi->xformIdx, gi->db.decmlt[ch], gi->db.overlap[ch], outbuf + ch, gi->nChannels);
823 }
824
825 /* save gain settings for overlap */
826 CopyGainInfo(&gi->dgainc[ch][0], &gi->dgainc[ch][1]);
827 gi->xbits[ch][0] = gi->xbits[ch][1];
828 }
829#endif
830 }
831
832 return 0;
833}
834