summaryrefslogtreecommitdiff
path: root/setedit/mp3/libamp/layer3.c
blob: a7cb92fcdc057ff71ce34255521ee2f93d22c763 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
*/

/* layer3.c  layer3 audio decoding
 *
 * Created by: tomislav uzelac  Mar  1 97
 * Last modified by: 
 */
#include "amp.h"
#include "audio.h"
#include "dump.h"
#include "getbits.h"
#include "getdata.h"
#include "huffman.h"
#include "misc2.h"
#include "rtbuf.h"
#include "transform.h"

#define LAYER3
#include "layer3.h"

/* this function decodes one layer3 audio frame, except for the header decoding
 * which is done in main() [audio.c]. returns 0 if everything is ok.
 */
int layer3_frame(struct AUDIO_HEADER *header,int cnt)
{
static struct SIDE_INFO info;

int gr,ch,sb,i;
int mean_frame_size,bitrate,fs,hsize,ssize;

/* we need these later, hsize is the size of header+side_info
*/
	if (header->ID) 
		if (header->mode==3) {
			nch=1;
			hsize=21;
		} else {
			nch=2;
			hsize=36;
		}
	else
		if (header->mode==3) {
			nch=1;
			hsize=13;
		} else {
			nch=2;
			hsize=21;
		}

/* crc increases hsize by 2
*/
	if (header->protection_bit==0) hsize+=2;


/* read layer3 specific side_info
*/
        getinfo(header,&info);


/* MPEG2 only has one granule
*/
	bitrate=t_bitrate[header->ID][3-header->layer][header->bitrate_index];
	fs=t_sampling_frequency[header->ID][header->sampling_frequency];
        if (header->ID) mean_frame_size=144000*bitrate/fs;
        else mean_frame_size=72000*bitrate/fs;


/* check if mdb is too big for the first few frames. this means that
 * a part of the stream could be missing. We must still fill the buffer
 *
 * don't forget to (re)initialise bclean_bytes to 0, and f_bdirty to FALSE!!!
 */
	if (f_bdirty) 
		if (info.main_data_begin > bclean_bytes) {
			fillbfr(mean_frame_size + header->padding_bit - hsize);
			bclean_bytes+=mean_frame_size + header->padding_bit - hsize;
			/* warn(" frame %d discarded, incomplete main_data\n",cnt); */
			return 0;
		} else {
			/* re-initialise */
			f_bdirty=FALSE;
			bclean_bytes=0;
		}
		
/* now update the data 'pointer' (counting in bits) according to
 * the main_data_begin information
 */
        data = 8 * ((append - info.main_data_begin) & (BUFFER_SIZE-1));


/* read into the buffer all bytes up to the start of next header
*/
        fillbfr(mean_frame_size + header->padding_bit - hsize);


/* these two should go away
*/
	t_l=&t_b8_l[header->ID][header->sampling_frequency][0];
	t_s=&t_b8_s[header->ID][header->sampling_frequency][0];

/* debug/dump stuff
*/
	if (A_DUMP_BINARY) dump((int *)info.part2_3_length);

/* decode the scalefactors and huffman data
 * this part needs to be enhanced for error robustness
 */
	for (gr=0;gr < ((header->ID) ? 2 : 1);gr++) {
		for (ch=0;ch<nch;ch++) {
			ssize=decode_scalefactors(&info,header,gr,ch);
			decode_huffman_data(&info,gr,ch,ssize);
		}
		
	/* requantization, stereo processing, reordering(shortbl)
	*/

		if (A_DOWNMIX && nch==2) requantize_downmix(gr,&info,header);
		else 
			if (header->mode!=1 || (header->mode==1 && header->mode_extension==0))
				for (ch=0;ch<nch;ch++) requantize_mono(gr,ch,&info,header);
			else requantize_ms(gr,&info,header);

	/* just which window?
	*/

	/* this is a very temporary, very ugly hack. 
	*/
		if (A_DOWNMIX) nch=1;

		for (ch=0; ch < (A_DOWNMIX ? 1:nch) ;ch++) {
		int win_type; /* same as in the standard, long=0, start=1 ,.... */
		int window_switching_flag = info.window_switching_flag[gr][ch];
		int block_type = info.block_type[gr][ch];
		int mixed_block_flag = info.mixed_block_flag[gr][ch];

		/* antialiasing butterflies
		*/
			if (!(window_switching_flag &&
			      block_type==2))
                                alias_reduction(ch);

			if (window_switching_flag &&
			    block_type==2 &&
			    mixed_block_flag)
				win_type=0;
			else
			        if (!window_switching_flag) win_type=0;
				else win_type=block_type;

		/* imdct ...
		*/
			for (sb=0;sb<2;sb++)
				imdct(win_type,sb,ch);

			if (window_switching_flag &&
			    block_type==2 &&
			    mixed_block_flag)
				win_type=2;

		/* no_of_imdcts tells us how many subbands from the top are all zero
		 * it is set by the requantize functions in misc2.c
		 */
			for (sb=2;sb<no_of_imdcts[ch];sb++)
				imdct(win_type,sb,ch);

			for (;sb<32;sb++) 
				for (i=0;i<18;i++) {
					res[sb][i]=s[ch][sb][i];
					s[ch][sb][i]=0.0f;
				}
	
		/* polyphase filterbank
		*/
			/* if (nch == 2) this was a bug, tomislav */
			        for (i=0;i<18;i++)
				        poly(ch,i);
		}

		printout();

		/* this is part2 of a particularily ugly hack. this should vanish as soon as nch isn't
		   a global variable anymore
		*/
		if (A_DOWNMIX && header->mode!=3) nch=2;

	}    /*  for (gr... */ 

	/* return status: 0 for ok, errors will be added
	*/
	return 0;
}