YM.js 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. /*------------------------------------------------------------------------------
  2. Tweaked for Phaser.js framework by Nicolas CHALLEIL Aka STuFF
  3. (removed all amiga song playback, handle ArrayBuffer)
  4. Copyright (c) 2011 Antoine Santo Aka NoNameNo
  5. This File is part of the CODEF project.
  6. More info : http://codef.santo.fr
  7. Demo gallery http://www.wab.com
  8. Permission is hereby granted, free of charge, to any person obtaining a copy
  9. of this software and associated documentation files (the "Software"), to deal
  10. in the Software without restriction, including without limitation the rights
  11. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. copies of the Software, and to permit persons to whom the Software is
  13. furnished to do so, subject to the following conditions:
  14. The above copyright notice and this permission notice shall be included in
  15. all copies or substantial portions of the Software.
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. THE SOFTWARE.
  23. ------------------------------------------------------------------------------*/
  24. !(function () {
  25. var CODEF_AUDIO_CONTEXT = null;
  26. var CODEF_AUDIO_NODE = null;
  27. function YM (data) {
  28. if (typeof window.AudioContext !== 'undefined') {
  29. CODEF_AUDIO_CONTEXT = new AudioContext(); // Atari YM Format !!! ;)
  30. CODEF_AUDIO_NODE = CODEF_AUDIO_CONTEXT.createScriptProcessor(8192);
  31. YmConst_PLAYER_FREQ = CODEF_AUDIO_CONTEXT.sampleRate;
  32. this.vu = [0, 0, 0];
  33. this.info = null;
  34. this.player = new YmProcessor(this);
  35. this.parse(data);
  36. this.stereo_value = false;
  37. }
  38. }
  39. YM.prototype.parse = function (data) {
  40. var binString = new dataType();
  41. var ff = [];
  42. if (data instanceof ArrayBuffer) {
  43. data = new Uint8Array(data);
  44. }
  45. for (var z = 0, l = data.length; z < l; z++) {
  46. ff[z] = String.fromCharCode(data[z]);
  47. }
  48. binString.data = ff.join('');
  49. this.player.stereo = this.stereo_value;
  50. data = binString;
  51. this.player.load(data);
  52. this.info = {
  53. title: this.player.song.title || 'unknown',
  54. author: this.player.song.author || 'unknown',
  55. comment: this.player.song.comment || 'unknown'
  56. }
  57. }
  58. YM.prototype.play = function () {
  59. if (this.player) {
  60. this.player.play();
  61. }
  62. }
  63. YM.prototype.stop = function () {
  64. if (this.player) {
  65. this.player.stop();
  66. }
  67. }
  68. YM.prototype.clearsong = function () {
  69. if (this.player) {
  70. this.player.reset();
  71. }
  72. }
  73. YM.prototype.stereo = function (stat) {
  74. this.stereo_value = stat;
  75. }
  76. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  77. //
  78. // YM replay routine
  79. //
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. ////////////////////////////////////////////////////////////////////
  82. //
  83. // YmConst.js
  84. //
  85. ////////////////////////////////////////////////////////////////////
  86. var YmConst_BUFFER_SIZE = 8192;
  87. var YmConst_PLAYER_FREQ = 48000;
  88. var YmConst_DRUM_PREC = 15;
  89. var YmConst_AMSTRAD_FREQ = 1000000;
  90. var YmConst_ATARI_FREQ = 2000000;
  91. var YmConst_SPECTRUM_FREQ = 1773400;
  92. var YmConst_INTERLEAVED = 1;
  93. var YmConst_DRUM_SIGNED = 2;
  94. var YmConst_DRUM_4BITS = 4;
  95. var YmConst_TIME_CONTROL = 8;
  96. var YmConst_LOOP_MODE = 16;
  97. var YmConst_MFP_PREDIV = [0, 4, 10, 16, 50, 64, 100, 200];
  98. var YmConst_MONO = [
  99. 0.00063071586250394, 0.00163782667521185, 0.00269580167037975, 0.00383515935748365,
  100. 0.00590024516535946, 0.00787377544480728, 0.01174962614825892, 0.01602221747489853,
  101. 0.02299061047191789, 0.03141371908729311, 0.04648986276843572, 0.06340728985463016,
  102. 0.09491256447035126, 0.13414919481999166, 0.21586759036022013, 0.33333333333333333
  103. ];
  104. var YmConst_STEREO = [
  105. 0.00094607379375591, 0.00245674001281777, 0.00404370250556963, 0.00575273903622547,
  106. 0.00885036774803918, 0.01181066316721091, 0.01762443922238838, 0.02403332621234779,
  107. 0.03448591570787683, 0.04712057863093966, 0.06973479415265358, 0.09511093478194525,
  108. 0.14236884670552690, 0.20122379222998749, 0.32380138554033021, 0.50000000000000000
  109. ];
  110. var YmConst_ENVELOPES = [
  111. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  112. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  113. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  114. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  115. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  116. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  117. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  118. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  119. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  120. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  121. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  122. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  123. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  124. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  125. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  126. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  127. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  128. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  129. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  130. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  131. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  132. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  133. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  134. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  135. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  136. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  137. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  138. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  139. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  140. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  141. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  142. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  143. ];
  144. ////////////////////////////////////////////////////////////////////
  145. //
  146. // YmSong.js
  147. //
  148. ////////////////////////////////////////////////////////////////////
  149. function YmSong(stream) {
  150. this.title;
  151. this.author;
  152. this.comment;
  153. this.attribs;
  154. this.clock;
  155. this.digidrums;
  156. this.drums;
  157. this.frames = new Array();
  158. this.frameSize;
  159. this.length;
  160. this.rate;
  161. this.restart;
  162. this.supported = true;
  163. this.data = new dataType();
  164. this.data.data = stream;
  165. this.init = function () {
  166. this.decode();
  167. if (this.attribs & YmConst_INTERLEAVED) this.deinterleave();
  168. for (i = 0; i < this.length; ++i) {
  169. this.frames[i] = this.data.readBytes(0, this.frameSize);
  170. }
  171. }
  172. this.decode = function () {
  173. var digidrum;
  174. var i;
  175. var id = this.data.readMultiByte(4, "txt");
  176. switch (id) {
  177. case "YM2!":
  178. case "YM3!":
  179. case "YM3b":
  180. this.frameSize = 14;
  181. this.length = (this.data.data.length - 4) / this.frameSize;
  182. this.clock = YmConst_ATARI_FREQ;
  183. this.rate = 50;
  184. this.restart = (id != "YM3b") ? 0 : this.data.readByte();
  185. this.attribs = YmConst_INTERLEAVED | YmConst_TIME_CONTROL;
  186. break;
  187. case "YM4!":
  188. this.supported = false;
  189. break;
  190. case "YM5!":
  191. case "YM6!":
  192. id = this.data.readMultiByte(8, "txt");
  193. if (id != "LeOnArD!") {
  194. this.supported = false;
  195. return;
  196. }
  197. this.length = this.data.readInt();
  198. this.attribs = this.data.readInt();
  199. this.drums = this.data.readShort();
  200. this.clock = this.data.readInt();
  201. this.rate = this.data.readShort();
  202. this.restart = this.data.readInt();
  203. this.data.readShort();
  204. if (this.drums) {
  205. this.digidrums = new Array();
  206. for (i = 0; i < this.drums; ++i) {
  207. this.digidrum = new Digidrum(this.data.readInt());
  208. if (this.digidrum.size != 0) {
  209. this.digidrum.wave.data = this.data.readBytes(0, this.digidrum.size);
  210. this.digidrum.convert(this.attribs);
  211. this.digidrums[i] = this.digidrum;
  212. }
  213. }
  214. this.attribs &= (~YmConst_DRUM_4BITS);
  215. }
  216. this.title = this.data.readString();
  217. this.author = this.data.readString();
  218. this.comment = this.data.readString();
  219. this.frameSize = 16;
  220. this.attribs = YmConst_INTERLEAVED | YmConst_TIME_CONTROL;
  221. break;
  222. case "MIX1":
  223. supported = false;
  224. break;
  225. case "YMT1":
  226. case "YMT2":
  227. supported = false;
  228. break;
  229. default:
  230. supported = false;
  231. break;
  232. }
  233. }
  234. this.deinterleave = function () {
  235. var i;
  236. var j;
  237. var s = 0;
  238. var p = new Array();
  239. var r = new Array();
  240. for (i = 0; i < this.frameSize; ++i) p[i] = this.data.pos + (this.length * i);
  241. for (i = 0; i < this.length; ++i) {
  242. for (j = 0; j < this.frameSize; ++j) r[j + s] = this.data.data[i + p[j]];
  243. s += this.frameSize;
  244. }
  245. this.data.data = "";
  246. this.data.data = r;
  247. this.data.pos = 0;
  248. this.attribs &= (~YmConst_INTERLEAVED);
  249. }
  250. this.init();
  251. }
  252. ////////////////////////////////////////////////////////////////////
  253. //
  254. // YmProcessor.js
  255. //
  256. ////////////////////////////////////////////////////////////////////
  257. function YmProcessor(ym) {
  258. this.ym = ym;
  259. this.counter;
  260. this.sound;
  261. this.soundChannel;
  262. this.soundChannelPos;
  263. this.song;
  264. this.loop = 1;
  265. this.stereo = 0;
  266. this.audioFreq;
  267. this.clock;
  268. this.registers = new Array();
  269. this.volumeEnv;
  270. this.buffer;
  271. this.bufferSize;
  272. this.voiceA = new YmChannel(this);;
  273. this.voiceB = new YmChannel(this);;
  274. this.voiceC = new YmChannel(this);;
  275. this.samplesTick;
  276. this.samplesLeft;
  277. this.frame;
  278. this.envData;
  279. this.envPhase;
  280. this.envPos;
  281. this.envShape;
  282. this.envStep;
  283. this.noiseOutput;
  284. this.noisePos;
  285. this.noiseStep;
  286. this.rng;
  287. this.syncBuzzer;
  288. this.syncBuzzerPhase;
  289. this.syncBuzzerStep;
  290. __self = this;
  291. this.init = function () {
  292. var i;
  293. this.bufferSize = YmConst_BUFFER_SIZE;
  294. this.buffer = new Array();
  295. for (i = 0; i < this.bufferSize; ++i) this.buffer[i] = new Sample();
  296. this.envData = YmConst_ENVELOPES;
  297. }
  298. this.load = function (stream) {
  299. var monLHa = new LHa();
  300. this.song = new YmSong(monLHa.unpack(stream));
  301. this.audioFreq = YmConst_PLAYER_FREQ;
  302. this.clock = this.song.clock;
  303. this.samplesTick = this.audioFreq / this.song.rate;
  304. return this.song.supported;
  305. }
  306. this.play = function () {
  307. CODEF_AUDIO_NODE.onaudioprocess = function (event) {
  308. __self.mixer(event);
  309. __self.ym.vu[0] = __self.voiceA.vol;
  310. __self.ym.vu[1] = __self.voiceB.vol;
  311. __self.ym.vu[2] = __self.voiceC.vol;
  312. }
  313. }
  314. this.mixer = function (e) {
  315. var b = 0;
  316. var i = 0;
  317. var mixed = 0;
  318. var mixPos = 0;
  319. var sample;
  320. var size = 0;
  321. var toMix = 0;
  322. var value = 0;
  323. while (mixed < this.bufferSize) {
  324. if (this.samplesLeft == 0) {
  325. if (this.frame >= this.song.length) {
  326. if (this.loop) {
  327. this.frame = this.song.restart;
  328. } else {
  329. this.stop();
  330. return;
  331. }
  332. }
  333. this.syncBuzzerStop();
  334. for (i = 0; i < this.song.frameSize; i++) {
  335. this.registers[i] = this.song.frames[this.frame][i].charCodeAt(0);
  336. }
  337. this.frame++;
  338. //this.registers = this.song.frames[this.frame++];
  339. this.updateEffects(1, 6, 14);
  340. this.updateEffects(3, 8, 15);
  341. this.writeRegisters();
  342. this.samplesLeft = this.samplesTick;
  343. }
  344. toMix = this.samplesLeft;
  345. if ((mixed + toMix) > this.bufferSize)
  346. toMix = this.bufferSize - mixed;
  347. size = mixPos + toMix;
  348. for (i = mixPos; i < size; ++i) {
  349. sample = this.buffer[i];
  350. if (this.noisePos & 65536) {
  351. b = (this.rng & 1) ^ ((this.rng >> 2) & 1);
  352. this.rng = (this.rng >> 1) | (b << 16);
  353. this.noiseOutput ^= (b ? 0 : 65535);
  354. this.noisePos &= 65535;
  355. }
  356. this.volumeEnv = this.envData[Math.floor((this.envShape << 6) + (this.envPhase << 5) + (this.envPos >> 26))];
  357. this.voiceA.computeVolume();
  358. this.voiceB.computeVolume();
  359. this.voiceC.computeVolume();
  360. b = this.voiceA.enabled() & (this.noiseOutput | this.voiceA.mixNoise);
  361. var toto = this.voiceA.getvolume();
  362. sample.voiceA = (b) ? this.voiceA.getvolume() : -1;
  363. b = this.voiceB.enabled() & (this.noiseOutput | this.voiceB.mixNoise);
  364. sample.voiceB = (b) ? this.voiceB.getvolume() : -1;
  365. b = this.voiceC.enabled() & (this.noiseOutput | this.voiceC.mixNoise);
  366. sample.voiceC = (b) ? this.voiceC.getvolume() : -1;
  367. this.voiceA.next();
  368. this.voiceB.next();
  369. this.voiceC.next();
  370. this.noisePos += this.noiseStep;
  371. this.envPos += this.envStep;
  372. if (this.envPos > 2147483647)
  373. this.envPos -= 2147483647;
  374. if (this.envPhase == 0 && this.envPos < this.envStep)
  375. envPhase = 1;
  376. if (this.syncBuzzer) {
  377. this.syncBuzzerPhase += this.syncBuzzerStep;
  378. if (this.syncBuzzerPhase & 1073741824) {
  379. this.envPos = 0;
  380. this.envPhase = 0;
  381. this.syncBuzzerPhase &= 0x3fffffff;
  382. }
  383. }
  384. }
  385. mixed += toMix;
  386. mixPos = size;
  387. this.samplesLeft -= toMix;
  388. }
  389. var l = event.outputBuffer.getChannelData(0);
  390. var r = event.outputBuffer.getChannelData(1);
  391. if (this.stereo) {
  392. for (i = 0; i < this.bufferSize; ++i) {
  393. sample = this.buffer[i];
  394. l[i] = sample.left();
  395. r[i] = sample.right();
  396. }
  397. } else {
  398. for (i = 0; i < this.bufferSize; ++i) {
  399. value = this.buffer[i].mono();
  400. l[i] = value;
  401. r[i] = value;
  402. }
  403. }
  404. }
  405. this.writeRegisters = function () {
  406. var p;
  407. this.registers[0] &= 255;
  408. this.registers[1] &= 15;
  409. this.voiceA.computeTone(this.registers[1], this.registers[0]);
  410. this.registers[2] &= 255;
  411. this.registers[3] &= 15;
  412. this.voiceB.computeTone(this.registers[3], this.registers[2]);
  413. this.registers[4] &= 255;
  414. this.registers[5] &= 15;
  415. this.voiceC.computeTone(this.registers[5], this.registers[4]);
  416. this.registers[6] &= 31;
  417. if (this.registers[6] < 3) {
  418. this.noisePos = 0;
  419. this.noiseOutput = 65535;
  420. this.noiseStep = 0;
  421. } else {
  422. p = this.clock / ((this.registers[6] << 3) * this.audioFreq);
  423. this.noiseStep = Math.floor(p * 32768);
  424. }
  425. this.registers[7] &= 255;
  426. this.voiceA.mixTone = (this.registers[7] & 1) ? 65535 : 0;
  427. this.voiceB.mixTone = (this.registers[7] & 2) ? 65535 : 0;
  428. this.voiceC.mixTone = (this.registers[7] & 4) ? 65535 : 0;
  429. this.voiceA.mixNoise = (this.registers[7] & 8) ? 65535 : 0;
  430. this.voiceB.mixNoise = (this.registers[7] & 16) ? 65535 : 0;
  431. this.voiceC.mixNoise = (this.registers[7] & 32) ? 65535 : 0;
  432. this.registers[8] &= 31;
  433. this.voiceA.setvolume(this.registers[8]);
  434. this.registers[9] &= 31;
  435. this.voiceB.setvolume(this.registers[9]);
  436. this.registers[10] &= 31;
  437. this.voiceC.setvolume(this.registers[10]);
  438. this.registers[11] &= 255;
  439. this.registers[12] &= 255;
  440. p = (this.registers[12] << 8) | this.registers[11];
  441. if (p < 3) {
  442. this.envStep = 0;
  443. } else {
  444. p = this.clock / ((p << 8) * this.audioFreq);
  445. this.envStep = Math.floor(p * 1073741824);
  446. }
  447. if (this.registers[13] == 255) {
  448. this.registers[13] = 0;
  449. } else {
  450. this.registers[13] &= 15;
  451. this.envPhase = 0;
  452. this.envPos = 0;
  453. this.envShape = this.registers[13];
  454. }
  455. }
  456. this.updateEffects = function (code, preDiv, count) {
  457. var index = 0;
  458. var tmpFreq = 0;
  459. var voice = 0;
  460. code = this.registers[code] & 0xf0;
  461. preDiv = (this.registers[preDiv] >> 5) & 7;
  462. count = this.registers[count];
  463. if (code & 0x30) {
  464. voice = ((code & 0x30) >> 4) - 1;
  465. switch (code & 0xc0) {
  466. case 0x00:
  467. case 0x80:
  468. break;
  469. case 0x40:
  470. index = this.registers[voice + 8] & 31;
  471. if ((index >= 0) && (index < this.song.drums)) {
  472. preDiv = YmConst_MFP_PREDIV[preDiv] * count;
  473. if (preDiv > 0) {
  474. tmpFreq = 2457600 / preDiv;
  475. if (voice == 0) {
  476. this.voiceA.drum = this.song.digidrums[index];
  477. this.voiceA.drumStart(tmpFreq);
  478. } else if (voice == 1) {
  479. this.voiceB.drum = this.song.digidrums[index];
  480. this.voiceB.drumStart(tmpFreq);
  481. } else if (voice == 2) {
  482. this.voiceC.drum = this.song.digidrums[index];
  483. this.voiceC.drumStart(tmpFreq);
  484. }
  485. }
  486. }
  487. break;
  488. case 0xc0:
  489. break;
  490. }
  491. }
  492. }
  493. this.syncBuzzerStart = function (timerFreq, shapeEnv) {
  494. this.envShape = this.shapeEnv & 15;
  495. this.syncBuzzerStep = (this.timerFreq * 1073741824) / this.audioFreq;;
  496. this.syncBuzzerPhase = 0;
  497. this.syncBuzzer = true;
  498. }
  499. this.syncBuzzerStop = function () {
  500. this.syncBuzzer = false;
  501. this.syncBuzzerPhase = 0;
  502. this.syncBuzzerStep = 0;
  503. }
  504. this.stop = function () {
  505. this.reset();
  506. return true;
  507. }
  508. this.reset = function () {
  509. var i;
  510. this.voiceA = new YmChannel(this);
  511. this.voiceB = new YmChannel(this);
  512. this.voiceC = new YmChannel(this);
  513. this.samplesLeft = 0;
  514. this.frame = 0;
  515. this.registers = new Array();
  516. for (i = 0; i < 16; ++i)
  517. this.registers[i] = 0;
  518. this.registers[7] = 255;
  519. this.writeRegisters();
  520. this.volumeEnv = 0;
  521. this.noiseOutput = 65535;
  522. this.noisePos = 0;
  523. this.noiseStep = 0;
  524. this.rng = 1;
  525. this.envPhase = 0;
  526. this.envPos = 0;
  527. this.envShape = 0;
  528. this.envStep = 0;
  529. this.syncBuzzerStop();
  530. }
  531. this.init();
  532. this.reset();
  533. CODEF_AUDIO_NODE.connect(CODEF_AUDIO_CONTEXT.destination);
  534. }
  535. ////////////////////////////////////////////////////////////////////
  536. //
  537. // Sample.js
  538. //
  539. ////////////////////////////////////////////////////////////////////
  540. function Sample() {
  541. this.voiceA = -1;
  542. this.voiceB = -1;
  543. this.voiceC = -1;
  544. this.mono = function () {
  545. var v = YmConst_MONO;
  546. var vol = 0.0;
  547. if (this.voiceA > -1) vol += v[this.voiceA];
  548. if (this.voiceB > -1) vol += v[this.voiceB];
  549. if (this.voiceC > -1) vol += v[this.voiceC];
  550. return vol;
  551. }
  552. this.left = function () {
  553. var v = YmConst_STEREO;
  554. var vol = 0.0;
  555. if (this.voiceA > -1) vol += v[this.voiceA];
  556. if (this.voiceB > -1) vol += v[this.voiceB];
  557. return vol;
  558. }
  559. this.right = function () {
  560. var v = YmConst_STEREO;
  561. var vol = 0.0;
  562. if (this.voiceB > -1) vol += v[this.voiceB];
  563. if (this.voiceC > -1) vol += v[this.voiceC];
  564. return vol;
  565. }
  566. }
  567. ////////////////////////////////////////////////////////////////////
  568. //
  569. // YmChannel.js
  570. //
  571. ////////////////////////////////////////////////////////////////////
  572. function YmChannel(processor) {
  573. this.mixNoise = 0;
  574. this.mixTone = 0;
  575. this.mode = 0;
  576. this.position = 0;
  577. this.step = 0;
  578. this.digidrum = 0;
  579. this.drum = 0;
  580. this.drumPos = 0;
  581. this.drumStep = 0;
  582. this.processor = processor;
  583. this.vol = 0;
  584. this.enabled = function () {
  585. return (this.position >> 30) | this.mixTone;
  586. }
  587. this.getvolume = function () {
  588. return (this.mode) ? this.processor.volumeEnv : this.vol;
  589. }
  590. this.setvolume = function (value) {
  591. if (value & 16)
  592. this.mode = true
  593. else
  594. this.mode = false;
  595. this.vol = value;
  596. }
  597. this.next = function () {
  598. this.position += this.step;
  599. if (this.position > 2147483647) this.position -= 2147483647;
  600. }
  601. this.computeTone = function (high, low) {
  602. var p = (high << 8) | low;
  603. if (p < 5) {
  604. this.position = 1073741824;
  605. this.step = 0;
  606. } else {
  607. p = this.processor.clock / ((p << 3) * this.processor.audioFreq);
  608. this.step = Math.floor(p * 1073741824);
  609. }
  610. }
  611. this.computeVolume = function () {
  612. var pos;
  613. if (this.digidrum) {
  614. pos = this.drumPos >> YmConst_DRUM_PREC;
  615. this.vol = this.drum.data[pos] / 16; //6;
  616. this.mixNoise = 65535;
  617. this.mixTone = 65535;
  618. this.drumPos += this.drumStep;
  619. pos = this.drumPos >> YmConst_DRUM_PREC;
  620. if (pos >= this.drum.size)
  621. this.digidrum = false;
  622. }
  623. }
  624. this.drumStart = function (drumFreq) {
  625. this.digidrum = true;
  626. this.drumPos = 0;
  627. this.drumStep = (this.drumFreq << 15) / this.processor.audioFreq;
  628. }
  629. this.drumStop = function () {
  630. this.digidrum = false;
  631. }
  632. }
  633. ////////////////////////////////////////////////////////////////////
  634. //
  635. // Digidrum.js
  636. //
  637. ////////////////////////////////////////////////////////////////////
  638. function Digidrum(size) {
  639. this.data;
  640. this.repeatLen;
  641. this.size;
  642. this.wave = null;
  643. this.size = size;
  644. this.wave = new dataType();
  645. this.convert = function (attribs) {
  646. var b;
  647. var i;
  648. this.data = new Array;
  649. if (attribs & YmConst_DRUM_4BITS) {
  650. for (i = 0; i < this.size; ++i) {
  651. b = (this.wave.readByte() & 15) >> 7;
  652. this.data[i] = YmConst_MONO[b];
  653. }
  654. } else {
  655. for (i = 0; i < this.size; ++i) {
  656. this.data[i] = this.wave.readByte(); // / 255;
  657. }
  658. }
  659. this.wave = null;
  660. }
  661. }
  662. function dataType() {
  663. this.data;
  664. this.pos = 0;
  665. this.endian = "BIG";
  666. this.readBytes = function (offset, nb) {
  667. var tmp = "";
  668. for (var i = 0; i < nb; i++) {
  669. tmp += this.data[offset + this.pos++];
  670. }
  671. return tmp;
  672. }
  673. this.readMultiByte = function (nb, type) {
  674. if (type == "txt") {
  675. var tmp = "";
  676. for (var i = 0; i < nb; i++) {
  677. tmp += this.data[this.pos++]
  678. }
  679. return tmp;
  680. }
  681. }
  682. this.readInt = function () {
  683. var tmp1 = parseInt(this.data[this.pos + 0].charCodeAt(0).toString(16), 16);
  684. var tmp2 = parseInt(this.data[this.pos + 1].charCodeAt(0).toString(16), 16);
  685. var tmp3 = parseInt(this.data[this.pos + 2].charCodeAt(0).toString(16), 16);
  686. var tmp4 = parseInt(this.data[this.pos + 3].charCodeAt(0).toString(16), 16);
  687. if (this.endian == "BIG")
  688. var tmp = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4;
  689. else
  690. var tmp = (tmp4 << 24) | (tmp3 << 16) | (tmp2 << 8) | tmp1;
  691. this.pos += 4;
  692. return tmp;
  693. }
  694. this.readShort = function () {
  695. var tmp1 = parseInt(this.data[this.pos + 0].charCodeAt(0).toString(16), 16);
  696. var tmp2 = parseInt(this.data[this.pos + 1].charCodeAt(0).toString(16), 16);
  697. var tmp = (tmp1 << 8) | tmp2;
  698. this.pos += 2;
  699. return tmp;
  700. }
  701. this.readByte = function () {
  702. var tmp = parseInt(this.data[this.pos].charCodeAt(0).toString(16), 16)
  703. this.pos += 1;
  704. return tmp;
  705. }
  706. this.readString = function () {
  707. var tmp = "";
  708. while (1) {
  709. if (this.data[this.pos++].charCodeAt(0) != 0)
  710. tmp += this.data[this.pos - 1];
  711. else
  712. return tmp;
  713. }
  714. }
  715. this.substr = function (start, nb) {
  716. return this.data.substr(start, nb);
  717. }
  718. this.bytesAvailable = function () {
  719. return this.length - this.pos;
  720. }
  721. }
  722. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  723. //
  724. // LHA depack routine
  725. //
  726. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  727. function LHa() {
  728. this.data;
  729. this.source;
  730. this.buffer;
  731. this.output;
  732. this.srcSize;
  733. this.dstSize;
  734. this.srcPos;
  735. this.dstPos;
  736. this.c_Table;
  737. this.p_Table;
  738. this.c_Len;
  739. this.p_Len;
  740. this.l_Tree;
  741. this.r_Tree;
  742. this.bitBuffer;
  743. this.bitCount;
  744. this.subBuffer;
  745. this.blockSize;
  746. this.fillBufferSize;
  747. this.fillIndex;
  748. this.decodei;
  749. this.decodej;
  750. this.data = "";
  751. this.buffer = new Array();
  752. this.output = new Array();
  753. this.c_Table = new Array();
  754. this.p_Table = new Array();
  755. this.c_Len = new Array();
  756. this.p_Len = new Array();
  757. this.l_Tree = new Array();
  758. this.r_Tree = new Array();
  759. this.unpack = function (source) {
  760. this.header = new LHaHeader(source);
  761. if (this.header.size == 0 || this.header.method != "-lh5-" || this.header.level != 0) return source.data;
  762. this.source = source;
  763. this.srcSize = this.header.packed;
  764. this.srcPos = this.source.pos;
  765. this.dstSize = this.header.original;
  766. this.fillBufferSize = 0;
  767. this.bitBuffer = 0;
  768. this.bitCount = 0;
  769. this.subBuffer = 0;
  770. this.fillBuffer(16);
  771. this.blockSize = 0;
  772. this.decodej = 0;
  773. var l = this.dstSize;
  774. var n;
  775. var np;
  776. while (l != 0) {
  777. n = l > 8192 ? 8192 : l;
  778. this.decode(n);
  779. np = n > this.dstSize ? this.dstSize : n;
  780. if (np > 0) {
  781. this.output.pos = 0;
  782. for (var yop = 0; yop < np; yop++) {
  783. this.data += String.fromCharCode(this.output[yop]);
  784. }
  785. this.dstPos += np;
  786. this.dstSize -= np;
  787. }
  788. l -= n;
  789. }
  790. this.buffer = "";
  791. this.output = new Array;
  792. return this.data;
  793. }
  794. this.decode = function (count) {
  795. var c;
  796. var r = 0;
  797. while (--this.decodej >= 0) {
  798. this.output[r] = this.output[this.decodei];
  799. this.decodei = ++this.decodei & 8191;
  800. if (++r == count) return;
  801. }
  802. for (;;) {
  803. c = this.decode_c();
  804. if (c <= 255) {
  805. this.output[r] = c;
  806. if (++r == count) return;
  807. } else {
  808. this.decodej = c - 253;
  809. this.decodei = (r - this.decode_p() - 1) & 8191;
  810. while (--this.decodej >= 0) {
  811. this.output[r] = this.output[this.decodei];
  812. this.decodei = ++this.decodei & 8191;
  813. if (++r == count) return;
  814. }
  815. }
  816. }
  817. }
  818. this.decode_c = function () {
  819. var j;
  820. var mask = 0;
  821. if (this.blockSize == 0) {
  822. this.blockSize = this.getBits(16);
  823. this.read_p(19, 5, 3);
  824. this.read_c();
  825. this.read_p(14, 4, -1);
  826. }
  827. this.blockSize--;
  828. j = this.c_Table[this.bitBuffer >> 4];
  829. if (j >= 510) {
  830. mask = 1 << 3;
  831. do {
  832. j = (this.bitBuffer & mask) ? this.r_Tree[j] : this.l_Tree[j];
  833. mask >>= 1;
  834. } while (j >= 510);
  835. }
  836. this.fillBuffer(this.c_Len[j]);
  837. return j & 0xffff;
  838. }
  839. this.decode_p = function () {
  840. var j = this.p_Table[this.bitBuffer >> 8];
  841. var mask = 0;
  842. if (j >= 14) {
  843. mask = 1 << 7;
  844. do {
  845. j = (this.bitBuffer & mask) ? this.r_Tree[j] : this.l_Tree[j];
  846. mask >>= 1;
  847. } while (j >= 14);
  848. }
  849. this.fillBuffer(this.p_Len[j]);
  850. if (j != 0) j = (1 << (j - 1)) + this.getBits(j - 1);
  851. return j & 0xffff;
  852. }
  853. this.read_c = function () {
  854. var c;
  855. var i = 0;
  856. var mask = 0
  857. var n = this.getBits(9);
  858. if (n == 0) {
  859. c = this.getBits(9);
  860. for (i = 0; i < 510; ++i) this.c_Len[i] = 0;
  861. for (i = 0; i < 4096; ++i) this.c_Table[i] = c;
  862. } else {
  863. while (i < n) {
  864. c = this.p_Table[this.bitBuffer >> 8];
  865. if (c >= 19) {
  866. mask = 1 << 7;
  867. do {
  868. c = (this.bitBuffer & mask) ? this.r_Tree[c] : this.l_Tree[c];
  869. mask >>= 1;
  870. } while (c >= 19);
  871. }
  872. this.fillBuffer(this.p_Len[c]);
  873. if (c <= 2) {
  874. if (c == 0)
  875. c = 1;
  876. else if (c == 1)
  877. c = this.getBits(4) + 3;
  878. else
  879. c = this.getBits(9) + 20;
  880. while (--c >= 0) this.c_Len[i++] = 0;
  881. } else {
  882. this.c_Len[i++] = c - 2;
  883. }
  884. }
  885. while (i < 510) this.c_Len[i++] = 0;
  886. this.makeTable(510, this.c_Len, 12, this.c_Table);
  887. }
  888. }
  889. this.read_p = function (nn, nbit, iSpecial) {
  890. var c;
  891. var i = 0;
  892. var mask = 0;
  893. var n = this.getBits(nbit);
  894. if (n == 0) {
  895. c = this.getBits(nbit);
  896. for (i = 0; i < nn; ++i) this.p_Len[i] = 0;
  897. for (i = 0; i < 256; ++i) this.p_Table[i] = c;
  898. } else {
  899. while (i < n) {
  900. c = this.bitBuffer >> 13;
  901. if (c == 7) {
  902. mask = 1 << 12;
  903. while (mask & this.bitBuffer) {
  904. mask >>= 1;
  905. c++;
  906. }
  907. }
  908. this.fillBuffer(c < 7 ? 3 : c - 3);
  909. this.p_Len[i++] = c;
  910. if (i == iSpecial) {
  911. c = this.getBits(2);
  912. while (--c >= 0) this.p_Len[i++] = 0;
  913. }
  914. }
  915. while (i < nn) this.p_Len[i++] = 0;
  916. this.makeTable(nn, this.p_Len, 8, this.p_Table);
  917. }
  918. }
  919. this.getBits = function (n) {
  920. var r = this.bitBuffer >> (16 - n);
  921. this.fillBuffer(n);
  922. return r & 0xffff;
  923. }
  924. this.fillBuffer = function (n) {
  925. var np;
  926. this.bitBuffer = (this.bitBuffer << n) & 0xffff;
  927. while (n > this.bitCount) {
  928. this.bitBuffer |= this.subBuffer << (n -= this.bitCount);
  929. this.bitBuffer &= 0xffff;
  930. if (this.fillBufferSize == 0) {
  931. this.fillIndex = 0;
  932. np = this.srcSize > 4064 ? 4064 : this.srcSize;
  933. if (np > 0) {
  934. this.source.pos = this.srcPos;
  935. this.buffer = this.source.readBytes(0, np);
  936. this.srcPos += np;
  937. this.srcSize -= np;
  938. }
  939. this.fillBufferSize = np;
  940. }
  941. if (this.fillBufferSize > 0) {
  942. this.fillBufferSize--;
  943. this.subBuffer = this.buffer[this.fillIndex++].charCodeAt(0);
  944. } else {
  945. this.subBuffer = 0;
  946. }
  947. this.bitCount = 8;
  948. }
  949. this.bitBuffer |= this.subBuffer >> (this.bitCount -= n);
  950. this.bitBuffer &= 0xffff;
  951. }
  952. this.makeTable = function (nchar, bitlen, tablebits, table) {
  953. var a = nchar;
  954. var h;
  955. var i;
  956. var j;
  957. var k;
  958. var l;
  959. var n;
  960. var p;
  961. var t;
  962. var r;
  963. var c = new Array();
  964. var w = new Array();
  965. var s = new Array();
  966. var mask = 1 << (15 - tablebits);
  967. for (i = 0; i < nchar; ++i)
  968. c[i] = 0;
  969. for (i = 0; i < nchar; ++i) c[bitlen[i]]++;
  970. s[1] = 0;
  971. for (i = 1; i < 17; ++i) s[i + 1] = (s[i] + (c[i] << (16 - i))) & 0xffff;
  972. if (s[17] != 0) return false;
  973. j = 16 - tablebits;
  974. for (i = 1; i <= tablebits; ++i) {
  975. s[i] >>= j;
  976. w[i] = 1 << (tablebits - i);
  977. }
  978. while (i < 17) w[i] = 1 << (16 - i++);
  979. i = s[tablebits + 1] >> j;
  980. if (i != 0) {
  981. k = 1 << tablebits;
  982. while (i != k) table[i++] = 0;
  983. }
  984. for (h = 0; h < nchar; ++h) {
  985. if ((l = bitlen[h]) == 0) continue;
  986. n = s[l] + w[l];
  987. if (l <= tablebits) {
  988. for (i = s[l]; i < n; ++i) table[i] = h;
  989. } else {
  990. i = l - tablebits;
  991. k = s[l];
  992. p = k >> j;
  993. t = table;
  994. while (i != 0) {
  995. if (t[p] == 0) {
  996. this.l_Tree[a] = 0;
  997. this.r_Tree[a] = 0;
  998. t[p] = a++;
  999. }
  1000. r = (k & mask) ? this.r_Tree : this.l_Tree;
  1001. k <<= 1;
  1002. i--;
  1003. }
  1004. r[t[p]] = h;
  1005. }
  1006. s[l] = n;
  1007. }
  1008. return true;
  1009. }
  1010. }
  1011. function LHaHeader(source) {
  1012. this.size;
  1013. this.checksum;
  1014. this.method;
  1015. this.packed;
  1016. this.original;
  1017. this.timeStamp;
  1018. this.attribute;
  1019. this.level;
  1020. this.nameLength;
  1021. this.name;
  1022. source.endian = "LITTLE";
  1023. source.pos = 0;
  1024. this.size = source.readByte();
  1025. this.checksum = source.readByte();
  1026. this.method = source.readMultiByte(5, "txt");
  1027. this.packed = source.readInt();
  1028. this.original = source.readInt();
  1029. this.timeStamp = source.readInt();
  1030. this.attribute = source.readByte();
  1031. this.level = source.readByte();
  1032. this.nameLength = source.readByte();
  1033. this.name = source.readMultiByte(this.nameLength, "txt");
  1034. source.readShort();
  1035. }
  1036. window.YM = YM;
  1037. }());