Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@asanoboy
Created October 30, 2012 11:39
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save asanoboy/3979747 to your computer and use it in GitHub Desktop.
Save asanoboy/3979747 to your computer and use it in GitHub Desktop.
How to make a WAV file in Javascript.
var Wav = function(opt_params){
/**
* @private
*/
this._sampleRate = opt_params && opt_params.sampleRate ? opt_params.sampleRate : 44100;
/**
* @private
*/
this._channels = opt_params && opt_params.channels ? opt_params.channels : 2;
/**
* @private
*/
this._eof = true;
/**
* @private
*/
this._bufferNeedle = 0;
/**
* @private
*/
this._buffer;
};
Wav.prototype.setBuffer = function(buffer){
this._buffer = this.getWavInt16Array(buffer);
this._bufferNeedle = 0;
this._internalBuffer = '';
this._hasOutputHeader = false;
this._eof = false;
};
Wav.prototype.getBuffer = function(len){
var rt;
if( this._bufferNeedle + len >= this._buffer.length ){
rt = new Int16Array(this._buffer.length - this._bufferNeedle);
this._eof = true;
}
else {
rt = new Int16Array(len);
}
for(var i=0; i<rt.length; i++){
rt[i] = this._buffer[i+this._bufferNeedle];
}
this._bufferNeedle += rt.length;
return rt.buffer;
};
Wav.prototype.eof = function(){
return this._eof;
};
Wav.prototype.getWavInt16Array = function(buffer){
var intBuffer = new Int16Array(buffer.length + 23), tmp;
intBuffer[0] = 0x4952; // "RI"
intBuffer[1] = 0x4646; // "FF"
intBuffer[2] = (2*buffer.length + 15) & 0x0000ffff; // RIFF size
intBuffer[3] = ((2*buffer.length + 15) & 0xffff0000) >> 16; // RIFF size
intBuffer[4] = 0x4157; // "WA"
intBuffer[5] = 0x4556; // "VE"
intBuffer[6] = 0x6d66; // "fm"
intBuffer[7] = 0x2074; // "t "
intBuffer[8] = 0x0012; // fmt chunksize: 18
intBuffer[9] = 0x0000; //
intBuffer[10] = 0x0001; // format tag : 1
intBuffer[11] = this._channels; // channels: 2
intBuffer[12] = this._sampleRate & 0x0000ffff; // sample per sec
intBuffer[13] = (this._sampleRate & 0xffff0000) >> 16; // sample per sec
intBuffer[14] = (2*this._channels*this._sampleRate) & 0x0000ffff; // byte per sec
intBuffer[15] = ((2*this._channels*this._sampleRate) & 0xffff0000) >> 16; // byte per sec
intBuffer[16] = 0x0004; // block align
intBuffer[17] = 0x0010; // bit per sample
intBuffer[18] = 0x0000; // cb size
intBuffer[19] = 0x6164; // "da"
intBuffer[20] = 0x6174; // "ta"
intBuffer[21] = (2*buffer.length) & 0x0000ffff; // data size[byte]
intBuffer[22] = ((2*buffer.length) & 0xffff0000) >> 16; // data size[byte]
for (var i = 0; i < buffer.length; i++) {
tmp = buffer[i];
if (tmp >= 1) {
intBuffer[i+23] = (1 << 15) - 1;
}
else if (tmp <= -1) {
intBuffer[i+23] = -(1 << 15);
}
else {
intBuffer[i+23] = Math.round(tmp * (1 << 15));
}
}
return intBuffer;
};
var i=0, vol=0.1,
sampleRate = 48000,
wav = new Wav({sampleRate: sampleRate, channels: 1}),
buffer = new Float32Array(sampleRate);
while(i<sampleRate){
if( parseInt(i/100) % 2 ){
buffer[i] = -vol;
}
else {
buffer[i] = vol;
}
i++;
}
wav.setBuffer(buffer);
var srclist = [];
while( !wav.eof() ){
srclist.push(wav.getBuffer(1000));
}
var b = new Blob(srclist, {type:'audio/wav'});
var URLObject = window.webkitURL || window.URL;
var url = URLObject.createObjectURL(b);
document.write("<a href='"+url+"'>play</a>");
@0x07dc
Copy link

0x07dc commented Jun 8, 2014

This doesn't run for me. The URL it links is blob:null/17c31a0b-bec9-4f56-be46-98f8b7e8058a or something similar and it shows a screen that is unable to play the sound. I'm thinking it's supposed to be a square wave?

@shunzh
Copy link

shunzh commented Jun 25, 2014

There will be problem with URLObject if it runs on the client. I'm finding a workaround.

@NikonorovNikita
Copy link

nice work ^_^
can i use some part of you code on my diploma in university?

@ltbringer
Copy link

In wav.getBuffer(1000) what is the use of 1000 ? I have tried changing its value, I see no difference.

@JohnWeisz
Copy link

JohnWeisz commented Jul 15, 2018

Anyone has an idea how we would go about writing an INFO chunk with LIST sub-chunks containing song metadata? (e.g. artist name, track number, etc.)

@juniusmu
Copy link

@JohnWeisz have you found a way to do that yet? I'm trying to do the same thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment