3 Copyright 2008 Tor-Einar Jarnbjo
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
9 http://www.apache.org/licenses/LICENSE-2.0
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.
19 package org.omtk.vorbis {
21 import flash.utils.getTimer;
22 import flash.utils.ByteArray;
23 import org.omtk.ogg.*;
24 import org.omtk.util.BitByteArray;
26 public class AudioPacket {
28 private var modeNumber:int;
29 private var mode:Mode;
30 private var mapping:Mapping;
33 private var blockFlag:Boolean;
34 private var previousWindowFlag:Boolean;
35 private var nextWindowFlag:Boolean;
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;
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>;
51 private var channelFloors:Vector.<Floor>;
52 private var noResidues:Vector.<Boolean>;
54 private var _lastPacket: Boolean;
55 private var _lastGranulePosition: int;
57 public function AudioPacket(vorbis:VorbisStream, packet: OggPacket, currentGranulePosition: int) {
59 var source: BitByteArray = packet.data;
60 _lastPacket = packet.lastPacket;
61 _lastGranulePosition = packet.lastGranulePosition;
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;
74 if (source.readUnsignedBitwiseInt(1) != 0) {
75 throw new Error("Packet type mismatch when trying to create an audio packet.");
78 modeNumber = source.readUnsignedBitwiseInt(Util.ilog(modes.length - 1));
80 mode = modes[modeNumber];
83 throw new Error("Reference to invalid mode in audio packet.");
86 mapping = mappings[mode.mapping];
88 var magnitudes:Vector.<int> = mapping.magnitudes;
89 var angles:Vector.<int> = mapping.angles;
91 blockFlag = mode.blockFlag;
93 var blockSize0:int = iHeader.blockSize0;
94 var blockSize1:int = iHeader.blockSize1;
96 n = blockFlag ? blockSize1 : blockSize0;
99 previousWindowFlag = source.readBit();
100 nextWindowFlag = source.readBit();
103 windowCenter = n / 2;
105 if (blockFlag && !previousWindowFlag) {
106 leftWindowStart = n / 4 - blockSize0 / 4;
107 leftWindowEnd = n / 4 + blockSize0 / 4;
108 leftN = blockSize0 / 2;
111 leftWindowEnd = n / 2;
112 leftN = windowCenter;
115 if (blockFlag && !nextWindowFlag) {
116 rightWindowStart = n * 3 / 4 - blockSize0 / 4;
117 rightWindowEnd = n * 3 / 4 + blockSize0 / 4;
118 rightN = blockSize0 / 2;
120 rightWindowStart = windowCenter;
125 window = getComputedWindow(vorbis);
127 channelFloors = new Vector.<Floor>(channels, true);
128 noResidues = new Vector.<Boolean>(channels, true);
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);
135 var allFloorsEmpty: Boolean = true;
136 var submapNumber: int;
137 var floorNumber: int;
138 var decodedFloor: Floor;
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;
158 for(i = 0; i < magnitudes.length; i++) {
161 if (!noResidues[mag] || !noResidues[ang]) {
162 noResidues[mag] = false;
163 noResidues[ang] = false;
168 var doNotDecodeFlags: Vector.<Boolean>;
171 for(i = 0; i < mapping.submaps; i++) {
173 doNotDecodeFlags = new Vector.<Boolean>();
175 for(j = 0; j < channels; j++) {
176 if(mapping.mux[j] == i) {
177 doNotDecodeFlags.push(noResidues[j]);
181 residue = residues[mapping.submapResidues[i]];
183 residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, freq0, freq1);
189 for(i = mapping.couplingSteps - 1; i >= 0; i--) {
194 for (j = 0; j < freq0.length; j++) {
196 a = ang == 0 ? freq0[j] : freq1[j];
197 m = mag == 0 ? freq0[j] : freq1[j];
201 freq0[j] = m > 0 ? m - a : m + a;
204 freq1[j] = m > 0 ? m - a : m + a;
209 freq0[j] = m > 0 ? m + a : m - a;
212 freq1[j] = m > 0 ? m + a : m - a;
225 if(channelFloors[0] != null) {
226 Floor(channelFloors[0]).computeFloor(freq0);
229 if(channelFloors[1] != null) {
230 Floor(channelFloors[1]).computeFloor(freq1);
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);
239 if(leftWindowEnd - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
240 leftWindowEnd = leftWindowStart + _lastGranulePosition - currentGranulePosition
242 if(rightWindowStart - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
243 rightWindowStart = leftWindowStart + _lastGranulePosition - currentGranulePosition
249 private function getComputedWindow(vorbis:VorbisStream):Vector.<Number> {
253 var ix:int = (blockFlag ? 4 : 0) + (previousWindowFlag ? 2 : 0) + (nextWindowFlag ? 1 : 0);
254 var w:Vector.<Number> = vorbis.windows[ix];
259 w = new Vector.<Number>(n);
261 for(i = 0; i < leftWindowStart; i++) {
265 for (i = 0; i < leftN; i++) {
266 x = (i + .5) / leftN * Math.PI / 2.;
271 w[i + leftWindowStart] = x;
274 for (i = leftWindowEnd; i < rightWindowStart; i++) {
278 for (i = 0; i < rightN; i++) {
279 x = (rightN - i - .5) / rightN * Math.PI / 2.;
284 w[i + rightWindowStart] = x;
287 for(i = rightN + rightWindowStart; i < n; i++) {
291 for(i = 0; i < w.length; i++) {
295 vorbis.windows[ix] = w;
302 public function readPcm(previousPacket:AudioPacket, target: ByteArray): int {
306 var ppcm0:Vector.<Number> = previousPacket.pcm0;
307 var ppcm1:Vector.<Number> = previousPacket.pcm1;
309 j2 = previousPacket.rightWindowStart;
311 for(j = leftWindowStart; j < leftWindowEnd; j++) {
312 target.writeFloat(pcm0[j] + ppcm0[j2]);
313 target.writeFloat(pcm1[j] + ppcm1[j2++]);
316 for (j = leftWindowEnd; j < rightWindowStart; j++) {
317 target.writeFloat(pcm0[j]);
318 target.writeFloat(pcm1[j]);
321 return numberOfSamples;
325 public function get numberOfSamples():int {
326 return rightWindowStart - leftWindowStart;
329 public function get lastPacket(): Boolean {
333 public function get lastGranulePosition(): int {
334 return lastGranulePosition;