├── LICENSE.txt ├── README.md ├── Rakefile └── lib ├── WavAudioEncoder.js └── WavAudioEncoder.min.js /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yuji Miyane 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WavAudioEncoder.js 2 | 3 | ## What is it? 4 | 5 | WavAudioEncoder.js is a small JavaScript library that encodes audio data to Waveform Audio (.wav) on web browsers. 6 | 7 | ### Acknowledgement 8 | 9 | Basic idea is taken from Recorderjs (). API has been totally re-designed and simplified. Now it has been a lower layer part of [WebAudioRecorder.js](https://github.com/higuma/web-audio-recorder-js). 10 | 11 | ## Demo 12 | 13 | 14 | 15 | ## Library files 16 | 17 | `lib/` contains library files. 18 | 19 | * `WavAudioEncoder.js`: JavaScript library (uncompressed) 20 | * `WavAudioEncoder.min.js`: JavaScript library (minified) 21 | 22 | ### Using library 23 | 24 | You can use it from both HTML and Web Worker. 25 | 26 | * from HTML: `` 27 | * from Worker: `importScripts("javascripts/WavAudioEncoder.js");` 28 | 29 | ## API 30 | 31 | ``` javascript 32 | encoder = new WavAudioEncoder(sampleRate, numChannels) 33 | ``` 34 | 35 | Create an encoder object. 36 | 37 | * Parameters 38 | * `samleRate`: sampling rate [Hz] 39 | * `numChannels`: number of audio channels 40 | * Returns 41 | * encoder object 42 | 43 | > In current implementation, bit width is fixed to 16 (2 bytes). 44 | 45 | ``` javascript 46 | encoder.encode(buffers) 47 | ``` 48 | 49 | Encode audio buffers. 50 | 51 | * Parameters 52 | * `buffers`: array of sample buffers (`[Float32Array, Float32Array ...]`) 53 | * Returns 54 | * (none) 55 | 56 | `buffers` must be an array of Float32Array audio data (range = [-1, 1]). Array length must be same as number of channels. It supports stream (incremental) processing. Sample buffers are processed to .wav fragment and appended to internal data. 57 | 58 | ``` javascript 59 | blob = encoder.finish([mimeType]) 60 | ``` 61 | 62 | Finish encoding and get Waveform Audio as a Blob. 63 | 64 | * Parameters 65 | * `mimeType`(optional): MIME type (default = `"audio/wav"`) 66 | * Returns 67 | * Blob object 68 | 69 | After calling `.finish()`, all internal data is cleared. You must create a new encoder object to encode another audio data. 70 | 71 | ``` javascript 72 | encoder.cancel() 73 | ``` 74 | 75 | * Parameters 76 | * (none) 77 | * Returns 78 | * (none) 79 | 80 | Cancel encoding and clear all internal data. 81 | 82 | ## License 83 | 84 | MIT (see [LICENSE.txt](LICENSE.txt)). 85 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | task :build_minified do 2 | sh 'uglifyjs -m sort lib/WavAudioEncoder.js > lib/WavAudioEncoder.min.js' 3 | end 4 | 5 | task :clean do 6 | sh 'rm -rf lib/WavAudioEncoder.min.js' 7 | end 8 | 9 | task default: :build_minified 10 | 11 | __END__ 12 | 13 | task copy_files: :build_minified do 14 | sh 'cp lib/* ../WebAudioRecorder.demo/src/js' 15 | sh 'cp lib-minified/* ../WebAudioRecorder.demo/public/js' 16 | end 17 | 18 | -------------------------------------------------------------------------------- /lib/WavAudioEncoder.js: -------------------------------------------------------------------------------- 1 | (function(self) { 2 | var min = Math.min, 3 | max = Math.max; 4 | 5 | var setString = function(view, offset, str) { 6 | var len = str.length; 7 | for (var i = 0; i < len; ++i) 8 | view.setUint8(offset + i, str.charCodeAt(i)); 9 | }; 10 | 11 | var Encoder = function(sampleRate, numChannels) { 12 | this.sampleRate = sampleRate; 13 | this.numChannels = numChannels; 14 | this.numSamples = 0; 15 | this.dataViews = []; 16 | }; 17 | 18 | Encoder.prototype.encode = function(buffer) { 19 | var len = buffer[0].length, 20 | nCh = this.numChannels, 21 | view = new DataView(new ArrayBuffer(len * nCh * 2)), 22 | offset = 0; 23 | for (var i = 0; i < len; ++i) 24 | for (var ch = 0; ch < nCh; ++ch) { 25 | var x = buffer[ch][i] * 0x7fff; 26 | view.setInt16(offset, x < 0 ? max(x, -0x8000) : min(x, 0x7fff), true); 27 | offset += 2; 28 | } 29 | this.dataViews.push(view); 30 | this.numSamples += len; 31 | }; 32 | 33 | Encoder.prototype.finish = function(mimeType) { 34 | var dataSize = this.numChannels * this.numSamples * 2, 35 | view = new DataView(new ArrayBuffer(44)); 36 | setString(view, 0, 'RIFF'); 37 | view.setUint32(4, 36 + dataSize, true); 38 | setString(view, 8, 'WAVE'); 39 | setString(view, 12, 'fmt '); 40 | view.setUint32(16, 16, true); 41 | view.setUint16(20, 1, true); 42 | view.setUint16(22, this.numChannels, true); 43 | view.setUint32(24, this.sampleRate, true); 44 | view.setUint32(28, this.sampleRate * 4, true); 45 | view.setUint16(32, this.numChannels * 2, true); 46 | view.setUint16(34, 16, true); 47 | setString(view, 36, 'data'); 48 | view.setUint32(40, dataSize, true); 49 | this.dataViews.unshift(view); 50 | var blob = new Blob(this.dataViews, { type: 'audio/wav' }); 51 | this.cleanup(); 52 | return blob; 53 | }; 54 | 55 | Encoder.prototype.cancel = Encoder.prototype.cleanup = function() { 56 | delete this.dataViews; 57 | }; 58 | 59 | self.WavAudioEncoder = Encoder; 60 | })(self); 61 | -------------------------------------------------------------------------------- /lib/WavAudioEncoder.min.js: -------------------------------------------------------------------------------- 1 | (function(n){var a=Math.min,s=Math.max;var e=function(n,a,e){var s=e.length;for(var t=0;t