UNPKG

cdf

Version:

A library for creating oldschool demo-like animations with JavaScript

1,132 lines (913 loc) 31.9 kB
/*! YM Playback by Antoine Santo Aka NoNameNo, (c) 2011, : http://codef.santo.fr */ (function(global){ var lib = global.cdf || {}; var CODEF_AUDIO_CONTEXT = lib.CODEF_AUDIO_CONTEXT = null; var CODEF_AUDIO_NODE =lib.CODEF_AUDIO_NODE = null; window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext; var music = lib.music = function(type) { if (AudioContext) { switch (type) { case "YM": CODEF_AUDIO_CONTEXT = new AudioContext(); CODEF_AUDIO_NODE = CODEF_AUDIO_CONTEXT.createScriptProcessor(8192); this.loader = {}; this.loader["player"] = new YmProcessor(); this.stereo_value = false; break; default : this.stereo_value = false; break; } } var __self = this; var loadSound = function(url, onReady){ var fetch = new XMLHttpRequest(); if(AudioContext){ fetch.open('GET', url); fetch.overrideMimeType("text/plain; charset=x-user-defined"); fetch.onreadystatechange = function(){ if (this.readyState === 4 && this.status === 200) { onReady.apply(this); __self.loader.player.stereo = __self.stereo_value; } }; fetch.send(); } return fetch; }; if (type === "YM") { this.LoadAndRun = function (zic) { loadSound(zic, function(){ var t = this.responseText || ""; var ff = []; var mx = t.length; var scc = String.fromCharCode; for (var z = 0; z < mx; z++) { ff[z] = scc(t.charCodeAt(z) & 255); } var binString = new dataType(); binString.data = ff.join(""); YmConst_PLAYER_FREQ = CODEF_AUDIO_CONTEXT.sampleRate; __self.loader.player.load(binString); }); } } else { this.LoadAndRun = function (zic) { this.loader = window.neoart.FileLoader; loadSound(zic, function(){ __self.loader.player = null; __self.loader.load(this.response); __self.loader.player.reset(); __self.loader.player.play(); }).responseType = 'arraybuffer'; } } this.stereo = function (stat) { this.stereo_value = stat; }; return this; }; var YmConst_BUFFER_SIZE = 8192; var YmConst_PLAYER_FREQ = 48000; var YmConst_DRUM_PREC = 15; var YmConst_AMSTRAD_FREQ = 1000000; var YmConst_ATARI_FREQ = 2000000; var YmConst_SPECTRUM_FREQ = 1773400; var YmConst_INTERLEAVED = 1; var YmConst_DRUM_SIGNED = 2; var YmConst_DRUM_4BITS = 4; var YmConst_TIME_CONTROL = 8; var YmConst_LOOP_MODE = 16; var YmConst_MFP_PREDIV = [0, 4, 10, 16, 50, 64, 100, 200]; var YmConst_MONO = [ 0.00063071586250394, 0.00163782667521185, 0.00269580167037975, 0.00383515935748365, 0.00590024516535946, 0.00787377544480728, 0.01174962614825892, 0.01602221747489853, 0.02299061047191789, 0.03141371908729311, 0.04648986276843572, 0.06340728985463016, 0.09491256447035126, 0.13414919481999166, 0.21586759036022013, 0.33333333333333333 ]; var YmConst_STEREO = [ 0.00094607379375591, 0.00245674001281777, 0.00404370250556963, 0.00575273903622547, 0.00885036774803918, 0.01181066316721091, 0.01762443922238838, 0.02403332621234779, 0.03448591570787683, 0.04712057863093966, 0.06973479415265358, 0.09511093478194525, 0.14236884670552690, 0.20122379222998749, 0.32380138554033021, 0.50000000000000000 ]; var YmConst_ENVELOPES = [ 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 ]; var YmSong = function(stream) { this.frames = []; this.supported = true; this.data = new dataType(); this.data.data = stream; this.init = function () { this.decode(); if (this.attribs & YmConst_INTERLEAVED) this.deinterleave(); for (i = 0; i < this.length; ++i) { this.frames[i] = this.data.readBytes(0, this.frameSize); } } this.decode = function () { var digidrum; var i; var id = this.data.readMultiByte(4, "txt"); switch (id) { case "YM2!": case "YM3!": case "YM3b": this.frameSize = 14; this.length = (this.data.data.length - 4) / this.frameSize; this.clock = YmConst_ATARI_FREQ; this.rate = 50; this.restart = (id != "YM3b") ? 0 : this.data.readByte(); this.attribs = YmConst_INTERLEAVED | YmConst_TIME_CONTROL; break; case "YM4!": this.supported = false; break; case "YM5!": case "YM6!": id = this.data.readMultiByte(8, "txt"); if (id != "LeOnArD!") { this.supported = false; return; } this.length = this.data.readInt(); this.attribs = this.data.readInt(); this.drums = this.data.readShort(); this.clock = this.data.readInt(); this.rate = this.data.readShort(); this.restart = this.data.readInt(); this.data.readShort(); if (this.drums) { this.digidrums = []; for (i = 0; i < this.drums; ++i) { this.digidrum = new Digidrum(this.data.readInt()); if (this.digidrum.size != 0) { this.digidrum.wave.data = this.data.readBytes(0, this.digidrum.size); this.digidrum.convert(this.attribs); this.digidrums[i] = this.digidrum; } } this.attribs &= (~YmConst_DRUM_4BITS); } this.title = this.data.readString(); this.author = this.data.readString(); this.comment = this.data.readString(); this.frameSize = 16; this.attribs = YmConst_INTERLEAVED | YmConst_TIME_CONTROL; break; case "MIX1": supported = false; break; case "YMT1": case "YMT2": supported = false; break; default: supported = false; break; } } this.deinterleave = function () { var i; var j; var s = 0; var p = []; var r = []; for (i = 0; i < this.frameSize; ++i) p[i] = this.data.pos + (this.length * i); for (i = 0; i < this.length; ++i) { for (j = 0; j < this.frameSize; ++j) r[j + s] = this.data.data[i + p[j]]; s += this.frameSize; } this.data.data = ""; this.data.data = r; this.data.pos = 0; this.attribs &= (~YmConst_INTERLEAVED); } this.init(); }; var YmProcessor = function() { this.loop = 1; this.stereo = 0; this.registers = []; this.voiceA = new YmChannel(this); this.voiceB = new YmChannel(this); this.voiceC = new YmChannel(this); var __self = this; this.init = function () { var i; this.bufferSize = YmConst_BUFFER_SIZE; this.buffer = []; for (i = 0; i < this.bufferSize; ++i) this.buffer[i] = new Sample(); this.envData = YmConst_ENVELOPES; }; this.load = function (stream) { var monLHa = new LHa(); this.song = new YmSong(monLHa.unpack(stream)); this.audioFreq = YmConst_PLAYER_FREQ; this.clock = this.song.clock; this.samplesTick = this.audioFreq / this.song.rate; CODEF_AUDIO_NODE.onaudioprocess = function (event) { __self.mixer(event); }; return this.song.supported; }; this.mixer = function (e) { var b = 0; var i = 0; var mixed = 0; var mixPos = 0; var sample; var size = 0; var toMix = 0; var value = 0; while (mixed < this.bufferSize) { if (this.samplesLeft === 0) { if (this.frame >= this.song.length) { if (this.loop) { this.frame = this.song.restart; } else { this.stop(); return; } } this.syncBuzzerStop(); for (i = 0; i < this.song.frameSize; i++) { this.registers[i] = this.song.frames[this.frame][i].charCodeAt(0); } this.frame++; //this.registers = this.song.frames[this.frame++]; this.updateEffects(1, 6, 14); this.updateEffects(3, 8, 15); this.writeRegisters(); this.samplesLeft = this.samplesTick; } toMix = this.samplesLeft; if ((mixed + toMix) > this.bufferSize) toMix = this.bufferSize - mixed; size = mixPos + toMix; for (i = mixPos; i < size; ++i) { sample = this.buffer[i]; if (this.noisePos & 65536) { b = (this.rng & 1) ^ ((this.rng >> 2) & 1); this.rng = (this.rng >> 1) | (b << 16); this.noiseOutput ^= (b ? 0 : 65535); this.noisePos &= 65535; } this.volumeEnv = this.envData[Math.floor((this.envShape << 6) + (this.envPhase << 5) + (this.envPos >> 26))]; this.voiceA.computeVolume(); this.voiceB.computeVolume(); this.voiceC.computeVolume(); b = this.voiceA.enabled() & (this.noiseOutput | this.voiceA.mixNoise); var toto = this.voiceA.getvolume(); sample.voiceA = (b) ? this.voiceA.getvolume() : -1; b = this.voiceB.enabled() & (this.noiseOutput | this.voiceB.mixNoise); sample.voiceB = (b) ? this.voiceB.getvolume() : -1; b = this.voiceC.enabled() & (this.noiseOutput | this.voiceC.mixNoise); sample.voiceC = (b) ? this.voiceC.getvolume() : -1; this.voiceA.next(); this.voiceB.next(); this.voiceC.next(); this.noisePos += this.noiseStep; this.envPos += this.envStep; if (this.envPos > 2147483647) this.envPos -= 2147483647; if (this.envPhase == 0 && this.envPos < this.envStep) envPhase = 1; if (this.syncBuzzer) { this.syncBuzzerPhase += this.syncBuzzerStep; if (this.syncBuzzerPhase & 1073741824) { this.envPos = 0; this.envPhase = 0; this.syncBuzzerPhase &= 0x3fffffff; } } } mixed += toMix; mixPos = size; this.samplesLeft -= toMix; } var l = e.outputBuffer.getChannelData(0); var r = e.outputBuffer.getChannelData(1); if (this.stereo) { for (i = 0; i < this.bufferSize; ++i) { sample = this.buffer[i]; l[i] = sample.left(); r[i] = sample.right(); } } else { for (i = 0; i < this.bufferSize; ++i) { value = this.buffer[i].mono(); l[i] = value; r[i] = value; } } }; this.writeRegisters = function () { var p; this.registers[0] &= 255; this.registers[1] &= 15; this.voiceA.computeTone(this.registers[1], this.registers[0]); this.registers[2] &= 255; this.registers[3] &= 15; this.voiceB.computeTone(this.registers[3], this.registers[2]); this.registers[4] &= 255; this.registers[5] &= 15; this.voiceC.computeTone(this.registers[5], this.registers[4]); this.registers[6] &= 31; if (this.registers[6] < 3) { this.noisePos = 0; this.noiseOutput = 65535; this.noiseStep = 0; } else { p = this.clock / ((this.registers[6] << 3) * this.audioFreq); this.noiseStep = Math.floor(p * 32768); } this.registers[7] &= 255; this.voiceA.mixTone = (this.registers[7] & 1) ? 65535 : 0; this.voiceB.mixTone = (this.registers[7] & 2) ? 65535 : 0; this.voiceC.mixTone = (this.registers[7] & 4) ? 65535 : 0; this.voiceA.mixNoise = (this.registers[7] & 8) ? 65535 : 0; this.voiceB.mixNoise = (this.registers[7] & 16) ? 65535 : 0; this.voiceC.mixNoise = (this.registers[7] & 32) ? 65535 : 0; this.registers[8] &= 31; this.voiceA.setvolume(this.registers[8]); this.registers[9] &= 31; this.voiceB.setvolume(this.registers[9]); this.registers[10] &= 31; this.voiceC.setvolume(this.registers[10]); this.registers[11] &= 255; this.registers[12] &= 255; p = (this.registers[12] << 8) | this.registers[11]; if (p < 3) { this.envStep = 0; } else { p = this.clock / ((p << 8) * this.audioFreq); this.envStep = Math.floor(p * 1073741824); } if (this.registers[13] === 255) { this.registers[13] = 0; } else { this.registers[13] &= 15; this.envPhase = 0; this.envPos = 0; this.envShape = this.registers[13]; } } this.updateEffects = function (code, preDiv, count) { var index = 0; var tmpFreq = 0; var voice = 0; code = this.registers[code] & 0xf0; preDiv = (this.registers[preDiv] >> 5) & 7; count = this.registers[count]; if (code & 0x30) { voice = ((code & 0x30) >> 4) - 1; switch (code & 0xc0) { case 0x00: case 0x80: break; case 0x40: index = this.registers[voice + 8] & 31; if ((index >= 0) && (index < this.song.drums)) { preDiv = YmConst_MFP_PREDIV[preDiv] * count; if (preDiv > 0) { tmpFreq = 2457600 / preDiv; if (voice === 0) { this.voiceA.drum = this.song.digidrums[index]; this.voiceA.drumStart(tmpFreq); } else if (voice === 1) { this.voiceB.drum = this.song.digidrums[index]; this.voiceB.drumStart(tmpFreq); } else if (voice === 2) { this.voiceC.drum = this.song.digidrums[index]; this.voiceC.drumStart(tmpFreq); } } } break; case 0xc0: break; } } }; this.syncBuzzerStart = function (timerFreq, shapeEnv) { this.envShape = this.shapeEnv & 15; this.syncBuzzerStep = (this.timerFreq * 1073741824) / this.audioFreq; this.syncBuzzerPhase = 0; this.syncBuzzer = true; }; this.syncBuzzerStop = function () { this.syncBuzzer = false; this.syncBuzzerPhase = 0; this.syncBuzzerStep = 0; }; this.stop = function () { this.reset(); return true; }; this.reset = function () { var i; this.voiceA = new YmChannel(this); this.voiceB = new YmChannel(this); this.voiceC = new YmChannel(this); this.samplesLeft = 0; this.frame = 0; this.registers = []; for (i = 0; i < 16; ++i) this.registers[i] = 0; this.registers[7] = 255; this.writeRegisters(); this.volumeEnv = 0; this.noiseOutput = 65535; this.noisePos = 0; this.noiseStep = 0; this.rng = 1; this.envPhase = 0; this.envPos = 0; this.envShape = 0; this.envStep = 0; this.syncBuzzerStop(); }; this.init(); this.reset(); CODEF_AUDIO_NODE.connect(CODEF_AUDIO_CONTEXT.destination); }; var Sample = function() { this.voiceA = -1; this.voiceB = -1; this.voiceC = -1; this.mono = function () { var v = YmConst_MONO; var vol = 0.0; if (this.voiceA > -1) vol += v[this.voiceA]; if (this.voiceB > -1) vol += v[this.voiceB]; if (this.voiceC > -1) vol += v[this.voiceC]; return vol; }; this.left = function () { var v = YmConst_STEREO; var vol = 0.0; if (this.voiceA > -1) vol += v[this.voiceA]; if (this.voiceB > -1) vol += v[this.voiceB]; return vol; }; this.right = function () { var v = YmConst_STEREO; var vol = 0.0; if (this.voiceB > -1) vol += v[this.voiceB]; if (this.voiceC > -1) vol += v[this.voiceC]; return vol; } }; var YmChannel = function(processor) { this.mixNoise = 0; this.mixTone = 0; this.mode = 0; this.position = 0; this.step = 0; this.digidrum = 0; this.drum = 0; this.drumPos = 0; this.drumStep = 0; this.processor = processor; this.vol = 0; this.enabled = function () { return (this.position >> 30) | this.mixTone; }; this.getvolume = function () { return (this.mode) ? this.processor.volumeEnv : this.vol; }; this.setvolume = function (value) { this.mode = !!(value&16); this.vol = value; }; this.next = function () { this.position += this.step; if (this.position > 2147483647) this.position -= 2147483647; }; this.computeTone = function (high, low) { var p = (high << 8) | low; if (p < 5) { this.position = 1073741824; this.step = 0; } else { p = this.processor.clock / ((p << 3) * this.processor.audioFreq); this.step = Math.floor(p * 1073741824); } }; this.computeVolume = function () { var pos; if (this.digidrum) { pos = this.drumPos >> YmConst_DRUM_PREC; this.vol = this.drum.data[pos] / 16;//6; this.mixNoise = 65535; this.mixTone = 65535; this.drumPos += this.drumStep; pos = this.drumPos >> YmConst_DRUM_PREC; if (pos >= this.drum.size) this.digidrum = false; } }; this.drumStart = function (drumFreq) { this.digidrum = true; this.drumPos = 0; this.drumStep = (this.drumFreq << 15) / this.processor.audioFreq; }; this.drumStop = function () { this.digidrum = false; } }; var Digidrum = function(size) { this.wave = null; this.size = size; this.wave = new dataType(); this.convert = function (attribs) { var b; var i; this.data = []; if (attribs & YmConst_DRUM_4BITS) { for (i = 0; i < this.size; ++i) { b = (this.wave.readByte() & 15) >> 7; this.data[i] = YmConst_MONO[b]; } } else { for (i = 0; i < this.size; ++i) { this.data[i] = this.wave.readByte();// / 255; } } this.wave = null; } }; var dataType = function() { this.pos = 0; this.endian = "BIG"; this.readBytes = function (offset, nb) { var tmp = ""; for (var i = 0; i < nb; i++) { tmp += this.data[offset + this.pos++]; } return tmp; }; this.readMultiByte = function (nb, type) { if (type === "txt") { var tmp = ""; for (var i = 0; i < nb; i++) { tmp += this.data[this.pos++] } return tmp; } }; this.readInt = function () { var tmp; var tmp1 = parseInt(this.data[this.pos].charCodeAt(0).toString(16), 16); var tmp2 = parseInt(this.data[this.pos + 1].charCodeAt(0).toString(16), 16); var tmp3 = parseInt(this.data[this.pos + 2].charCodeAt(0).toString(16), 16); var tmp4 = parseInt(this.data[this.pos + 3].charCodeAt(0).toString(16), 16); if (this.endian === "BIG") tmp = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4; else tmp = (tmp4 << 24) | (tmp3 << 16) | (tmp2 << 8) | tmp1; this.pos += 4; return tmp; }; this.readShort = function () { var tmp1 = parseInt(this.data[this.pos].charCodeAt(0).toString(16), 16); var tmp2 = parseInt(this.data[this.pos + 1].charCodeAt(0).toString(16), 16); var tmp = (tmp1 << 8) | tmp2; this.pos += 2; return tmp; }; this.readByte = function () { var tmp = parseInt(this.data[this.pos].charCodeAt(0).toString(16), 16) this.pos += 1; return tmp; }; this.readString = function () { var tmp = ""; while (1) { if (this.data[this.pos++].charCodeAt(0) !== 0) tmp += this.data[this.pos - 1]; else return tmp; } }; this.substr = function (start, nb) { return this.data.substr(start, nb); }; this.bytesAvailable = function () { return this.length - this.pos; }; }; var LHa = function() { this.data = ""; this.buffer = []; this.output = []; this.c_Table = []; this.p_Table = []; this.c_Len = []; this.p_Len = []; this.l_Tree = []; this.r_Tree = []; this.unpack = function (source) { this.header = new LHaHeader(source); if (this.header.size == 0 || this.header.method != "-lh5-" || this.header.level != 0) return source.data; this.source = source; this.srcSize = this.header.packed; this.srcPos = this.source.pos; this.dstSize = this.header.original; this.fillBufferSize = 0; this.bitBuffer = 0; this.bitCount = 0; this.subBuffer = 0; this.fillBuffer(16); this.blockSize = 0; this.decodej = 0; var l = this.dstSize; var n; var np; while (l != 0) { n = l > 8192 ? 8192 : l; this.decode(n); np = n > this.dstSize ? this.dstSize : n; if (np > 0) { this.output.pos = 0; for (var yop = 0; yop < np; yop++) { this.data += String.fromCharCode(this.output[yop]); } this.dstPos += np; this.dstSize -= np; } l -= n; } this.buffer = ""; this.output = []; return this.data; } this.decode = function (count) { var c; var r = 0; while (--this.decodej >= 0) { this.output[r] = this.output[this.decodei]; this.decodei = ++this.decodei & 8191; if (++r == count) return; } for (; ;) { c = this.decode_c(); if (c <= 255) { this.output[r] = c; if (++r == count) return; } else { this.decodej = c - 253; this.decodei = (r - this.decode_p() - 1) & 8191; while (--this.decodej >= 0) { this.output[r] = this.output[this.decodei]; this.decodei = ++this.decodei & 8191; if (++r == count) return; } } } } this.decode_c = function () { var j; var mask = 0; if (this.blockSize == 0) { this.blockSize = this.getBits(16); this.read_p(19, 5, 3); this.read_c(); this.read_p(14, 4, -1); } this.blockSize--; j = this.c_Table[this.bitBuffer >> 4]; if (j >= 510) { mask = 1 << 3; do { j = (this.bitBuffer & mask) ? this.r_Tree[j] : this.l_Tree[j]; mask >>= 1; } while (j >= 510); } this.fillBuffer(this.c_Len[j]); return j & 0xffff; } this.decode_p = function () { var j = this.p_Table[this.bitBuffer >> 8]; var mask = 0; if (j >= 14) { mask = 1 << 7; do { j = (this.bitBuffer & mask) ? this.r_Tree[j] : this.l_Tree[j]; mask >>= 1; } while (j >= 14); } this.fillBuffer(this.p_Len[j]); if (j != 0) j = (1 << (j - 1)) + this.getBits(j - 1); return j & 0xffff; } this.read_c = function () { var c; var i = 0; var mask = 0 var n = this.getBits(9); if (n == 0) { c = this.getBits(9); for (i = 0; i < 510; ++i) this.c_Len[i] = 0; for (i = 0; i < 4096; ++i) this.c_Table[i] = c; } else { while (i < n) { c = this.p_Table[this.bitBuffer >> 8]; if (c >= 19) { mask = 1 << 7; do { c = (this.bitBuffer & mask) ? this.r_Tree[c] : this.l_Tree[c]; mask >>= 1; } while (c >= 19); } this.fillBuffer(this.p_Len[c]); if (c <= 2) { if (c == 0) c = 1; else if (c == 1) c = this.getBits(4) + 3; else c = this.getBits(9) + 20; while (--c >= 0) this.c_Len[i++] = 0; } else { this.c_Len[i++] = c - 2; } } while (i < 510) this.c_Len[i++] = 0; this.makeTable(510, this.c_Len, 12, this.c_Table); } } this.read_p = function (nn, nbit, iSpecial) { var c; var i = 0; var mask = 0; var n = this.getBits(nbit); if (n == 0) { c = this.getBits(nbit); for (i = 0; i < nn; ++i) this.p_Len[i] = 0; for (i = 0; i < 256; ++i) this.p_Table[i] = c; } else { while (i < n) { c = this.bitBuffer >> 13; if (c == 7) { mask = 1 << 12; while (mask & this.bitBuffer) { mask >>= 1; c++; } } this.fillBuffer(c < 7 ? 3 : c - 3); this.p_Len[i++] = c; if (i == iSpecial) { c = this.getBits(2); while (--c >= 0) this.p_Len[i++] = 0; } } while (i < nn) this.p_Len[i++] = 0; this.makeTable(nn, this.p_Len, 8, this.p_Table); } } this.getBits = function (n) { var r = this.bitBuffer >> (16 - n); this.fillBuffer(n); return r & 0xffff; } this.fillBuffer = function (n) { var np; this.bitBuffer = (this.bitBuffer << n) & 0xffff; while (n > this.bitCount) { this.bitBuffer |= this.subBuffer << (n -= this.bitCount); this.bitBuffer &= 0xffff; if (this.fillBufferSize == 0) { this.fillIndex = 0; np = this.srcSize > 4064 ? 4064 : this.srcSize; if (np > 0) { this.source.pos = this.srcPos; this.buffer = this.source.readBytes(0, np); this.srcPos += np; this.srcSize -= np; } this.fillBufferSize = np; } if (this.fillBufferSize > 0) { this.fillBufferSize--; this.subBuffer = this.buffer[this.fillIndex++].charCodeAt(0); } else { this.subBuffer = 0; } this.bitCount = 8; } this.bitBuffer |= this.subBuffer >> (this.bitCount -= n); this.bitBuffer &= 0xffff; } this.makeTable = function (nchar, bitlen, tablebits, table) { var a = nchar; var h; var i; var j; var k; var l; var n; var p; var t; var r; var c = []; var w = []; var s = []; var mask = 1 << (15 - tablebits); for (i = 0; i < nchar; ++i) c[i] = 0; for (i = 0; i < nchar; ++i) c[bitlen[i]]++; s[1] = 0; for (i = 1; i < 17; ++i) s[i + 1] = (s[i] + (c[i] << (16 - i))) & 0xffff; if (s[17] != 0) return false; j = 16 - tablebits; for (i = 1; i <= tablebits; ++i) { s[i] >>= j; w[i] = 1 << (tablebits - i); } while (i < 17) w[i] = 1 << (16 - i++); i = s[tablebits + 1] >> j; if (i != 0) { k = 1 << tablebits; while (i != k) table[i++] = 0; } for (h = 0; h < nchar; ++h) { if ((l = bitlen[h]) == 0) continue; n = s[l] + w[l]; if (l <= tablebits) { for (i = s[l]; i < n; ++i) table[i] = h; } else { i = l - tablebits; k = s[l]; p = k >> j; t = table; while (i != 0) { if (t[p] == 0) { this.l_Tree[a] = 0; this.r_Tree[a] = 0; t[p] = a++; } r = (k & mask) ? this.r_Tree : this.l_Tree; k <<= 1; i--; } r[t[p]] = h; } s[l] = n; } return true; } }; var LHaHeader = function(source) { source.endian = "LITTLE"; source.pos = 0; this.size = source.readByte(); this.checksum = source.readByte(); this.method = source.readMultiByte(5, "txt"); this.packed = source.readInt(); this.original = source.readInt(); this.timeStamp = source.readInt(); this.attribute = source.readByte(); this.level = source.readByte(); this.nameLength = source.readByte(); this.name = source.readMultiByte(this.nameLength, "txt"); source.readShort(); }; if(typeof module!=='undefined'&& module.exports){module.exports=lib;}else{global.cdf=lib;} })(window);