DecoderIMAADPCM.hx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. //
  2. // WAV/AU Flash player with resampler
  3. //
  4. // Copyright (c) 2011, Anton Fedorov <datacompboy@call2ru.com>
  5. //
  6. /* This code is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 only, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This code is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. * version 2 for more details (a copy is included in the LICENSE file that
  14. * accompanied this code).
  15. */
  16. package fmt;
  17. // IMA ADPCM decoder for MS/4bit
  18. class IMAADPCM {
  19. var predictor : Int;
  20. var index : Int;
  21. var step : Int;
  22. var proceed : Int;
  23. var resync : Int;
  24. var spb : Int;
  25. static var ima_index_table : Array<Int> = [
  26. -1, -1, -1, -1, 2, 4, 6, 8,
  27. -1, -1, -1, -1, 2, 4, 6, 8
  28. ];
  29. static var ima_step_table : Array<Int> = [ // 89 values 0-88
  30. 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
  31. 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
  32. 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
  33. 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
  34. 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
  35. 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
  36. 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
  37. 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
  38. 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
  39. ];
  40. public function new(samples: Int) {
  41. proceed = 0;
  42. resync = Std.int((samples+7)/8);
  43. spb = samples;
  44. }
  45. public function reset(): Int {
  46. proceed = 0;
  47. return resync;
  48. }
  49. function calc(nibble: Int): Float {
  50. var diff: Int;
  51. step = ima_step_table[index];
  52. index += ima_index_table[nibble];
  53. if (index < 0) index = 0;
  54. if (index > 88) index = 88;
  55. //diff = Std.int(((nibble&7)+0.5)*step/4.0);
  56. diff = step >> 3;
  57. if (nibble&4!=0) diff += step;
  58. if (nibble&2!=0) diff += step>>1;
  59. if (nibble&1!=0) diff += step>>2;
  60. if (nibble&8!=0) {
  61. predictor -= diff;
  62. } else {
  63. predictor += diff;
  64. }
  65. if (predictor < -32768) predictor = -32768;
  66. if (predictor > 32767) predictor = 32767;
  67. return predictor / 32767.0;
  68. }
  69. public function decodeLength(chunks: Int): Int {
  70. var f = Math.floor(chunks / resync);
  71. var r = chunks % resync;
  72. if (r>0) r = r*8 - 7;
  73. return f*spb+r;
  74. }
  75. public function decode( InBuf : haxe.io.BytesData, Off: Int, OutBuf: Array<Float>, OutOff: Int) : Int {
  76. if ((proceed++) % resync == 0) {
  77. // Read initial pack
  78. predictor = InBuf[Off+1] * 256 + InBuf[Off];
  79. if (predictor > 32767) predictor = predictor-65536;
  80. index = InBuf[Off+2];
  81. OutBuf[OutOff] = predictor/32767.0;
  82. return 1;
  83. } else {
  84. for(i in 0...4) {
  85. var n: Int = InBuf[Off++];
  86. OutBuf[OutOff++] = calc(n&0x0F);
  87. OutBuf[OutOff++] = calc(n>>4);
  88. }
  89. return 8;
  90. }
  91. }
  92. }
  93. class DecoderIMAADPCM extends fmt.Decoder {
  94. var channels : Array<IMAADPCM>;
  95. public function new(bps : Int, chans: Int, ?align: Int, ?samplesPerBlock: Int) {
  96. var i: Int;
  97. if (bps != 4) {
  98. trace("Unsupported BPS");
  99. throw "Unsupported BPS";
  100. }
  101. sampleSize = 4;
  102. sampleLength = 8;
  103. if ( ((samplesPerBlock-1)/8+1)*chans != align/4) {
  104. trace("Unsupported packing ("+(((samplesPerBlock-1)/8+1)*chans)+" != "+(align/4)+")");
  105. throw "Unsupported packing";
  106. }
  107. channels = new Array<IMAADPCM>();
  108. for (i in 0...chans) {
  109. channels.push( new IMAADPCM(samplesPerBlock) );
  110. }
  111. }
  112. public override function seek ( chunk: Int ) : Int {
  113. var chu: Int;
  114. var res: Int = 1;
  115. for (channel in channels) {
  116. res = channel.reset();
  117. }
  118. chu = Math.floor(chunk / res) * res;
  119. return chu;
  120. }
  121. public override function decodeLength(chunks: Int): Int {
  122. return channels[0].decodeLength(chunks);
  123. }
  124. public override function decode( InBuf : haxe.io.BytesData, Off: Int, Chan: Int, OutBuf: Array<Float>, OutOff: Int) : Int {
  125. return channels[Chan].decode(InBuf, Off, OutBuf, OutOff);
  126. }
  127. }