diff options
author | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
---|---|---|
committer | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
commit | 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch) | |
tree | 4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/de/jarnbjo/vorbis/AudioPacket.java | |
parent | dfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff) | |
download | rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.gz rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.zip |
Songdb java version, source. only 1.5 compatible
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/de/jarnbjo/vorbis/AudioPacket.java')
-rw-r--r-- | songdbj/de/jarnbjo/vorbis/AudioPacket.java | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/songdbj/de/jarnbjo/vorbis/AudioPacket.java b/songdbj/de/jarnbjo/vorbis/AudioPacket.java new file mode 100644 index 0000000000..90a54073c1 --- /dev/null +++ b/songdbj/de/jarnbjo/vorbis/AudioPacket.java | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * $ProjectName$ | ||
3 | * $ProjectRevision$ | ||
4 | * ----------------------------------------------------------- | ||
5 | * $Id$ | ||
6 | * ----------------------------------------------------------- | ||
7 | * | ||
8 | * $Author$ | ||
9 | * | ||
10 | * Description: | ||
11 | * | ||
12 | * Copyright 2002-2003 Tor-Einar Jarnbjo | ||
13 | * ----------------------------------------------------------- | ||
14 | * | ||
15 | * Change History | ||
16 | * ----------------------------------------------------------- | ||
17 | * $Log$ | ||
18 | * Revision 1.1 2005/07/11 15:42:36 hcl | ||
19 | * Songdb java version, source. only 1.5 compatible | ||
20 | * | ||
21 | * Revision 1.2 2004/09/21 06:39:06 shred | ||
22 | * Importe reorganisiert, damit Eclipse Ruhe gibt. ;-) | ||
23 | * | ||
24 | * Revision 1.1.1.1 2004/04/04 22:09:12 shred | ||
25 | * First Import | ||
26 | * | ||
27 | * Revision 1.2 2003/03/16 01:11:12 jarnbjo | ||
28 | * no message | ||
29 | * | ||
30 | * | ||
31 | */ | ||
32 | |||
33 | package de.jarnbjo.vorbis; | ||
34 | |||
35 | import java.io.IOException; | ||
36 | |||
37 | import de.jarnbjo.util.io.BitInputStream; | ||
38 | |||
39 | class AudioPacket { | ||
40 | |||
41 | private int modeNumber; | ||
42 | private Mode mode; | ||
43 | private Mapping mapping; | ||
44 | private int n; // block size | ||
45 | private boolean blockFlag, previousWindowFlag, nextWindowFlag; | ||
46 | |||
47 | private int windowCenter, leftWindowStart, leftWindowEnd, leftN, rightWindowStart, rightWindowEnd, rightN; | ||
48 | private float[] window; | ||
49 | private float[][] pcm; | ||
50 | private int[][] pcmInt; | ||
51 | |||
52 | private Floor[] channelFloors; | ||
53 | private boolean[] noResidues; | ||
54 | |||
55 | private final static float[][] windows=new float[8][]; | ||
56 | |||
57 | protected AudioPacket(final VorbisStream vorbis, final BitInputStream source) throws VorbisFormatException, IOException { | ||
58 | |||
59 | final SetupHeader sHeader=vorbis.getSetupHeader(); | ||
60 | final IdentificationHeader iHeader=vorbis.getIdentificationHeader(); | ||
61 | final Mode[] modes=sHeader.getModes(); | ||
62 | final Mapping[] mappings=sHeader.getMappings(); | ||
63 | final Residue[] residues=sHeader.getResidues(); | ||
64 | final int channels=iHeader.getChannels(); | ||
65 | |||
66 | if(source.getInt(1)!=0) { | ||
67 | throw new VorbisFormatException("Packet type mismatch when trying to create an audio packet."); | ||
68 | } | ||
69 | |||
70 | modeNumber=source.getInt(Util.ilog(modes.length-1)); | ||
71 | |||
72 | try { | ||
73 | mode=modes[modeNumber]; | ||
74 | } | ||
75 | catch(ArrayIndexOutOfBoundsException e) { | ||
76 | throw new VorbisFormatException("Reference to invalid mode in audio packet."); | ||
77 | } | ||
78 | |||
79 | mapping=mappings[mode.getMapping()]; | ||
80 | |||
81 | final int[] magnitudes=mapping.getMagnitudes(); | ||
82 | final int[] angles=mapping.getAngles(); | ||
83 | |||
84 | blockFlag=mode.getBlockFlag(); | ||
85 | |||
86 | final int blockSize0=iHeader.getBlockSize0(); | ||
87 | final int blockSize1=iHeader.getBlockSize1(); | ||
88 | |||
89 | n=blockFlag?blockSize1:blockSize0; | ||
90 | |||
91 | if(blockFlag) { | ||
92 | previousWindowFlag=source.getBit(); | ||
93 | nextWindowFlag=source.getBit(); | ||
94 | } | ||
95 | |||
96 | windowCenter=n/2; | ||
97 | |||
98 | if(blockFlag && !previousWindowFlag) { | ||
99 | leftWindowStart=n/4-blockSize0/4; | ||
100 | leftWindowEnd=n/4+blockSize0/4; | ||
101 | leftN=blockSize0/2; | ||
102 | } | ||
103 | else { | ||
104 | leftWindowStart=0; | ||
105 | leftWindowEnd=n/2; | ||
106 | leftN=windowCenter; | ||
107 | } | ||
108 | |||
109 | if(blockFlag && !nextWindowFlag) { | ||
110 | rightWindowStart=n*3/4-blockSize0/4; | ||
111 | rightWindowEnd=n*3/4+blockSize0/4; | ||
112 | rightN=blockSize0/2; | ||
113 | } | ||
114 | else { | ||
115 | rightWindowStart=windowCenter; | ||
116 | rightWindowEnd=n; | ||
117 | rightN=n/2; | ||
118 | } | ||
119 | |||
120 | window=getComputedWindow();//new double[n]; | ||
121 | |||
122 | channelFloors=new Floor[channels]; | ||
123 | noResidues=new boolean[channels]; | ||
124 | |||
125 | pcm=new float[channels][n]; | ||
126 | pcmInt=new int[channels][n]; | ||
127 | |||
128 | boolean allFloorsEmpty=true; | ||
129 | |||
130 | for(int i=0; i<channels; i++) { | ||
131 | int submapNumber=mapping.getMux()[i]; | ||
132 | int floorNumber=mapping.getSubmapFloors()[submapNumber]; | ||
133 | Floor decodedFloor=sHeader.getFloors()[floorNumber].decodeFloor(vorbis, source); | ||
134 | channelFloors[i]=decodedFloor; | ||
135 | noResidues[i]=decodedFloor==null; | ||
136 | if(decodedFloor!=null) { | ||
137 | allFloorsEmpty=false; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | if(allFloorsEmpty) { | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | for(int i=0; i<magnitudes.length; i++) { | ||
146 | if(!noResidues[magnitudes[i]] || | ||
147 | !noResidues[angles[i]]) { | ||
148 | |||
149 | noResidues[magnitudes[i]]=false; | ||
150 | noResidues[angles[i]]=false; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | Residue[] decodedResidues=new Residue[mapping.getSubmaps()]; | ||
155 | |||
156 | for(int i=0; i<mapping.getSubmaps(); i++) { | ||
157 | int ch=0; | ||
158 | boolean[] doNotDecodeFlags=new boolean[channels]; | ||
159 | for(int j=0; j<channels; j++) { | ||
160 | if(mapping.getMux()[j]==i) { | ||
161 | doNotDecodeFlags[ch++]=noResidues[j]; | ||
162 | } | ||
163 | } | ||
164 | int residueNumber=mapping.getSubmapResidues()[i]; | ||
165 | Residue residue=residues[residueNumber]; | ||
166 | |||
167 | residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, pcm); | ||
168 | } | ||
169 | |||
170 | |||
171 | for(int i=mapping.getCouplingSteps()-1; i>=0; i--) { | ||
172 | double newA=0, newM=0; | ||
173 | final float[] magnitudeVector=pcm[magnitudes[i]]; | ||
174 | final float[] angleVector=pcm[angles[i]]; | ||
175 | for(int j=0; j<magnitudeVector.length; j++) { | ||
176 | float a=angleVector[j]; | ||
177 | float m=magnitudeVector[j]; | ||
178 | if(a>0) { | ||
179 | //magnitudeVector[j]=m; | ||
180 | angleVector[j]=m>0?m-a:m+a; | ||
181 | } | ||
182 | else { | ||
183 | magnitudeVector[j]=m>0?m+a:m-a; | ||
184 | angleVector[j]=m; | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | for(int i=0; i<channels; i++) { | ||
190 | if(channelFloors[i]!=null) { | ||
191 | channelFloors[i].computeFloor(pcm[i]); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | // perform an inverse mdct to all channels | ||
196 | |||
197 | for(int i=0; i<channels; i++) { | ||
198 | MdctFloat mdct=blockFlag?iHeader.getMdct1():iHeader.getMdct0(); | ||
199 | mdct.imdct(pcm[i], window, pcmInt[i]); | ||
200 | } | ||
201 | |||
202 | } | ||
203 | |||
204 | private float[] getComputedWindow() { | ||
205 | int ix=(blockFlag?4:0)+(previousWindowFlag?2:0)+(nextWindowFlag?1:0); | ||
206 | float[] w=windows[ix]; | ||
207 | if(w==null) { | ||
208 | w=new float[n]; | ||
209 | |||
210 | for(int i=0;i<leftN;i++){ | ||
211 | float x=(float)((i+.5)/leftN*Math.PI/2.); | ||
212 | x=(float)Math.sin(x); | ||
213 | x*=x; | ||
214 | x*=(float)Math.PI/2.; | ||
215 | x=(float)Math.sin(x); | ||
216 | w[i+leftWindowStart]=x; | ||
217 | } | ||
218 | |||
219 | for(int i=leftWindowEnd; i<rightWindowStart; w[i++]=1.0f); | ||
220 | |||
221 | for(int i=0;i<rightN;i++){ | ||
222 | float x=(float)((rightN-i-.5)/rightN*Math.PI/2.); | ||
223 | x=(float)Math.sin(x); | ||
224 | x*=x; | ||
225 | x*=(float)Math.PI/2.; | ||
226 | x=(float)Math.sin(x); | ||
227 | w[i+rightWindowStart]=x; | ||
228 | } | ||
229 | |||
230 | windows[ix]=w; | ||
231 | } | ||
232 | return w; | ||
233 | } | ||
234 | |||
235 | protected int getNumberOfSamples() { | ||
236 | return rightWindowStart-leftWindowStart; | ||
237 | } | ||
238 | |||
239 | protected int getPcm(final AudioPacket previousPacket, final int[][] buffer) { | ||
240 | int channels=pcm.length; | ||
241 | int val; | ||
242 | |||
243 | // copy left window flank and mix with right window flank from | ||
244 | // the previous audio packet | ||
245 | for(int i=0; i<channels; i++) { | ||
246 | int j1=0, j2=previousPacket.rightWindowStart; | ||
247 | final int[] ppcm=previousPacket.pcmInt[i]; | ||
248 | final int[] tpcm=pcmInt[i]; | ||
249 | final int[] target=buffer[i]; | ||
250 | |||
251 | for(int j=leftWindowStart; j<leftWindowEnd; j++) { | ||
252 | val=ppcm[j2++]+tpcm[j]; | ||
253 | if(val>32767) val=32767; | ||
254 | if(val<-32768) val=-32768; | ||
255 | target[j1++]=val; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | // use System.arraycopy to copy the middle part (if any) | ||
260 | // of the window | ||
261 | if(leftWindowEnd+1<rightWindowStart) { | ||
262 | for(int i=0; i<channels; i++) { | ||
263 | System.arraycopy(pcmInt[i], leftWindowEnd, buffer[i], leftWindowEnd-leftWindowStart, rightWindowStart-leftWindowEnd); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | return rightWindowStart-leftWindowStart; | ||
268 | } | ||
269 | |||
270 | protected void getPcm(final AudioPacket previousPacket, final byte[] buffer) { | ||
271 | int channels=pcm.length; | ||
272 | int val; | ||
273 | |||
274 | // copy left window flank and mix with right window flank from | ||
275 | // the previous audio packet | ||
276 | for(int i=0; i<channels; i++) { | ||
277 | int ix=0, j2=previousPacket.rightWindowStart; | ||
278 | final int[] ppcm=previousPacket.pcmInt[i]; | ||
279 | final int[] tpcm=pcmInt[i]; | ||
280 | for(int j=leftWindowStart; j<leftWindowEnd; j++) { | ||
281 | val=ppcm[j2++]+tpcm[j]; | ||
282 | if(val>32767) val=32767; | ||
283 | if(val<-32768) val=-32768; | ||
284 | buffer[ix+(i*2)+1]=(byte)(val&0xff); | ||
285 | buffer[ix+(i*2)]=(byte)((val>>8)&0xff); | ||
286 | ix+=channels*2; | ||
287 | } | ||
288 | |||
289 | ix=(leftWindowEnd-leftWindowStart)*channels*2; | ||
290 | for(int j=leftWindowEnd; j<rightWindowStart; j++) { | ||
291 | val=tpcm[j]; | ||
292 | if(val>32767) val=32767; | ||
293 | if(val<-32768) val=-32768; | ||
294 | buffer[ix+(i*2)+1]=(byte)(val&0xff); | ||
295 | buffer[ix+(i*2)]=(byte)((val>>8)&0xff); | ||
296 | ix+=channels*2; | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | |||
301 | protected float[] getWindow() { | ||
302 | return window; | ||
303 | } | ||
304 | |||
305 | protected int getLeftWindowStart() { | ||
306 | return leftWindowStart; | ||
307 | } | ||
308 | |||
309 | protected int getLeftWindowEnd() { | ||
310 | return leftWindowEnd; | ||
311 | } | ||
312 | |||
313 | protected int getRightWindowStart() { | ||
314 | return rightWindowStart; | ||
315 | } | ||
316 | |||
317 | protected int getRightWindowEnd() { | ||
318 | return rightWindowEnd; | ||
319 | } | ||
320 | |||
321 | public int[][] getPcm() { | ||
322 | return pcmInt; | ||
323 | } | ||
324 | |||
325 | public float[][] getFreqencyDomain() { | ||
326 | return pcm; | ||
327 | } | ||
328 | } | ||