2014-06-05 19 views
2

我正在使用Web Audio API創建基於Recorderjs的網絡音頻錄製器。目前,我的刻錄機似乎在Firefox上運行得非常好。我遇到的問題是在Chrome上,我的程序似乎錄製了音頻(或者至少錄製了正確的時間),但是當我嘗試播放錄製內容後,將它編碼爲WAV文件後,音頻似乎是錄音的最後一個聲音的連續循環,但仍會播放正確的時間量。網絡音頻API錄製可在Firefox中使用,但不適用於Chrome

任何幫助將不勝感激!

下面是相關代碼:

//toggle recording 
function recordButton() { 
//if not currently recording already 
if (recording === false) { 
    //if this is initial recording 
    if (!somethingRecorded) { 
     arrayPos.push(0);  //recLength at 0 sceonds is also 0 
    } 

    //check if dictation is being played 
    if (playing) { 
     //if it is, then first pause audio 
     dictation.pause(); 
     playing = false; 
    } 

    //if need to record over previous audio 
    if (timeBar.value < timeBar.max) { 
     console.log("In rewound block"); 

     seconds = Number(timeBar.value); //convert to number since timeBar.value is a string 

     //erase buffers after place where rewound to 
     var index = timeBar.value/0.1;  //calculate index in arrayPos that the value for the current time will be, since values are pushed into arrayPos every 0.1 seconds 
     for (var i = numBuffers; i > arrayPos[index]; i--) { 
      recLength -= recBuffersL[i - 1].length; 
      recBuffersL.pop(); 
      recBuffersR.pop(); 
      numBuffers--; 
     } 

    } 

    console.log("Start Record"); 
    recording = true; 
    timeBar.max = 300; 
    intervalID = setInterval(updateTime, 100); 
    somethingRecorded = true; 

    //disable buttons 
    disableButtons([0, 0, 1, 0, 0, 0]); 

} 
else { 
    console.log("Stop Record"); 
    recording = false; 
    clearInterval(intervalID); 
    timeBar.max = timeBar.value; 
    window.document.getElementById("maxtime").innerHTML = Math.floor(timeBar.max/60) + ":" + ("0" + Math.floor(timeBar.max % 60)).slice(-2); 

    //disable buttons and save audio 
    disableButtons([0, 0, 0, 1, 0, 0]); 
    saveAudio(); 
} 
} 

//save audio file 
function saveAudio(fileType) { 
fileType = fileType || 'audio/wav'; 

//flatten out the input channels 
var mergedL = new Float32Array(recLength); 
var mergedR = new Float32Array(recLength); 

offset = 0; 
for (var i = 0; i < recBuffersL.length; i++)  //both arrays should have same length 
{ 
    mergedL.set(recBuffersL[i], offset); 
    mergedR.set(recBuffersR[i], offset); 
    offset += recBuffersL[i].length; 
} 

//combine two channels of input into one single sample 
var combined = new Float32Array(mergedL.length + mergedR.length); 

for (var i = 0; i < mergedL.length + mergedR.length; i += 2) { 
    combined[i] = mergedL[i/2]; 
    combined[i + 1] = mergedR[i/2]; 
} 

console.log(combined); 
//encode sample into WAV format 
var dataview = encodeWAV(combined); 

//final binary blob, then call functions to set up playback and download 
var audioBlob = new Blob([dataview], { type: fileType }); 
var blobURL = (window.URL || window.webkitURL).createObjectURL(audioBlob); 

setUpPlayback(blobURL); 
// doneEncoding(audioBlob); 
} 

//helper function for writing strings into DataView 
function writeString(view, offset, string) { 
for (var i = 0; i < string.length; i++) { 
    view.setUint8(offset + i, string.charCodeAt(i)); 
} 
} 

//encode into WAV file 
function encodeWAV(audio) { 
//create buffer and view to create WAV file 
var buffer = new ArrayBuffer(44 + audio.length * 2); 
var view = new DataView(buffer); 

// RIFF identifier 
writeString(view, 0, 'RIFF'); 
// file length 
view.setUint32(4, 32 + audio.length * 2, true); 
// RIFF type 
writeString(view, 8, 'WAVE'); 
// format chunk identifier 
writeString(view, 12, 'fmt '); 
// format chunk length 
view.setUint32(16, 16, true); 
// sample format (raw) 
view.setUint16(20, 1, true); 
// channel count 
view.setUint16(22, 2, true); 
// sample rate 
view.setUint32(24, sampleRate, true); 
// byte rate (sample rate * block align) 
view.setUint32(28, sampleRate * 4, true); 
// block align (channel count * bytes per sample) 
view.setUint16(32, 4, true); 
// bits per sample 
view.setUint16(34, 16, true); 
// data chunk identifier 
writeString(view, 36, 'data'); 
// data chunk length 
view.setUint32(40, audio.length * 2, true); 

//write PCM samples 
var index = 44; 
for (var i = 0; i < audio.length; i++) { 
    view.setInt16(index, audio[i] * (0x7FFF), true); 
    index += 2; 
} 

return view; 
} 

回答

1

以防萬一有人有同樣的問題,我想它了。問題實際上是在inaudioprocess函數中。由於getChannelData實際上返回一個指針而不是實際的數組,因此在將數據推入包含緩衝區的數組之前,需要將數據克隆到Float32Array中。

相關問題