flexPartyPlayer 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +6 -0
- data/README +45 -0
- data/lib/corelib-08.30.2007.swc +0 -0
- data/lib/flexPartyPlayer.rb +42 -0
- data/lib/flexunit-08.30.2007.swc +0 -0
- data/sample.json +1 -0
- data/script/destroy +14 -0
- data/script/flex_compile +2 -0
- data/script/generate +14 -0
- data/src/FlexPlayer.mxml +34 -0
- data/src/assets/app_icons/icon_128.png +0 -0
- data/src/cc/varga/mvc/ApplicationContext.as +120 -0
- data/src/cc/varga/mvc/commands/data/LoadArtistDataCommand.as +61 -0
- data/src/cc/varga/mvc/commands/playlist/AddItemToPlaylist.as +13 -0
- data/src/cc/varga/mvc/commands/playlist/LoadPlaylistCommand.as +109 -0
- data/src/cc/varga/mvc/commands/system/DrawPlaylist.as +40 -0
- data/src/cc/varga/mvc/commands/system/Shutdown.as +51 -0
- data/src/cc/varga/mvc/commands/system/Startup.as +57 -0
- data/src/cc/varga/mvc/commands/video/AddVideoCommand.as +55 -0
- data/src/cc/varga/mvc/events/appBar/AppBarEvent.as +16 -0
- data/src/cc/varga/mvc/events/blipfm/feedloader/FeedLoaderEvent.as +17 -0
- data/src/cc/varga/mvc/events/controllers/ControllersEvent.as +59 -0
- data/src/cc/varga/mvc/events/menu/MenuEvent.as +13 -0
- data/src/cc/varga/mvc/events/player/PlayerEvent.as +29 -0
- data/src/cc/varga/mvc/events/playlist/PlaylistEvent.as +16 -0
- data/src/cc/varga/mvc/events/playlist/PlaylistURLEvent.as +57 -0
- data/src/cc/varga/mvc/events/playlist/controller/PlaylistControllerEvent.as +59 -0
- data/src/cc/varga/mvc/events/search/SearchEvent.as +17 -0
- data/src/cc/varga/mvc/events/serveradmin/ServerAdminEvent.as +15 -0
- data/src/cc/varga/mvc/events/sound/SoundEvent.as +16 -0
- data/src/cc/varga/mvc/events/system/SystemEvent.as +24 -0
- data/src/cc/varga/mvc/models/data/AppDataModel.as +17 -0
- data/src/cc/varga/mvc/models/player/PlayerModel.as +76 -0
- data/src/cc/varga/mvc/models/playlist/PlaylistModel.as +118 -0
- data/src/cc/varga/mvc/models/sound/ISound.as +12 -0
- data/src/cc/varga/mvc/models/sound/SoundModel.as +284 -0
- data/src/cc/varga/mvc/models/sound/SoundModelPlayer.as +8 -0
- data/src/cc/varga/mvc/services/KeyboardControl.as +60 -0
- data/src/cc/varga/mvc/views/blipfm/feedloader/FeedLoader.mxml +34 -0
- data/src/cc/varga/mvc/views/blipfm/feedloader/FeedLoaderMediator.as +68 -0
- data/src/cc/varga/mvc/views/controllers/Controllers.mxml +36 -0
- data/src/cc/varga/mvc/views/controllers/ControllersMediator.as +107 -0
- data/src/cc/varga/mvc/views/infoDisplay/InfoDisplay.mxml +20 -0
- data/src/cc/varga/mvc/views/infoDisplay/InfoDisplayMediator.as +51 -0
- data/src/cc/varga/mvc/views/menu/Menu.mxml +28 -0
- data/src/cc/varga/mvc/views/menu/MenuMediator.as +30 -0
- data/src/cc/varga/mvc/views/player/PlayerItem.mxml +11 -0
- data/src/cc/varga/mvc/views/player/PlayerWindow.mxml +73 -0
- data/src/cc/varga/mvc/views/player/PlayerWindowMediator.as +136 -0
- data/src/cc/varga/mvc/views/playlist/Playlist.mxml +22 -0
- data/src/cc/varga/mvc/views/playlist/PlaylistMediator.as +117 -0
- data/src/cc/varga/mvc/views/playlist/PlaylistStates.as +10 -0
- data/src/cc/varga/mvc/views/playlistItem/PlaylistItem.mxml +94 -0
- data/src/cc/varga/mvc/views/playlistItem/PlaylistItemMediator.as +87 -0
- data/src/cc/varga/mvc/views/playlistManager/PlaylistManager.mxml +7 -0
- data/src/cc/varga/mvc/views/playlistManager/PlaylistManagerMediator.as +15 -0
- data/src/cc/varga/mvc/views/playlisturl/PlaylistURL.mxml +41 -0
- data/src/cc/varga/mvc/views/playlisturl/PlaylistURLMediator.as +87 -0
- data/src/cc/varga/mvc/views/playlisturl/controller/PlaylistController.mxml +37 -0
- data/src/cc/varga/mvc/views/playlisturl/controller/PlaylistControllerMediator.as +79 -0
- data/src/cc/varga/mvc/views/search/Search.mxml +26 -0
- data/src/cc/varga/mvc/views/search/SearchMediator.as +31 -0
- data/src/cc/varga/mvc/views/server/administration/ServerAdmin.mxml +26 -0
- data/src/cc/varga/mvc/views/server/administration/ServerAdminMediator.as +51 -0
- data/src/cc/varga/mvc/views/visualisation/Visualisation.mxml +8 -0
- data/src/cc/varga/mvc/views/visualisation/VisualisationMediator.as +51 -0
- data/src/cc/varga/utils/URLHelper.as +52 -0
- data/src/cc/varga/utils/logging/Logger.as +94 -0
- data/src/com/automatastudios/audio/audiodecoder/AudioDecoder.as +84 -0
- data/src/com/automatastudios/audio/audiodecoder/decoders/AudioInfo.as +52 -0
- data/src/com/automatastudios/audio/audiodecoder/decoders/IDecoder.as +13 -0
- data/src/com/automatastudios/audio/audiodecoder/decoders/OggVorbisDecoder.as +221 -0
- data/src/com/automatastudios/audio/audiodecoder/decoders/WAVDecoder.as +325 -0
- data/src/com/automatastudios/audio/audiodecoder/events/AudioDecoderEvent.as +13 -0
- data/src/com/automatastudios/data/riff/RIFFChunkInfo.as +6 -0
- data/src/com/automatastudios/data/riff/RIFFParser.as +175 -0
- data/src/libs/appinf/appinf.json +0 -0
- data/src/libs/appinf/config.json +0 -0
- data/src/libs/appinf/sample.json +1 -0
- data/src/libs/appinf/server.json +0 -0
- data/src/nl/flexcoders/controls/YouTubePlayer.as +317 -0
- data/test/Test-app.xml +40 -0
- data/test/Test.mxml +35 -0
- data/views/jukebox.haml +30 -0
- metadata +157 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
package com.automatastudios.audio.audiodecoder.decoders {
|
|
2
|
+
import com.automatastudios.audio.audiodecoder.events.AudioDecoderEvent;
|
|
3
|
+
import com.automatastudios.data.riff.RIFFChunkInfo;
|
|
4
|
+
import com.automatastudios.data.riff.RIFFParser;
|
|
5
|
+
|
|
6
|
+
import flash.errors.EOFError;
|
|
7
|
+
import flash.events.EventDispatcher;
|
|
8
|
+
import flash.events.Event;
|
|
9
|
+
import flash.events.IOErrorEvent;
|
|
10
|
+
import flash.events.ProgressEvent;
|
|
11
|
+
import flash.errors.EOFError;
|
|
12
|
+
import flash.net.URLStream;
|
|
13
|
+
import flash.utils.ByteArray;
|
|
14
|
+
import flash.utils.Endian;
|
|
15
|
+
import flash.utils.IDataInput;
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
public class WAVDecoder extends EventDispatcher implements IDecoder {
|
|
19
|
+
private var _data:IDataInput;
|
|
20
|
+
private var _riffParser:RIFFParser;
|
|
21
|
+
private var _audioInfo:AudioInfo;
|
|
22
|
+
private var _nextMethod:Function;
|
|
23
|
+
private var _convertMethod:Function;
|
|
24
|
+
private var _isBuffering:Boolean;
|
|
25
|
+
private var _bufferSize:uint;
|
|
26
|
+
|
|
27
|
+
private var _dataSize:uint;
|
|
28
|
+
private var _position:uint;
|
|
29
|
+
private var _isSmallFile:Boolean;
|
|
30
|
+
|
|
31
|
+
public function WAVDecoder():void {
|
|
32
|
+
// do nothing, wait for init
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public function init(data:IDataInput, bufferSize:uint, progressEventName:String):void {
|
|
36
|
+
_data = data;
|
|
37
|
+
_riffParser = new RIFFParser(data);
|
|
38
|
+
_bufferSize = bufferSize;
|
|
39
|
+
|
|
40
|
+
_position = 0;
|
|
41
|
+
_dataSize = 0;
|
|
42
|
+
|
|
43
|
+
_nextMethod = parseRIFFChunk;
|
|
44
|
+
|
|
45
|
+
if (progressEventName != null) {
|
|
46
|
+
_isSmallFile = true;
|
|
47
|
+
(data as EventDispatcher).addEventListener(progressEventName, onDataProgress);
|
|
48
|
+
(data as EventDispatcher).addEventListener(Event.COMPLETE, onDataComplete);
|
|
49
|
+
} else {
|
|
50
|
+
_nextMethod();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public function getSamples(position:Number, numSamples:uint, sampleData:ByteArray):void {
|
|
55
|
+
var numBytes:uint = numSamples * _audioInfo.blockAlign / _audioInfo.sampleMultiplier;
|
|
56
|
+
var dataReadSize:int;
|
|
57
|
+
var sampleReadSize:int;
|
|
58
|
+
var rawSampleData:ByteArray = new ByteArray();
|
|
59
|
+
var i:uint;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
dataReadSize = _riffParser.streamChunkData(numBytes, rawSampleData);
|
|
63
|
+
|
|
64
|
+
sampleReadSize = dataReadSize / _audioInfo.blockAlign;
|
|
65
|
+
|
|
66
|
+
_position += dataReadSize;
|
|
67
|
+
rawSampleData.endian = Endian.LITTLE_ENDIAN;
|
|
68
|
+
|
|
69
|
+
_convertMethod(sampleReadSize, rawSampleData, sampleData);
|
|
70
|
+
|
|
71
|
+
if (!_riffParser.isDataComplete) {
|
|
72
|
+
// padd with extra 0s as needed
|
|
73
|
+
for (i=sampleReadSize * _audioInfo.sampleMultiplier; i<numSamples; ++i) {
|
|
74
|
+
sampleData.writeFloat(0);
|
|
75
|
+
sampleData.writeFloat(0);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
dispatchEvent(new Event(Event.COMPLETE));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
} catch (error:EOFError) {
|
|
82
|
+
// padd with extra 0s as needed
|
|
83
|
+
for (i=0; i<numSamples; ++i) {
|
|
84
|
+
sampleData.writeFloat(0);
|
|
85
|
+
sampleData.writeFloat(0);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public function getAudioInfo():AudioInfo {
|
|
91
|
+
return _audioInfo;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public function getTotalTime():Number {
|
|
95
|
+
return ((_dataSize / (_audioInfo.blockAlign * _audioInfo.sampleMultiplier)) / 44100);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public function getPosition():Number {
|
|
99
|
+
return ((_position / (_audioInfo.blockAlign * _audioInfo.sampleMultiplier)) / 44100);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private function onDataProgress(event:Event):void {
|
|
103
|
+
if (_nextMethod != null) {
|
|
104
|
+
if (_data.bytesAvailable >= _bufferSize) {
|
|
105
|
+
_isSmallFile = false;
|
|
106
|
+
_nextMethod();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private function onDataComplete(event:Event):void {
|
|
112
|
+
if (_isSmallFile) {
|
|
113
|
+
_bufferSize = _data.bytesAvailable;
|
|
114
|
+
|
|
115
|
+
_nextMethod();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private function parseRIFFChunk():void {
|
|
120
|
+
var headerInfo:RIFFChunkInfo;
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
headerInfo = _riffParser.readChunk();
|
|
124
|
+
|
|
125
|
+
if (headerInfo.chunkId == "RIFF") {
|
|
126
|
+
|
|
127
|
+
_nextMethod = parseRIFFSubChunk;
|
|
128
|
+
_nextMethod();
|
|
129
|
+
} else {
|
|
130
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad audio format"));
|
|
131
|
+
}
|
|
132
|
+
} catch (error:EOFError) {
|
|
133
|
+
// do nothing, wait for next attempt
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private function parseRIFFSubChunk():void {
|
|
138
|
+
var subChunkFormat:String;
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
subChunkFormat = _riffParser.readSubChunk();
|
|
142
|
+
|
|
143
|
+
if (subChunkFormat == "WAVE") {
|
|
144
|
+
_nextMethod = locateFormatChunk;
|
|
145
|
+
_nextMethod();
|
|
146
|
+
} else {
|
|
147
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad audio format"));
|
|
148
|
+
}
|
|
149
|
+
} catch (error:EOFError) {
|
|
150
|
+
// do nothing, wait for next attempt
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private function locateFormatChunk():void {
|
|
155
|
+
var chunkInfo:RIFFChunkInfo;
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
chunkInfo = _riffParser.readChunk();
|
|
159
|
+
|
|
160
|
+
while (chunkInfo.chunkId != "fmt " && chunkInfo != null) {
|
|
161
|
+
chunkInfo = _riffParser.readChunk();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (chunkInfo.chunkId == "fmt ") {
|
|
165
|
+
_nextMethod = parseFormatChunk;
|
|
166
|
+
_nextMethod();
|
|
167
|
+
} else {
|
|
168
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad audio format"));
|
|
169
|
+
}
|
|
170
|
+
} catch (error:EOFError) {
|
|
171
|
+
// do nothing, wait for next attempt
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private function parseFormatChunk():void {
|
|
176
|
+
var chunkData:ByteArray;
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
chunkData = _riffParser.readChunkData();
|
|
180
|
+
chunkData.endian = Endian.LITTLE_ENDIAN;
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if (chunkData.length >= 16) {
|
|
184
|
+
_audioInfo = new AudioInfo();
|
|
185
|
+
_audioInfo.decoder = "com.automatastudios.audio.audiodecoder.decoders.WAVDecoder";
|
|
186
|
+
_audioInfo.format = (chunkData.readUnsignedShort() == 1 ? "PCM" : "Unknown");
|
|
187
|
+
_audioInfo.channels = chunkData.readUnsignedShort();
|
|
188
|
+
_audioInfo.sampleRate = chunkData.readUnsignedInt();
|
|
189
|
+
_audioInfo.bitRateUpper =
|
|
190
|
+
_audioInfo.bitRateLower = chunkData.readUnsignedInt()/8;
|
|
191
|
+
_audioInfo.blockAlign = chunkData.readUnsignedShort();
|
|
192
|
+
_audioInfo.bitsPerSample = chunkData.readUnsignedShort();
|
|
193
|
+
_audioInfo.sampleMultiplier = 44100 / _audioInfo.sampleRate;
|
|
194
|
+
|
|
195
|
+
trace(_audioInfo.toString());
|
|
196
|
+
|
|
197
|
+
if (_audioInfo.channels == 1) {
|
|
198
|
+
if (_audioInfo.bitsPerSample == 8) {
|
|
199
|
+
_convertMethod = convert8BitMono;
|
|
200
|
+
} else if (_audioInfo.bitsPerSample == 16) {
|
|
201
|
+
_convertMethod = convert16BitMono;
|
|
202
|
+
}
|
|
203
|
+
} else if (_audioInfo.channels == 2) {
|
|
204
|
+
if (_audioInfo.bitsPerSample == 8) {
|
|
205
|
+
_convertMethod = convert8BitStereo;
|
|
206
|
+
} else if (_audioInfo.bitsPerSample == 16) {
|
|
207
|
+
_convertMethod = convert16BitStereo;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (_audioInfo.format != "PCM" || _convertMethod == null) {
|
|
212
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad audio format"));
|
|
213
|
+
_nextMethod = null;
|
|
214
|
+
} else if (_audioInfo.sampleRate != 44100 && _audioInfo.sampleRate != 22050 && _audioInfo.sampleRate != 11025) {
|
|
215
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad sample rate"));
|
|
216
|
+
_nextMethod = null;
|
|
217
|
+
} else {
|
|
218
|
+
_nextMethod = locateDataChunk;
|
|
219
|
+
_nextMethod();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
} else {
|
|
223
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad audio format"));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
} catch (error:EOFError) {
|
|
227
|
+
// do nothing, wait for next attempt
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private function locateDataChunk():void {
|
|
232
|
+
var chunkInfo:RIFFChunkInfo;
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
_nextMethod = null;
|
|
236
|
+
chunkInfo = _riffParser.readChunk();
|
|
237
|
+
|
|
238
|
+
while (chunkInfo.chunkId != "data" && chunkInfo != null) {
|
|
239
|
+
chunkInfo = _riffParser.readChunk();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (chunkInfo.chunkId == "data") {
|
|
243
|
+
_dataSize = chunkInfo.size;
|
|
244
|
+
dispatchEvent(new Event(Event.INIT));
|
|
245
|
+
|
|
246
|
+
_nextMethod = null;
|
|
247
|
+
} else {
|
|
248
|
+
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Bad audio format"));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
} catch (error:EOFError) {
|
|
253
|
+
// do nothing, wait for next attempt
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private function convert8BitMono(numSamples:uint, inputData:ByteArray, outputData:ByteArray):void {
|
|
258
|
+
var i:uint;
|
|
259
|
+
var j:uint;
|
|
260
|
+
var sample:Number;
|
|
261
|
+
|
|
262
|
+
for (i=0; i<numSamples; ++i) {
|
|
263
|
+
sample = (inputData.readUnsignedByte() - 128) / 128;
|
|
264
|
+
for (j=0; j< _audioInfo.sampleMultiplier; ++j) {
|
|
265
|
+
outputData.writeFloat(sample);
|
|
266
|
+
outputData.writeFloat(sample);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private function convert16BitMono(numSamples:uint, inputData:ByteArray, outputData:ByteArray):void {
|
|
272
|
+
var i:uint;
|
|
273
|
+
var j:uint;
|
|
274
|
+
var sample:Number;
|
|
275
|
+
|
|
276
|
+
for (i=0; i<numSamples; ++i) {
|
|
277
|
+
sample = inputData.readShort();
|
|
278
|
+
sample /= 32768;
|
|
279
|
+
|
|
280
|
+
for (j=0; j< _audioInfo.sampleMultiplier; ++j) {
|
|
281
|
+
outputData.writeFloat(sample);
|
|
282
|
+
outputData.writeFloat(sample);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private function convert8BitStereo(numSamples:uint, inputData:ByteArray, outputData:ByteArray):void {
|
|
288
|
+
var i:uint;
|
|
289
|
+
var j:uint;
|
|
290
|
+
var sample:Number;
|
|
291
|
+
|
|
292
|
+
for (i=0; i<numSamples; ++i) {
|
|
293
|
+
sample = (inputData.readUnsignedByte() - 128) / 128;
|
|
294
|
+
for (j=0; j< _audioInfo.sampleMultiplier; ++j) {
|
|
295
|
+
outputData.writeFloat(sample);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
sample = (inputData.readUnsignedByte() - 128) / 128;
|
|
299
|
+
for (j=0; j< _audioInfo.sampleMultiplier; ++j) {
|
|
300
|
+
outputData.writeFloat(sample);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private function convert16BitStereo(numSamples:uint, inputData:ByteArray, outputData:ByteArray):void {
|
|
306
|
+
var i:uint;
|
|
307
|
+
var j:uint;
|
|
308
|
+
var leftSample:Number;
|
|
309
|
+
var rightSample:Number;
|
|
310
|
+
var count:uint = 0;
|
|
311
|
+
|
|
312
|
+
for (i=0; i<numSamples; ++i) {
|
|
313
|
+
leftSample = inputData.readShort() / 32767;
|
|
314
|
+
rightSample = inputData.readShort() / 32767;
|
|
315
|
+
|
|
316
|
+
for (j=0; j< _audioInfo.sampleMultiplier; ++j) {
|
|
317
|
+
outputData.writeFloat(leftSample);
|
|
318
|
+
outputData.writeFloat(rightSample);
|
|
319
|
+
++count;
|
|
320
|
+
++count;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.automatastudios.audio.audiodecoder.events {
|
|
2
|
+
import flash.events.Event;
|
|
3
|
+
|
|
4
|
+
public class AudioDecoderEvent extends Event {
|
|
5
|
+
public static const INVALID_SAMPLE_RATE:String = "audioDecoderInvalidSampleRate";
|
|
6
|
+
public static const INVALID_FORMAT:String = "audioDecoderInvalidFormat";
|
|
7
|
+
|
|
8
|
+
public function AudioDecoderEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
|
|
9
|
+
super(type, bubbles, cancelable);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
package com.automatastudios.data.riff {
|
|
2
|
+
import flash.errors.EOFError;
|
|
3
|
+
import com.automatastudios.audio.audiodecoder.events.AudioDecoderEvent;
|
|
4
|
+
import com.automatastudios.audio.audiodecoder.events.AudioDecoderEvent;
|
|
5
|
+
import flash.events.EventDispatcher;
|
|
6
|
+
import flash.events.Event;
|
|
7
|
+
import flash.events.ProgressEvent;
|
|
8
|
+
import flash.errors.EOFError;
|
|
9
|
+
import flash.net.URLStream;
|
|
10
|
+
import flash.utils.ByteArray;
|
|
11
|
+
import flash.utils.Endian;
|
|
12
|
+
import flash.utils.IDataInput;
|
|
13
|
+
|
|
14
|
+
public class RIFFParser {
|
|
15
|
+
private var _data:IDataInput;
|
|
16
|
+
private var _currentSize:uint;
|
|
17
|
+
private var _chunkSize:uint;
|
|
18
|
+
private var _currentPosition:uint;
|
|
19
|
+
private var _startPosition:uint;
|
|
20
|
+
private var _isDataComplete:Boolean;
|
|
21
|
+
private var _dataSize:uint;
|
|
22
|
+
|
|
23
|
+
private var _positionStack:Array;
|
|
24
|
+
private var _sizeStack:Array;
|
|
25
|
+
|
|
26
|
+
public function RIFFParser(data:IDataInput = null) {
|
|
27
|
+
_data = data;
|
|
28
|
+
_sizeStack = new Array();
|
|
29
|
+
_positionStack = new Array();
|
|
30
|
+
_currentPosition = 0;
|
|
31
|
+
_currentSize = 0;
|
|
32
|
+
_startPosition = 0;
|
|
33
|
+
_isDataComplete = false;
|
|
34
|
+
|
|
35
|
+
if (_data is ByteArray) {
|
|
36
|
+
_dataSize = (_data as ByteArray).length;
|
|
37
|
+
} else {
|
|
38
|
+
(_data as EventDispatcher).addEventListener(ProgressEvent.PROGRESS, onDataProgress);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public function get isDataComplete():Boolean {
|
|
43
|
+
return _isDataComplete;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public function parse(data:IDataInput):void {
|
|
47
|
+
_data = data;
|
|
48
|
+
_sizeStack = new Array();
|
|
49
|
+
_positionStack = new Array();
|
|
50
|
+
_currentPosition = 0;
|
|
51
|
+
_currentSize = 0;
|
|
52
|
+
_startPosition = 0;
|
|
53
|
+
|
|
54
|
+
if (_data is ByteArray) {
|
|
55
|
+
_isDataComplete = true;
|
|
56
|
+
} else {
|
|
57
|
+
_isDataComplete = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public function readChunk():RIFFChunkInfo {
|
|
62
|
+
var chunkInfo:RIFFChunkInfo;
|
|
63
|
+
|
|
64
|
+
_data.endian = Endian.BIG_ENDIAN;
|
|
65
|
+
|
|
66
|
+
if (_data.bytesAvailable >= 8) {
|
|
67
|
+
|
|
68
|
+
// move on to next chunk
|
|
69
|
+
if (_currentSize > 0) {
|
|
70
|
+
_data.readBytes(new ByteArray(), 0, _currentSize - (_currentPosition - _startPosition));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// check to see if we need to pop up the stack
|
|
74
|
+
while(_sizeStack.length > 0 && _sizeStack[_sizeStack.length - 1] - _currentPosition - _positionStack[_positionStack.length - 1] < 1) {
|
|
75
|
+
_sizeStack.pop();
|
|
76
|
+
_positionStack.pop();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// if on an odd byte remove the padding byte
|
|
80
|
+
if (_currentPosition % 2 == 1) {
|
|
81
|
+
_data.readUnsignedByte();
|
|
82
|
+
++_currentPosition;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
chunkInfo = new RIFFChunkInfo();
|
|
86
|
+
chunkInfo.chunkId = String.fromCharCode(_data.readUnsignedByte(),
|
|
87
|
+
_data.readUnsignedByte(),
|
|
88
|
+
_data.readUnsignedByte(),
|
|
89
|
+
_data.readUnsignedByte());
|
|
90
|
+
|
|
91
|
+
_data.endian = Endian.LITTLE_ENDIAN;
|
|
92
|
+
chunkInfo.size =
|
|
93
|
+
_chunkSize =
|
|
94
|
+
_currentSize = _data.readUnsignedInt();
|
|
95
|
+
|
|
96
|
+
_currentPosition += 8;
|
|
97
|
+
_startPosition = _currentPosition;
|
|
98
|
+
|
|
99
|
+
return chunkInfo;
|
|
100
|
+
} else {
|
|
101
|
+
throw new EOFError("Not enough data available to read chunk");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public function readSubChunk():String {
|
|
106
|
+
var subChunkId:String = "";
|
|
107
|
+
|
|
108
|
+
if (_data.bytesAvailable >= 4) {
|
|
109
|
+
|
|
110
|
+
_sizeStack.push(_currentSize);
|
|
111
|
+
_positionStack.push(_startPosition);
|
|
112
|
+
|
|
113
|
+
_currentSize = 0;
|
|
114
|
+
_startPosition = 0;
|
|
115
|
+
|
|
116
|
+
_data.endian = Endian.BIG_ENDIAN;
|
|
117
|
+
|
|
118
|
+
subChunkId = String.fromCharCode(_data.readUnsignedByte(),
|
|
119
|
+
_data.readUnsignedByte(),
|
|
120
|
+
_data.readUnsignedByte(),
|
|
121
|
+
_data.readUnsignedByte());
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
_currentPosition += 4;
|
|
125
|
+
|
|
126
|
+
return subChunkId;
|
|
127
|
+
} else {
|
|
128
|
+
throw new EOFError("Not enough data avilable to read sub chunk");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public function readChunkData():ByteArray {
|
|
133
|
+
var chunkData:ByteArray;
|
|
134
|
+
|
|
135
|
+
if (_data.bytesAvailable >= _currentSize) {
|
|
136
|
+
chunkData = new ByteArray();
|
|
137
|
+
_data.readBytes(chunkData, 0, _currentSize);
|
|
138
|
+
_currentPosition += _currentSize;
|
|
139
|
+
_currentSize = 0;
|
|
140
|
+
|
|
141
|
+
return chunkData;
|
|
142
|
+
} else {
|
|
143
|
+
throw new EOFError("Not enough data avilable to read chunk data");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public function streamChunkData(bufferSize:uint, streamData:ByteArray):uint {
|
|
148
|
+
var readSize:int = Math.min(bufferSize, _currentSize);
|
|
149
|
+
var maxPosition:uint = Math.min(_chunkSize, _currentPosition + _data.bytesAvailable);
|
|
150
|
+
var movedPosition:uint;
|
|
151
|
+
|
|
152
|
+
readSize = Math.max(readSize, 0);
|
|
153
|
+
|
|
154
|
+
if (_data.bytesAvailable >= readSize) {
|
|
155
|
+
if (readSize > 0) {
|
|
156
|
+
_data.readBytes(streamData, streamData.length, readSize);
|
|
157
|
+
_currentPosition += readSize;
|
|
158
|
+
_currentSize -= readSize;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (_currentSize == 0 && _dataSize > 0) {
|
|
162
|
+
_isDataComplete = true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return readSize;
|
|
166
|
+
} else {
|
|
167
|
+
throw new EOFError("Not enough data avilable to read " + readSize + " bytes from chunk data");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private function onDataProgress(event:ProgressEvent):void {
|
|
172
|
+
_dataSize = event.bytesTotal;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
File without changes
|
|
File without changes
|