Last active
December 14, 2015 03:38
-
-
Save bklimt/5022117 to your computer and use it in GitHub Desktop.
WaveWriter for JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Creates a helper to write a WAVE file to a Buffer. | |
* @param {Number} seconds - The length of the WAVE file to write. | |
* @param {Number} sampleRate - The sample rate in Hz, such as 44100 for a CD. | |
* @param {Number} bitsPerSample - Either 8 or 16. | |
*/ | |
var WaveWriter = function(seconds, sampleRate, bitsPerSample) { | |
this._sampleRate = sampleRate; | |
this._bitsPerSample = bitsPerSample; | |
this._writer = new BufferWriter(); | |
this._samples = Math.round(this._sampleRate * seconds); | |
var numChannels = 1; | |
var subChunk2Size = this._samples * numChannels * bitsPerSample / 8; | |
var chunkSize = 36 + subChunk2Size; | |
try { | |
this._writer.writeUTF8("RIFF"); | |
this._writer.writeUInt32LE(chunkSize); | |
this._writer.writeUTF8("WAVE"); | |
} catch (e1) { | |
console.error("Got an exception while writing WAVE header."); | |
throw e1; | |
} | |
try { | |
// Sub-chunk 1 | |
var byteRate = 36 + sampleRate * numChannels * bitsPerSample / 8; | |
var blockAlign = numChannels * bitsPerSample / 8; | |
this._writer.writeUTF8("fmt "); | |
this._writer.writeUInt32LE(16); | |
this._writer.writeUInt16LE(1); | |
this._writer.writeUInt16LE(numChannels); | |
this._writer.writeUInt32LE(sampleRate); | |
this._writer.writeUInt32LE(byteRate); | |
this._writer.writeUInt16LE(blockAlign); | |
this._writer.writeUInt16LE(bitsPerSample); | |
} catch (e2) { | |
console.error("Got an exception while writing subchunk 1."); | |
throw e2; | |
} | |
try { | |
// Sub-chunk 2 | |
this._writer.writeUTF8("data"); | |
this._writer.writeUInt32LE(subChunk2Size); | |
} catch (e3) { | |
console.error("Got an exception while writing subchunk 2."); | |
throw e3; | |
} | |
}; | |
_.extend(WaveWriter.prototype, { | |
/** | |
* Write a single sample to the WAVE file. | |
* @param {Number} sample The amplitude of the sample, from -1 to 1. | |
* @return {Boolean} false if the file is already full, true otherwise. | |
*/ | |
writeSample: function(sample) { | |
if (this._samples === 0) { | |
return false; | |
} | |
// Clamp values out of range. | |
if (sample < -1.0) { | |
sample = -1; | |
} | |
if (sample > 1.0) { | |
sample = 1; | |
} | |
if (this._bitsPerSample === 16) { | |
this._writer.writeInt16(Math.floor(32767 * sample)); | |
} else if (this._bitsPerSample === 8) { | |
try { | |
this._writer.writeUInt8(Math.floor(-127.5 * sample + 127.5)); | |
} catch (e) { | |
console.error("Got an exception while writing a sample."); | |
console.error("Sample is " + Math.floor(-127.5 * sample + 127.5)); | |
throw e; | |
} | |
} | |
this._samples = this._samples - 1; | |
return true; | |
}, | |
/** | |
* Fills the rest of the file with zero-amplitude samples. | |
*/ | |
close: function() { | |
while (this._samples > 0) { | |
this.writeSample(0.0); | |
} | |
}, | |
/** | |
* Returns the underlying buffer with the contents of the WAVE file. | |
*/ | |
buffer: function() { | |
return this._writer.buffer(); | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment