summaryrefslogtreecommitdiff
path: root/songdbj/de/jarnbjo/vorbis/AudioPacket.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/de/jarnbjo/vorbis/AudioPacket.java')
-rw-r--r--songdbj/de/jarnbjo/vorbis/AudioPacket.java328
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
33package de.jarnbjo.vorbis;
34
35import java.io.IOException;
36
37import de.jarnbjo.util.io.BitInputStream;
38
39class 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}