diff --git a/library/jy4340132-aaa/adpcm.js b/library/jy4340132-aaa/adpcm.js
new file mode 100644
index 00000000..cd2b0a10
--- /dev/null
+++ b/library/jy4340132-aaa/adpcm.js
@@ -0,0 +1,61 @@
+
+
+class Adpcm extends AudioCoder
+{
+ constructor(wasm, importObj)
+ {
+ super(wasm, importObj);
+ this._indexDe = Adpcm._currentIndex;
+ this._indexEn = Adpcm._currentIndex + 1;
+ Adpcm._currentIndex = (Adpcm._currentIndex + 2) & 0x3F;
+ this._wasm.instance.exports._initAdpcmState(this._indexDe);
+ this._wasm.instance.exports._initAdpcmState(this._indexEn);
+ }
+
+ resetDecodeState(state)
+ {
+ this._wasm.instance.exports._resetAdpcmState(this._indexDe, state.valprev, state.index);
+ }
+
+ resetEncodeState(state)
+ {
+ this._wasm.instance.exports._resetAdpcmState(this._indexEn, state.valprev, state.index);
+ }
+
+ getDecodeState()
+ {
+ this._wasm.instance.exports._getAdpcmState(this._indexDe, 10236, 10238);
+ return new Adpcm.State(this._memory[10236] + (this._memory[10237] << 8), this._memory[10238]);
+ }
+
+ getEncodeState()
+ {
+ this._wasm.instance.exports._getAdpcmState(this._indexEn, 10236, 10238);
+ return new Adpcm.State(this._memory[10236] + (this._memory[10237] << 8), this._memory[10238]);
+ }
+
+ decode(data)
+ {
+ this._copyToMemory(data);
+ this._wasm.instance.exports._decodeAdpcm(this._indexDe, 0, 10240, data.byteLength << 1);
+ return new Int16Array(this._memory.buffer, 10240, data.byteLength << 1);
+ }
+
+ encode(data)
+ {
+ this._copyToMemory(data);
+ this._wasm.instance.exports._encodeAdpcm(this._indexEn, 0, 10240, data.byteLength >>> 1);
+ return new Uint8Array(this._memory.buffer, 10240, data.byteLength >>> 2);
+ }
+}
+
+Adpcm._currentIndex = 0;
+
+Adpcm.State = class
+{
+ constructor(valprev, index)
+ {
+ this.valprev = valprev;
+ this.index = index;
+ }
+}
diff --git a/library/jy4340132-aaa/adpcm.wasm b/library/jy4340132-aaa/adpcm.wasm
new file mode 100644
index 00000000..6591605c
Binary files /dev/null and b/library/jy4340132-aaa/adpcm.wasm differ
diff --git a/library/jy4340132-aaa/pcm_player.js b/library/jy4340132-aaa/pcm_player.js
new file mode 100644
index 00000000..ebe152ed
--- /dev/null
+++ b/library/jy4340132-aaa/pcm_player.js
@@ -0,0 +1,80 @@
+
+class PCMPlayer
+{
+ constructor(channels, sampleRate)
+ {
+ this._samples = new Float32Array();
+ this._flushingTime = 200;
+ this._channels = channels;
+ this._sampleRate = sampleRate;
+ this._flush = this._flush.bind(this);
+ this._audioCtx = new (window.AudioContext || window.webkitAudioContext)();
+ this._gainNode = this._audioCtx.createGain();
+ this._gainNode.gain.value = 1;
+ this._gainNode.connect(this._audioCtx.destination);
+ this._startTime = this._audioCtx.currentTime;
+ this._interval = setInterval(this._flush, this._flushingTime);
+ }
+
+ setVolume(volume)
+ {
+ this._gainNode.gain.value = volume;
+ }
+
+ close()
+ {
+ if(this._interval)
+ {
+ clearInterval(this._interval);
+ }
+ this._audioCtx.close();
+ };
+
+ feed(data)
+ {
+ let tmp = new Float32Array(this._samples.length + data.length);
+ tmp.set(this._samples, 0);
+ tmp.set(data, this._samples.length);
+ this._samples = tmp;
+ };
+
+ _flush()
+ {
+ if(!this._channels || !this._sampleRate || !this._samples.length)
+ {
+ return;
+ }
+ let bufferSource = this._audioCtx.createBufferSource();
+ let length = this._samples.length / this._channels;
+ let audioBuffer = this._audioCtx.createBuffer(this._channels, length, this._sampleRate);
+ for (let channel = 0; channel != this._channels; ++channel)
+ {
+ let audioData = audioBuffer.getChannelData(channel);
+ let offset = channel;
+ let decrement = 50;
+ for (let i = 0; i != length; ++i)
+ {
+ audioData[i] = this._samples[offset];
+ if (i < 50)
+ {
+ audioData[i] = (audioData[i] * i) / 50;
+ }
+ if (i >= (length - 51))
+ {
+ audioData[i] = (audioData[i] * decrement--) / 50;
+ }
+ offset += this._channels;
+ }
+ }
+
+ if (this._startTime < this._audioCtx.currentTime)
+ {
+ this._startTime = this._audioCtx.currentTime;
+ }
+ bufferSource.buffer = audioBuffer;
+ bufferSource.connect(this._gainNode);
+ bufferSource.start(this._startTime);
+ this._startTime += audioBuffer.duration;
+ this._samples = new Float32Array();
+ }
+}
diff --git a/library/jy4340132-aaa/std.js b/library/jy4340132-aaa/std.js
new file mode 100644
index 00000000..1c1e3f23
--- /dev/null
+++ b/library/jy4340132-aaa/std.js
@@ -0,0 +1,171 @@
+
+class Std
+{
+ constructor()
+ {}
+
+ static memmem(data1, data1Offset, data2)
+ {
+ for (let i = 0; i <= data1.byteLength - data2.byteLength - data1Offset; ++i)
+ {
+ let j = 0;
+ for (; j != data2.byteLength; ++j)
+ {
+ if(data1[i + j + data1Offset] != data2[j])
+ {
+ break;
+ }
+ }
+ if(j >= data2.byteLength)
+ {
+ return i + data1Offset;
+ }
+ }
+ return -1;
+ }
+
+ static memcmp(data1, data1Offset, data2)
+ {
+ for(let i = 0; i != data2.byteLength; ++i)
+ {
+ if(data1[i + data1Offset] != data2[i])
+ {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ static memcpy(data1, data1Offset, data2, data2Begin, data2End)
+ {
+ data1.set(data2.subarray(data2Begin, data2End), data1Offset);
+ }
+
+ static milliSecondTime()
+ {
+ return new Date().getTime();
+ }
+
+ static shortToFloatData(input)
+ {
+ let inputSamples = input.length;
+ let output = new Float32Array(inputSamples);
+ for(let i = 0; i != inputSamples; ++i)
+ {
+ output[i] = input[i] / 32768;
+ }
+ return output;
+ }
+
+ static floatToShortData(input)
+ {
+ let inputSamples = input.length;
+ let output = new Int16Array(inputSamples);
+ for(let i = 0; i != inputSamples; ++i)
+ {
+ output[i] = input[i] * 32768;
+ }
+ return output;
+ }
+
+ static downsampleBuffer(buffer, rate, sampleRate)
+ {
+ if(rate == sampleRate)
+ {
+ return buffer;
+ }
+ else if(rate > sampleRate)
+ {
+ throw "rate > sampleRate error !!";
+ }
+ let sampleRateRatio = sampleRate / rate;
+ let newLength = Math.ceil(buffer.length / sampleRateRatio) & 0xFFFC;
+ let result = new Float32Array(newLength);
+ let offsetResult = 0;
+ let offsetBuffer = 0;
+ while (offsetResult != result.length)
+ {
+ let nextOffsetBuffer = offsetBuffer + sampleRateRatio;
+ let accum = 0;
+ let count = 0;
+ let currentOffset = Math.ceil(offsetBuffer);
+ let currentNextOffset = Math.ceil(nextOffsetBuffer);
+ for (let i = currentOffset; i != currentNextOffset && i != buffer.length; ++i)
+ {
+ accum += buffer[i];
+ ++count;
+ }
+ result[offsetResult] = accum / count;
+ ++offsetResult;
+ offsetBuffer = nextOffsetBuffer;
+ }
+ return result;
+ }
+}
+
+class Result
+{
+ constructor(data, type, time, errorCode, duration = 20)
+ {
+ this.data = data;
+ this.type = type;
+ this.time = time;
+ this.duration = duration;
+ this.errorCode = errorCode;
+ }
+
+ static makeErrorResult(errorCode)
+ {
+ return new Result(null, -1, -1, errorCode);
+ }
+}
+
+Result.ErrorCode = class
+{
+ constructor()
+ {}
+}
+
+Result.ErrorCode.SUCCESS = 0;
+Result.ErrorCode.PARAM_ERROR = 1000;
+Result.ErrorCode.PARAM_CHANGE = 2000;
+Result.ErrorCode.FAIL = 3000;
+Result.ErrorCode.NO_INIT_ERROR = Result.ErrorCode.FAIL + 1;
+Result.ErrorCode.CACHE_MAX_ERROR = Result.ErrorCode.FAIL + 2;
+
+Result.Type = class
+{
+ constructor()
+ {}
+}
+
+Result.Type.H264_I_FRAME = 0;
+Result.Type.H264_P_FRAME = 1;
+Result.Type.H264_B_FRAME = 2;
+Result.Type.AUDIO = 3;
+Result.Type.TRANS_DATA = 4;
+Result.Type.FMP4_HEAD = 5;
+Result.Type.FMP4_BODY = 6;
+
+class AudioCoder
+{
+ constructor(wasm, importObj)
+ {
+ if(importObj.memoryBase < 102400)
+ {
+ throw new Error("too small");
+ }
+ this._importObj = importObj;
+ this._wasm = wasm;
+ this._memory = new Uint8Array(this._importObj.env.memory.buffer);
+ }
+
+ _copyToMemory(data)
+ {
+ if(data.byteLength > (this._importObj.env.memoryBase >>> 6))
+ {
+ throw new Error("overflow");
+ }
+ this._memory.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
+ }
+}
diff --git a/multi.html b/multi.html
index 22b2fc98..f42d8f95 100644
--- a/multi.html
+++ b/multi.html
@@ -14,6 +14,11 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+