Commit RELEASE-NOTES line for the wgCategories js variable I added some time ago.
[lhc/web/wiklou.git] / js2 / mwEmbed / libEmbedVideo / binPlayers / omtk-fx / src / as / org / omtk / vorbis / AudioPacket.as
1 /*
2
3 Copyright 2008 Tor-Einar Jarnbjo
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 */
18
19 package org.omtk.vorbis {
20
21 import flash.utils.getTimer;
22 import flash.utils.ByteArray;
23 import org.omtk.ogg.*;
24 import org.omtk.util.BitByteArray;
25
26 public class AudioPacket {
27
28 private var modeNumber:int;
29 private var mode:Mode;
30 private var mapping:Mapping;
31 private var n:int;
32
33 private var blockFlag:Boolean;
34 private var previousWindowFlag:Boolean;
35 private var nextWindowFlag:Boolean;
36
37 private var windowCenter:int;
38 private var leftWindowStart:int;
39 private var leftWindowEnd:int;
40 private var leftN:int;
41 private var rightWindowStart:int;
42 private var rightWindowEnd:int;
43 private var rightN:int;
44
45 private var window:Vector.<Number>;
46 private var freq0:Vector.<Number>;
47 private var freq1:Vector.<Number>;
48 private var pcm0:Vector.<Number>;
49 private var pcm1:Vector.<Number>;
50
51 private var channelFloors:Vector.<Floor>;
52 private var noResidues:Vector.<Boolean>;
53
54 private var _lastPacket: Boolean;
55 private var _lastGranulePosition: int;
56
57 public function AudioPacket(vorbis:VorbisStream, packet: OggPacket, currentGranulePosition: int) {
58
59 var source: BitByteArray = packet.data;
60 _lastPacket = packet.lastPacket;
61 _lastGranulePosition = packet.lastGranulePosition;
62
63 var i:int;
64 var j:int;
65 var k:int;
66
67 var sHeader:SetupHeader = vorbis.setupHeader;
68 var iHeader:IdentificationHeader = vorbis.identificationHeader;
69 var modes:Vector.<Mode> = sHeader.modes;
70 var mappings:Vector.<Mapping> = sHeader.mappings;
71 var residues:Vector.<Residue> = sHeader.residues;
72 var channels:int = iHeader.channels;
73
74 if (source.readUnsignedBitwiseInt(1) != 0) {
75 throw new Error("Packet type mismatch when trying to create an audio packet.");
76 }
77
78 modeNumber = source.readUnsignedBitwiseInt(Util.ilog(modes.length - 1));
79
80 mode = modes[modeNumber];
81
82 if(mode == null) {
83 throw new Error("Reference to invalid mode in audio packet.");
84 }
85
86 mapping = mappings[mode.mapping];
87
88 var magnitudes:Vector.<int> = mapping.magnitudes;
89 var angles:Vector.<int> = mapping.angles;
90
91 blockFlag = mode.blockFlag;
92
93 var blockSize0:int = iHeader.blockSize0;
94 var blockSize1:int = iHeader.blockSize1;
95
96 n = blockFlag ? blockSize1 : blockSize0;
97
98 if (blockFlag) {
99 previousWindowFlag = source.readBit();
100 nextWindowFlag = source.readBit();
101 }
102
103 windowCenter = n / 2;
104
105 if (blockFlag && !previousWindowFlag) {
106 leftWindowStart = n / 4 - blockSize0 / 4;
107 leftWindowEnd = n / 4 + blockSize0 / 4;
108 leftN = blockSize0 / 2;
109 } else {
110 leftWindowStart = 0;
111 leftWindowEnd = n / 2;
112 leftN = windowCenter;
113 }
114
115 if (blockFlag && !nextWindowFlag) {
116 rightWindowStart = n * 3 / 4 - blockSize0 / 4;
117 rightWindowEnd = n * 3 / 4 + blockSize0 / 4;
118 rightN = blockSize0 / 2;
119 } else {
120 rightWindowStart = windowCenter;
121 rightWindowEnd = n;
122 rightN = n / 2;
123 }
124
125 window = getComputedWindow(vorbis);
126
127 channelFloors = new Vector.<Floor>(channels, true);
128 noResidues = new Vector.<Boolean>(channels, true);
129
130 freq0 = new Vector.<Number>(n, true);
131 freq1 = new Vector.<Number>(n, true);
132 pcm0 = new Vector.<Number>(n, true);
133 pcm1 = new Vector.<Number>(n, true);
134
135 var allFloorsEmpty: Boolean = true;
136 var submapNumber: int;
137 var floorNumber: int;
138 var decodedFloor: Floor;
139
140 for(i = 0; i < channels; i++) {
141 submapNumber = mapping.mux[i];
142 floorNumber = mapping.submapFloors[submapNumber];
143 decodedFloor = sHeader.floors[floorNumber].decodeFloor(vorbis, source);
144 channelFloors[i] = decodedFloor;
145 noResidues[i] = decodedFloor == null;
146 if (decodedFloor != null) {
147 allFloorsEmpty = false;
148 }
149 }
150
151 if(allFloorsEmpty) {
152 return;
153 }
154
155 var mag: int;
156 var ang: int;
157
158 for(i = 0; i < magnitudes.length; i++) {
159 mag = magnitudes[i];
160 ang = angles[i];
161 if (!noResidues[mag] || !noResidues[ang]) {
162 noResidues[mag] = false;
163 noResidues[ang] = false;
164 }
165 }
166
167 var ch: int;
168 var doNotDecodeFlags: Vector.<Boolean>;
169 var residue:Residue;
170
171 for(i = 0; i < mapping.submaps; i++) {
172
173 doNotDecodeFlags = new Vector.<Boolean>();
174
175 for(j = 0; j < channels; j++) {
176 if(mapping.mux[j] == i) {
177 doNotDecodeFlags.push(noResidues[j]);
178 }
179 }
180
181 residue = residues[mapping.submapResidues[i]];
182
183 residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, freq0, freq1);
184 }
185
186 var a: Number;
187 var m: Number;
188
189 for(i = mapping.couplingSteps - 1; i >= 0; i--) {
190
191 mag = magnitudes[i];
192 ang = angles[i];
193
194 for (j = 0; j < freq0.length; j++) {
195
196 a = ang == 0 ? freq0[j] : freq1[j];
197 m = mag == 0 ? freq0[j] : freq1[j];
198
199 if(a > 0) {
200 if(ang == 0) {
201 freq0[j] = m > 0 ? m - a : m + a;
202 }
203 else {
204 freq1[j] = m > 0 ? m - a : m + a;
205 }
206 }
207 else {
208 if(mag == 0) {
209 freq0[j] = m > 0 ? m + a : m - a;
210 }
211 else {
212 freq1[j] = m > 0 ? m + a : m - a;
213 }
214
215 if(ang == 0) {
216 freq0[j] = m;
217 }
218 else {
219 freq1[j] = m;
220 }
221 }
222 }
223 }
224
225 if(channelFloors[0] != null) {
226 Floor(channelFloors[0]).computeFloor(freq0);
227 }
228
229 if(channelFloors[1] != null) {
230 Floor(channelFloors[1]).computeFloor(freq1);
231 }
232
233 // perform an inverse mdct to all channels
234 var mdct: Mdct = blockFlag ? iHeader.mdct1 : iHeader.mdct0;
235 mdct.imdct(freq0, window, pcm0);
236 mdct.imdct(freq1, window, pcm1);
237
238 if(_lastPacket) {
239 if(leftWindowEnd - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
240 leftWindowEnd = leftWindowStart + _lastGranulePosition - currentGranulePosition
241 }
242 if(rightWindowStart - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
243 rightWindowStart = leftWindowStart + _lastGranulePosition - currentGranulePosition
244 }
245 }
246
247 }
248
249 private function getComputedWindow(vorbis:VorbisStream):Vector.<Number> {
250
251 var i:int;
252
253 var ix:int = (blockFlag ? 4 : 0) + (previousWindowFlag ? 2 : 0) + (nextWindowFlag ? 1 : 0);
254 var w:Vector.<Number> = vorbis.windows[ix];
255
256 var x:Number;
257
258 if (w == null) {
259 w = new Vector.<Number>(n);
260
261 for(i = 0; i < leftWindowStart; i++) {
262 w[i] = 0;
263 }
264
265 for (i = 0; i < leftN; i++) {
266 x = (i + .5) / leftN * Math.PI / 2.;
267 x = Math.sin(x);
268 x *= x;
269 x *= Math.PI / 2.;
270 x = Math.sin(x);
271 w[i + leftWindowStart] = x;
272 }
273
274 for (i = leftWindowEnd; i < rightWindowStart; i++) {
275 w[i] = 1;
276 }
277
278 for (i = 0; i < rightN; i++) {
279 x = (rightN - i - .5) / rightN * Math.PI / 2.;
280 x = Math.sin(x);
281 x *= x;
282 x *= Math.PI / 2.;
283 x = Math.sin(x);
284 w[i + rightWindowStart] = x;
285 }
286
287 for(i = rightN + rightWindowStart; i < n; i++) {
288 w[i] = 0;
289 }
290
291 for(i = 0; i < w.length; i++) {
292 w[i] *= 0.5;
293 }
294
295 vorbis.windows[ix] = w;
296 }
297
298 return w;
299 }
300
301
302 public function readPcm(previousPacket:AudioPacket, target: ByteArray): int {
303
304 var j:int;
305 var j2:int;
306 var ppcm0:Vector.<Number> = previousPacket.pcm0;
307 var ppcm1:Vector.<Number> = previousPacket.pcm1;
308
309 j2 = previousPacket.rightWindowStart;
310
311 for(j = leftWindowStart; j < leftWindowEnd; j++) {
312 target.writeFloat(pcm0[j] + ppcm0[j2]);
313 target.writeFloat(pcm1[j] + ppcm1[j2++]);
314 }
315
316 for (j = leftWindowEnd; j < rightWindowStart; j++) {
317 target.writeFloat(pcm0[j]);
318 target.writeFloat(pcm1[j]);
319 }
320
321 return numberOfSamples;
322
323 }
324
325 public function get numberOfSamples():int {
326 return rightWindowStart - leftWindowStart;
327 }
328
329 public function get lastPacket(): Boolean {
330 return lastPacket;
331 }
332
333 public function get lastGranulePosition(): int {
334 return lastGranulePosition;
335 }
336
337 }
338
339
340 }