| 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..14cab7b3a2f8d8553532fe2736c74e8dd02f1e6e 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;
|
| }
|
| - // Writes way data.
|
| +
|
| + 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 wav data.
|
| 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() {
|
|
|