Chromium Code Reviews| Index: ppapi/examples/audio_encode/audio_encode.html |
| diff --git a/ppapi/examples/audio_encode/audio_encode.html b/ppapi/examples/audio_encode/audio_encode.html |
| index 36b322a54d1e8d236a68a4d86867a3bd94a477c0..b7ae85076b3ab70f4babc0f13c5faacf5708f650 100644 |
| --- a/ppapi/examples/audio_encode/audio_encode.html |
| +++ b/ppapi/examples/audio_encode/audio_encode.html |
| @@ -14,71 +14,126 @@ |
| var profiles; |
| function writeString(array, offset, string) { |
| - var out = new Uint8Array(array); |
| for (var i = 0; i < string.length; i++) |
| - out.set([string.charCodeAt(i)], i + offset); |
| + array.set([string.charCodeAt(i)], i + offset); |
| return string.length; |
| } |
| function writeValue(array, bytes, offset, value) { |
| - var out = new Uint8Array(array); |
| for (var i = 0; i < bytes; i++) |
| - out.set([((value >>> (i * 8)) & 0xff)], offset + i); |
| + array.set([((value >>> (i * 8)) & 0xff)], offset + i); |
| return bytes; |
| } |
| + |
| + var BufferArray = function() { |
| + this._arrays = [ this._createBuffer() ]; |
| + }; |
| + BufferArray.prototype = { |
| + _createBuffer: function() { |
| + var buffer = new Uint8Array(100 * 1024); |
| + buffer.dataLength = 0; |
| + return buffer; |
| + }, |
| + appendData: function(data) { |
| + var currentBuffer = this._arrays[this._arrays.length - 1]; |
| + if (currentBuffer.byteLength < (currentBuffer.dataLength + data.byteLength)) { |
| + this._arrays.push(this._createBuffer()); |
| + currentBuffer = this._arrays[this._arrays.length - 1]; |
| + } |
| + currentBuffer.set(new Uint8Array(data), currentBuffer.dataLength); |
| + currentBuffer.dataLength += data.byteLength; |
| + }, |
| + getByte: function(offset) { |
| + var bufferOffset = 0; |
| + for (var i = 0; i < this._arrays.length; i++) { |
| + var buffer = this._arrays[i]; |
| + if (offset < (bufferOffset + buffer.dataLength)) { |
| + return buffer[offset - bufferOffset]; |
| + } |
| + bufferOffset += buffer.dataLength; |
| + } |
| + throw new Error('Out of range access'); |
| + }, |
| + getSize: function() { |
| + var size = 0; |
| + for (var i = 0; i < this._arrays.length; i++) |
| + size += this._arrays[i].dataLength; |
| + return size; |
| + }, |
| + writeValue: function(bytes, offset, value) { |
| + var bufferOffset = 0; |
| + for (var i = 0; i < this._arrays.length; i++) { |
| + var buffer = this._arrays[i]; |
| + if (offset < (bufferOffset + buffer.dataLength)) { |
| + writeValue(buffer, bytes, offset - bufferOffset, value); |
| + return; |
| + } |
| + bufferOffset += buffer.dataLength; |
| + } |
| + throw new Error('Out of range access'); |
| + }, |
| + toBlob: function() { |
| + var result = new Uint8Array(this.getSize()); |
| + var offset = 0; |
| + for (var i = 0; i < this._arrays.length; i++) { |
| + var buffer = this._arrays[i]; |
| + result.set(buffer.subarray(0, buffer.dataLength), offset); |
| + offset += buffer.dataLength; |
| + } |
| + return new Blob([result]); |
| + }, |
| + }; |
| + |
| // Writes way data. |
|
bbudge
2016/01/20 19:13:09
s/way/wav ?
|
| var WavWriter = function() { |
| this.chunkSizeOffset = 0; |
| - this.arrayBuffer = new ArrayBuffer(); |
| + this.buffer = new BufferArray(); |
| }; |
| WavWriter.prototype = { |
| writeHeader: function(format) { |
| - this.arrayBuffer = |
| - new ArrayBuffer(4 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2 + 4 + 4); |
| + var buffer = |
| + new Uint8Array(4 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2 + 4 + 4); |
| var i = 0; |
| // File header |
| - i += writeString(this.arrayBuffer, i, 'RIFF'); |
| + i += writeString(buffer, i, 'RIFF'); |
| i += 4; // Gap for final size. |
| - i += writeString(this.arrayBuffer, i, 'WAVE'); |
| + i += writeString(buffer, i, 'WAVE'); |
| // Chunk ID. |
| - i += writeString(this.arrayBuffer, i, 'fmt '); |
| + i += writeString(buffer, i, 'fmt '); |
| // Chunk length. |
| - i += writeValue(this.arrayBuffer, 4, i, 16); |
| + i += writeValue(buffer, 4, i, 16); |
| // Codec (uncompressed LPCM). |
| - i += writeValue(this.arrayBuffer, 2, i, 1); |
| + i += writeValue(buffer, 2, i, 1); |
| // Number of channels. |
| - i += writeValue(this.arrayBuffer, 2, i, format.channels); |
| + i += writeValue(buffer, 2, i, format.channels); |
| // Sample rate. |
| - i += writeValue(this.arrayBuffer, 4, i, format.sample_rate); |
| + i += writeValue(buffer, 4, i, format.sample_rate); |
| // Average bytes per seconds (sample rate * bytes per sample) |
| - i += writeValue(this.arrayBuffer, 4, i, |
| + i += writeValue(buffer, 4, i, |
| format.sample_rate * format.sample_size); |
| // Bytes per sample. |
| - i += writeValue(this.arrayBuffer, 2, i, |
| + i += writeValue(buffer, 2, i, |
| format.sample_size * format.channels); |
| // Bits per sample. |
| - i += writeValue(this.arrayBuffer, 2, i, format.sample_size * 8); |
| + i += writeValue(buffer, 2, i, format.sample_size * 8); |
| // Data chunk |
| - i += writeString(this.arrayBuffer, i, 'data'); |
| + i += writeString(buffer, i, 'data'); |
| this.chunkSizeOffset = i; // Location of the chunk's size |
| + this.buffer.appendData(buffer); |
| }, |
| writeData: function(data) { |
| - var tmp = new Uint8Array(this.arrayBuffer.byteLength + data.byteLength); |
| - tmp.set(new Uint8Array(this.arrayBuffer), 0); |
| - tmp.set(new Uint8Array(data), this.arrayBuffer.byteLength); |
| - this.arrayBuffer = tmp.buffer; |
| + this.buffer.appendData(data); |
| }, |
| end: function() { |
| - var out = new Uint32Array(this.arrayBuffer); |
| - out.set([this.arrayBuffer.byteLength - 8], 1); |
| - out.set([this.arrayBuffer.byteLength - this.chunkSizeOffset], |
| - this.chunkSizeOffset / 4); |
| + this.buffer.writeValue(4, 4, this.buffer.getSize() - 8); |
| + this.buffer.writeValue(4, this.chunkSizeOffset, |
| + this.buffer.getSize() - this.chunkSizeOffset); |
| }, |
| getSize: function() { |
| - return this.arrayBuffer.byteLength; |
| + return this.buffer.getSize(); |
| }, |
| getData: function() { |
| - return this.arrayBuffer; |
| + return this.buffer; |
| }, |
| getExtension: function() { |
| return 'wav'; |
| @@ -88,7 +143,7 @@ |
| // Writes ogg data. |
| var OggWriter = function(profile) { |
| this.writeHeader = this._writeOpusHeader; |
| - this.arrayBuffer = new ArrayBuffer(); |
| + this.buffer = new BufferArray(); |
| this.pageSequence = 0; |
| this.bitstreamNumber = 0; |
| this.position = 0; |
| @@ -98,12 +153,6 @@ |
| _Start: 0x2, |
| _Continue: 0x1, |
| _Stop: 0x4, |
| - _append: function(data) { |
| - var tmp = new Uint8Array(this.arrayBuffer.byteLength + data.byteLength); |
| - tmp.set(new Uint8Array(this.arrayBuffer), 0); |
| - tmp.set(new Uint8Array(data), this.arrayBuffer.byteLength); |
| - this.arrayBuffer = tmp.buffer; |
| - }, |
| _makeCRCTable: function() { |
| var crcTable = []; |
| for (var n = 0; n < 256; n++) { |
| @@ -120,15 +169,14 @@ |
| }, |
| _crc32: function(data, start, end) { |
| var crc = 0; |
| - var u8data = new Uint8Array(data) |
| var crcTable = this._crcTable || (this._crcTable = this._makeCRCTable()); |
| for (var i = start; i < end; i++) |
| - crc = (crc << 8) ^ crcTable[((crc >> 24) & 0xff) ^ u8data[i]]; |
| + crc = (crc << 8) ^ crcTable[((crc >> 24) & 0xff) ^ data.getByte(i)]; |
| return crc; |
| }, |
| _writePage: function(flag, size, position) { |
| var pages = 1 + Math.floor(size / 255); |
| - var buffer = new ArrayBuffer(27 + pages), i = 0; |
| + var buffer = new Uint8Array(27 + pages), i = 0; |
| // capture_pattern. |
| i += writeString(buffer, i, 'OggS'); |
| // stream_structure_version. |
| @@ -154,17 +202,17 @@ |
| i += writeValue(buffer, 1, i, 255); |
| i += writeValue(buffer, 1, i, size % 255); |
| - this._append(buffer); |
| + this.buffer.appendData(buffer); |
| }, |
| _writePageChecksum: function(pageOffset) { |
| - var crc = this._crc32(this.arrayBuffer, pageOffset, |
| - this.arrayBuffer.byteLength); |
| - writeValue(this.arrayBuffer, 4, pageOffset + 22, crc); |
| + var crc = this._crc32(this.buffer, pageOffset, |
| + this.buffer.getSize()); |
| + this.buffer.writeValue(4, pageOffset + 22, crc); |
| }, |
| _writeOpusHeader: function(format) { |
| this.format = format; |
| - var start = this.getSize(); |
| - var buffer = new ArrayBuffer(8 + 1 + 1 + 2 + 4 + 2 + 1), i = 0; |
| + var start = this.buffer.getSize(); |
| + var buffer = new Uint8Array(8 + 1 + 1 + 2 + 4 + 2 + 1), i = 0; |
| // Opus header. |
| i += writeString(buffer, i, 'OpusHead'); |
| // version. |
| @@ -181,13 +229,13 @@ |
| i += writeValue(buffer, 1, i, 0); |
| this._writePage(this._Start, buffer.byteLength); |
| - this._append(buffer); |
| + this.buffer.appendData(buffer); |
| this._writePageChecksum(start); |
| this._writeCommentHeader('OpusTags'); |
| }, |
| _writeCommentHeader: function(name) { |
| - var start = this.getSize(); |
| - var buffer = new ArrayBuffer(8 + 4 + 8 + 4 + 4 + 13), i = 0; |
| + var start = this.buffer.getSize(); |
| + var buffer = new Uint8Array(8 + 4 + 8 + 4 + 4 + 13), i = 0; |
| // Opus comment header. |
| i += writeString(buffer, i, name); |
| // Vendor string. |
| @@ -198,7 +246,7 @@ |
| i += this._writeLengthString(buffer, i, 'TITLE=example'); |
| this._writePage(this._Continue, buffer.byteLength); |
| - this._append(buffer); |
| + this.buffer.appendData(buffer); |
| this._writePageChecksum(start); |
| }, |
| _writeLengthString: function(buffer, offset, str) { |
| @@ -207,20 +255,17 @@ |
| }, |
| writeData: function(data) { |
| this.position += this.format.sample_per_frame / this.format.channels; |
| - var start = this.getSize(); |
| + var start = this.buffer.getSize(); |
| this._writePage(0, data.byteLength, this.position); |
| - this._append(data); |
| + this.buffer.appendData(data); |
| this._writePageChecksum(start); |
| this.dataWritten = true; |
| }, |
| end: function() { |
| this._writePage(this._Stop, 0); |
| }, |
| - getSize: function() { |
| - return this.arrayBuffer.byteLength; |
| - }, |
| getData: function() { |
| - return this.arrayBuffer; |
| + return this.buffer; |
| }, |
| getExtension: function() { |
| return 'ogg'; |
| @@ -255,9 +300,8 @@ |
| download.parentNode.removeChild(download); |
| } |
| - function setDownload(data, filename) { |
| + function setDownload(blob, filename) { |
| var mimeType = 'application/octet-stream'; |
| - var blob = new Blob([data], { type: mimeType }); |
| var a = document.createElement('a'); |
| a.id = "download"; |
| a.download = filename; |
| @@ -297,12 +341,8 @@ |
| }); |
| track.stop(); |
| writer.end(); |
| - setDownload(writer.getData(), 'Capture.' + writer.getExtension()); |
| - } |
| - |
| - function saveBlob(blob) { |
| - var blobUrl = URL.createObjectURL(blob); |
| - window.location = blobUrl; |
| + setDownload(writer.getData().toBlob(), |
| + 'Capture.' + writer.getExtension()); |
| } |
| function handleMessage(msg) { |
| @@ -312,10 +352,10 @@ |
| console.error(msg.data.message); |
| } else if (msg.data.command == 'data') { |
| writer.writeData(msg.data.buffer); |
| - $('length').textContent = ' Size: ' + writer.getSize() + ' bytes'; |
| + $('length').textContent = ' Size: ' + writer.getData().getSize() + ' bytes'; |
| } else if (msg.data.command == 'format') { |
| writer.writeHeader(msg.data); |
| - $('length').textContent = ' Size: ' + writer.getSize() + ' bytes'; |
| + $('length').textContent = ' Size: ' + writer.getData().getSize() + ' bytes'; |
| } else if (msg.data.command == 'supportedProfiles') { |
| profiles = []; |
| var profileList = $('profileList'); |
| @@ -342,7 +382,7 @@ |
| function resetData() { |
| writer = new WavWriter(); |
| - $('length').textContent = ' Size: ' + writer.getSize() + ' bytes'; |
| + $('length').textContent = ' Size: ' + writer.getData().getSize() + ' bytes'; |
| } |
| function initialize() { |