How to Record From A Microphone
<script type="text/javascript">
//Make multi browser compatible
navigator.getUserMedia=(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
window.AudioContext=(window.webkitAudioContext || window.AudioContext || window.mozAudioContext);
// Global Variables for Audio
var gRecording=false,gSourceNode,gAudioContext,gJavascriptNode,gAudioStream,gSampleSize=4096; // number of samples to collect before analyzing
var BufferL,BufferR,gSampleRate;
function InitMic() {
gAudioContext = new AudioContext();
navigator.getUserMedia({video:false,audio:true},SetupAudioNodes,function(e) {alert("Sorry, a problem has occurred trying to connect to your microphone:\n\n(Error: "+e+")");});
}
function Start() {//Finish setting up the audio nodes, and start processing audio streaming in from the input device
BufferL=new Float32Array(0); BufferR=new Float32Array(0); gRecording=true;
}
function SetupAudioNodes(Stream) {
gSourceNode=gAudioContext.createMediaStreamSource(Stream); //create the media stream from the audio input source (microphone)
gAudioStream=Stream; //Set global in order to stop later
gSampleRate=gAudioContext.sampleRate;
if (gAudioContext.createScriptProcessor) {
gJavascriptNode=gAudioContext.createScriptProcessor(gSampleSize,2,2);
} else {
gJavascriptNode=gAudioContext.createJavaScriptNode(gSampleSize,2,2);
}
gJavascriptNode.onaudioprocess=function(e){
if (gRecording) {
BufferL=ConcatFloat32Arrays(BufferL,e.inputBuffer.getChannelData(0));
BufferR=ConcatFloat32Arrays(BufferR,e.inputBuffer.getChannelData(1));
}
}
gSourceNode.connect(gJavascriptNode); gJavascriptNode.connect(gAudioContext.destination);
}
function Stop(f) {// Stop the audio processing, note time is BufferL.length/gSampleRate
var m,c,l,i,j,b,u,flag,start,stop,combined;
gRecording=false;
//Note: dB=20*log10(factor) and factor=10^(dB/20)
m=0; //max value
for (i=0;i<BufferL.length;i++) {if (BufferL[i]>m) {m=BufferL[i];}}
for (i=0;i<BufferR.length;i++) {if (BufferR[i]>m) {m=BufferR[i];}}
m=1/m; //Factor to multiply by so that max is 1
for (i=0;i<BufferL.length;i++) {BufferL[i]*=m;}
for (i=0;i<BufferR.length;i++) {BufferR[i]*=m;}
l=BufferL.length;
//Find start time, i.e. look for first non-silence then see whether 0.2 seconds ahead has 0.5 seconds of silence and jump to it if so
start=0; flag=true;
while (flag) {
if (start<l) {
if (IsWAVZero(BufferL[start]) && IsWAVZero(BufferR[start])) {
start++;
} else {
j=start+Math.round(0.2*gSampleRate);
c=0;
for (j=start+Math.round(0.2*gSampleRate);j<Math.min(l,start+Math.round(0.7*gSampleRate));j++) {
if (!(IsWAVZero(BufferL[j]) && IsWAVZero(BufferR[j]))) {c++;}
}
if (c==0) {
start=Math.min(l,start+Math.round(0.7*gSampleRate));
} else {
flag=false;
}
}
} else {
flag=false; //i.e. stop
}
}
start-=0.1*gSampleRate; if (start<0) {start=0;}
//Find stop time, i.e. look from end for first non-silence then see whether 0.2 seconds before has 0.5 seconds of silence before and jump back if so
stop=l; flag=true;
while (flag) {
if (stop>=0) {
if (IsWAVZero(BufferL[stop]) && IsWAVZero(BufferR[stop])) {
stop--;
} else {
j=stop-Math.round(0.2*gSampleRate);
c=0;
for (j=stop-Math.round(0.2*gSampleRate);j>Math.max(0,stop-Math.round(0.7*gSampleRate));j--) {
if (!(IsWAVZero(BufferL[j]) && IsWAVZero(BufferR[j]))) {c++;}
}
if (c==0) {
stop=Math.max(0,stop-Math.round(0.7*gSampleRate));
} else {
flag=false;
}
}
} else {
flag=false; //i.e. stop
}
}
stop+=0.1*gSampleRate; if (stop>l) {stop=l;}
//Fill buffer
if (stop<start) {stop=start;}
l=2*(stop-start);
combined=new Float32Array(l);
i=0; j=0; while (i<l){combined[i++]=BufferL[start+j]; combined[i++]=BufferR[start+j]; j++;}
b=new Blob([EncodeWAV(combined)], {type:'audio/wav'});
UploadAudio(b,f);
u=(window.URL || window.webkitURL).createObjectURL(b);
l=document.getElementById("Save");
l.href=u;
l.download="New.wav";//Works in Chrome, in others default name is used
}
function IsWAVZero(i) {return (Math.abs(i)<0.05);} //About -26 dB
function ConcatFloat32Arrays(a1,a2) {var ans=new Float32Array(a1.length+a2.length); ans.set(a1,0); ans.set(a2,a1.length); return ans;}
function FloatTo16BitPCM(output, offset, input){
var i,s;
for (i=0;i<input.length;i++,offset+=2){
s=Math.max(-1,Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
}
function EncodeWAV(samples){
var buffer = new ArrayBuffer(44+samples.length*2);
var view = new DataView(buffer);
WriteString(view, 0, 'RIFF'); // RIFF identifier zz
view.setUint32(4, 32 + samples.length * 2, true); // file length
WriteString(view, 8, 'WAVE'); // RIFF type
WriteString(view, 12, 'fmt '); // format chunk identifier
view.setUint32(16, 16, true); // format chunk length
view.setUint16(20, 1, true); // sample format (raw)
view.setUint16(22, 2, true); // channel count
view.setUint32(24, gSampleRate, true); // sample rate
view.setUint32(28, gSampleRate * 4, true); // byte rate (sample rate * block align)
view.setUint16(32, 4, true); // block align (channel count * bytes per sample)
view.setUint16(34, 16, true); // bits per sample
WriteString(view, 36, 'data'); // data chunk identifier
view.setUint32(40, samples.length * 2, true); // data chunk length
FloatTo16BitPCM(view, 44, samples);
return view;
}
function WriteString(view, offset, string){var i; for (i=0;i<string.length;i++){view.setUint8(offset+i,string.charCodeAt(i));}}
function GetXMLHttpRequest() {try {return new XMLHttpRequest();} catch(e) {return new ActiveXObject("Microsoft.XMLHTTP");}}
function GetNewFormData() {if(typeof FormData == "undefined"){return [];} return new FormData();} //Needed for IE9
function AppendToFormData(fd, s, t) {if(typeof FormData=="undefined") {fd.push(s,t);} else {fd.append(s,t);} return fd;}
function UploadAudio(blob,f) {
var s,req=GetXMLHttpRequest();
//var Page,TargetLang,Voice;
//TargetLang=GetVars()["TargetLang"];
//Page=GetVars()["Page"];
//Voice="Default";
req.onload=function(e) {}; // readyState=4 means done
var fd=GetNewFormData();
fd=AppendToFormData(fd,"action","upload");
fd=AppendToFormData(fd,"filetype","audio");
//if (Page=="TestRecording") {s="Data/TestRecording.mp3";} else {s="Data/"+TargetLang+"/"+Voice+"/"+GetFileName()+".mp3";}
s="TestRecording.mp3";
fd=AppendToFormData(fd,"filename",s);
fd=AppendToFormData(fd,"tempfile",blob);
req.onreadystatechange = function() {
if (req.readyState == 4) {
s=req.responseText;
if (document.getElementById("FBAudioMessage")) {
if (IsEmpty(s)) {
ShowRecordPage();
} else {
document.getElementById("FBAudioMessage").innerHTML="Error uploading audio: "+s+"<br /><br />";
}
} else {
if (s!="") {alert(s);}
}
}
}
req.open("POST","Fraze.php",true); //Note: POST has no restriction on length
req.send(fd);
if (document.getElementById("FBAudioMessage")) {
document.getElementById("FBAudioMessage").innerHTML="[Uploading audio...]<br /><br />";
document.getElementById("FBPlay").className="off";
document.getElementById("FBRecord").className="off";
document.getElementById("FBStop").className="off";
}
}
//Play file
function Play(s) {var au=new Audio(s+".mp3?n="+Math.random()); au.play();} //Adding .random refreshes file, i.e. doesn't use cache
</script>
</head>
<body onload='InitMic();'>
<input type="button" id="start_button" value="Start" onclick="Start();">
<input type="button" id="stop_button" value="Stop" onclick="Stop('TestRecording');">
<input type="button" id="play_button" value="Play" onclick="Play('TestRecording');">
<a id="Save" href="#">Click</a>
<br />