Permalink
Browse files

Partial support for IMA ADPCM.

  • Loading branch information...
1 parent e76ad91 commit d10a8ad1f06c6b2b40392c17ceb9ea453d5ef586 @datacompboy committed Aug 12, 2011
View
@@ -303,7 +303,7 @@ class WavPlayerGui_Full extends WavPlayerGui {
// Main user interface: play / stop buttons & ExternalInterface
class WavPlayer {
- static var Version = "1.7.4";
+ static var Version = "1.8.0beta1";
static var player : Player;
static var state : String = PlayerEvent.STOPPED;
static var handlers : List<JsEventHandler>;
View
@@ -44,7 +44,8 @@
<body bgcolor="#dddddd" onload="init()">
<a href="javascript:doPlay()">doPlay()</a>
<a href="javascript:doPlay('test.gsm')">doPlay('test.gsm')</a>
-<a href="javascript:doPlay('test-vf-44100.au')">doPlay('test-vf-44100.au')</a>
+<a href="javascript:doPlay('test.wav')">doPlay('test.wav')</a>
+<a href="javascript:doPlay('test2.wav')">doPlay('test2.wav')</a>
<a href="javascript:doPlay('test.au')">doPlay('test.au')</a>
<a href="javascript:doPlay('hl-78003330781-5627.au')">doPlay('hl-78003330781-5627.au')</a>
<a href="javascript:doStop()">doStop()</a><br/>
@@ -77,7 +78,7 @@
<embed src="wavplayer-debug.swf?gui=full&h=40&w=400&sound=test.au&4"
bgcolor="#ffffff"
width="1200"
- height="400"
+ height="4000"
name="haxe"
quality="high"
align="middle"
View
@@ -23,5 +23,5 @@ interface Decoder {
// Number of PCM samples in one input chunk
var sampleLength : Int;
// Decode one input chunk to PCM samples
- function decode( InBuf : haxe.io.BytesData, InOff: Int, OutBuf : Array<Float>, OutOff: Int ) : Int;
+ function decode( InBuf : haxe.io.BytesData, InOff: Int, Chan: Int, OutBuf : Array<Float>, OutOff: Int ) : Int;
}
View
@@ -32,7 +32,7 @@ class DecoderG711a implements fmt.Decoder {
inverted = inv;
generate();
}
- public function decode( InBuf : haxe.io.BytesData, InOff: Int, OutBuf : Array<Float>, OutOff : Int) : Int {
+ public function decode( InBuf : haxe.io.BytesData, InOff: Int, Chan: Int, OutBuf : Array<Float>, OutOff : Int) : Int {
if (inverted) {
OutBuf[OutOff] = aLaw[Inv[InBuf[InOff]]];
} else {
View
@@ -32,7 +32,7 @@ class DecoderG711u implements fmt.Decoder {
inverted = inv;
generate();
}
- public function decode( InBuf : haxe.io.BytesData, InOff: Int, OutBuf : Array<Float>, OutOff: Int) : Int {
+ public function decode( InBuf : haxe.io.BytesData, InOff: Int, Chan: Int, OutBuf : Array<Float>, OutOff: Int) : Int {
if (inverted) {
OutBuf[OutOff] = ulaw[Inv[InBuf[InOff]]];
} else {
View
@@ -39,7 +39,7 @@ class DecoderGSM implements fmt.Decoder {
throw "Unsupported BPS";
decoder = new GSMDecoder();
}
- public function decode( InBuf : haxe.io.BytesData, InOff: Int, OutBuf : Array<Float>, OutOff: Int) : Int {
+ public function decode( InBuf : haxe.io.BytesData, InOff: Int, Chan: Int, OutBuf : Array<Float>, OutOff: Int) : Int {
decoder.decode( InBuf, InOff, OutBuf, OutOff, wavmode );
return wavmode ? 320 : 160;
}
View
@@ -0,0 +1,122 @@
+//
+// WAV/AU Flash player with resampler
+//
+// Copyright (c) 2011, Anton Fedorov <datacompboy@call2ru.com>
+//
+/* This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ */
+package fmt;
+
+// IMA ADPCM decoder for MS/4bit
+class IMAADPCM {
+ var predictor : Int;
+ var index : Int;
+ var step : Int;
+ var proceed : Int;
+ var resync : Int;
+
+ static var ima_index_table : Array<Int> = [
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+ ];
+ static var ima_step_table : Array<Int> = [ // 89 values 0-88
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+ ];
+
+ var calcs: Int;
+ public function new(samples: Int) {
+ proceed = 0;
+ calcs = 0;
+ resync = Std.int((samples+7)/8);
+ }
+
+ static var show: Int = 0;
+ function calc(nibble: Int): Float {
+ var diff: Int;
+ calcs++;
+ step = ima_step_table[index];
+ index += ima_index_table[nibble];
+ if (index < 0) index = 0;
+ if (index > 88) index = 88;
+ //diff = Std.int(((nibble&7)+0.5)*step/4.0);
+ diff = step >> 3;
+ if (nibble&4!=0) diff += step;
+ if (nibble&2!=0) diff += step>>1;
+ if (nibble&1!=0) diff += step>>2;
+ if (nibble&8!=0) {
+ predictor -= diff;
+ } else {
+ predictor += diff;
+ }
+ if (predictor < -32768) predictor = -32768;
+ if (predictor > 32767) predictor = 32767;
+ if (predictor != 0) {
+ if(show++<5) {
+ trace("Nibble="+nibble+" step="+step+" index="+index+" diff="+diff);
+ trace("Non-null predictor at "+calcs+" = "+predictor);
+ }
+ }
+ return predictor / 32767.0;
+ }
+
+ public function decode( InBuf : haxe.io.BytesData, Off: Int, OutBuf: Array<Float>, OutOff: Int) : Int {
+ if ((proceed++) % resync == 0) {
+ // Read initial pack
+ predictor = InBuf[Off] * 256 + InBuf[Off+1];
+ if (predictor > 32767) predictor = 65536-predictor;
+ index = InBuf[Off+2];
+ OutBuf[OutOff] = predictor/32767.0;
+ return 1;
+ } else {
+ for(i in 0...4) {
+ var n: Int = InBuf[Off++];
+ OutBuf[OutOff++] = calc(n&0x0F);
+ OutBuf[OutOff++] = calc(n>>4);
+ }
+ return 8;
+ }
+ }
+}
+class DecoderIMAADPCM implements fmt.Decoder {
+ public var sampleSize : Int;
+ public var sampleLength : Int;
+ var channels : Array<IMAADPCM>;
+
+ public function new(bps : Int, chans: Int, ?align: Int, ?samplesPerBlock: Int) {
+ var i: Int;
+ if (bps != 4) {
+ trace("Unsupported BPS");
+ throw "Unsupported BPS";
+ }
+ sampleSize = 4;
+ sampleLength = 8;
+ if ( (samplesPerBlock-1)/8+1 != align/4) {
+ trace("Unsupported packing");
+ throw "Unsupported packing";
+ }
+ channels = new Array<IMAADPCM>();
+ for (i in 0...chans) {
+ channels.push( new IMAADPCM(samplesPerBlock) );
+ }
+ }
+
+ public function decode( InBuf : haxe.io.BytesData, Off: Int, Chan: Int, OutBuf: Array<Float>, OutOff: Int) : Int {
+ return channels[Chan].decode(InBuf, Off, OutBuf, OutOff);
+ }
+}
View
@@ -28,7 +28,7 @@ class DecoderPCM implements fmt.Decoder {
shift = 1 << bps;
sampleLength = 1;
}
- public function decode( InBuf : haxe.io.BytesData, Off: Int, OutBuf: Array<Float>, OutOff: Int) : Int {
+ public function decode( InBuf : haxe.io.BytesData, Off: Int, Chan: Int, OutBuf: Array<Float>, OutOff: Int) : Int {
var Sample: Int = 0;
switch (sampleSize) {
case 1: Sample = InBuf[Off];
View
@@ -123,7 +123,7 @@ class File implements IFile {
var chk = 0;
while(SoundBuffer[0].length < samples && bufsize - i >= chunkSize) {
for(j in 0...channels) {
- sndDecoder.decode(Buffer, i, SoundBuffer[j], SoundBuffer[j].length);
+ sndDecoder.decode(Buffer, i, j, SoundBuffer[j], SoundBuffer[j].length);
i += sndDecoder.sampleSize;
}
i += align;
View
@@ -76,7 +76,7 @@ class FileWav extends fmt.File {
dataOff = i;
}
case 1: // Read fmt block
- if (i-dataOff < 24) {
+ if (i-dataOff < 24 || i-dataOff < dataSize+8) {
if (bufsize-i < 4) break;
var W1 = Buffer[i+1]*256+Buffer[i];
var W2 = Buffer[i+3]*256+Buffer[i+2];
@@ -102,9 +102,11 @@ class FileWav extends fmt.File {
bps = W2;
align = W1;
trace("align = "+align+"; bps="+bps);
+ case 24:
+ trace("Appendix W1="+W1+", W2="+W2+", DW="+DW);
}
i += 4;
- if (i-dataOff == 24) {
+ if (i-dataOff == dataSize+8) {
if (channels < 1 || channels > 2) {
trace("Wrong number of channels: "+channels);
Readed = -1;
@@ -129,8 +131,9 @@ class FileWav extends fmt.File {
sndDecoder = new DecoderG711u(bps, false);
case 17:
trace("File in IMA ADPCM");
- Readed = -1; return;
- //sndDecoder = new DecoderIMAADPCM(bps);
+ sndDecoder = new DecoderIMAADPCM(bps, channels, align, W2);
+ align = 0; // hack :(
+ //Readed = -1; return;
case 20:
trace("File in G.723 ADPCM");
Readed = -1; return;
View
Binary file not shown.
View
Binary file not shown.

0 comments on commit d10a8ad

Please sign in to comment.