2012-10-10 2 views
3

사용자가 자신의 메시지를 녹음 할 수있는 커뮤니티 기반 인터넷 라디오를 만들고 있습니다.웹 오디오 API 출력

나는 내 사용자가 자신의 기록에 효과를 추가 할 수 있도록 (리버브 (Reverb) 아소 바이 쿼드 필터와 같은 ..)

이 가능 (하나의 PCM 출력에 (효과 포함) 최종 믹싱을 처리하는 것입니다 예를 들어 오디오 태그 src="data:audio/wav;base64")에 게시하여 믹스를 게시 할 수 있습니까?

나는이 시도 :

recorder.locals.filter1.connect(recorder.locals.filter3); 
recorder.locals.filter3.connect(recorder.locals.filter2); 
recorder.locals.filter2.connect(context.destination); 
recorder.locals.source.noteOn(0); 
context.oncomplete = function(e) { var buffer = e.renderedBuffer; }; 
context.startRendering(); 

를하지만 나에게 아무것도주지 않았다.

답변

7

해결책을 찾았습니다. startRendering()을 사용할 때 durationsamplerate을 컨텍스트에 제공해야합니다.

(new webkitAudioContext(channels, duration * samplerate, samplerate);

미리 렌더링 된 audioBuffer를 생성하고이를 base64 wav로 변환하는 방법은 다음과 같습니다.

var audioBuffer = audio.createBuffer(arrayBuffer, false), /* <- Input Audio */ 
    offlineContext = new webkitAudioContext(1, audioBuffer.duration * 44100, 44100); 

offlineContext.oncomplete = function(event) { 

    var buffer = event.renderedBuffer;  
    var UintWave = createWaveFileData(buffer); 
    var base64 = btoa(uint8ToString(UintWave)); 

    document.getElementById("audio").src = "data:audio/wav;base64," + base64; 

}; 

var source = offlineContext.createBufferSource(); 
source.buffer = audioBuffer; 
var gain = offlineContext.createGainNode(); 
// Effects 
var filter1 = offlineContext.createBiquadFilter(); 
filter1.type = 2; 
filter1.frequency.value = 4000; 
filter1.Q.value = 0.1; 
// Connect 
source.connect(filter1); 
filter1.connect(gain); 
gain.connect(offlineContext.destination); 

source.noteOn(0); 
offlineContext.startRendering(); 

function createWaveFileData(audioBuffer) { 

    var frameLength = audioBuffer.length; 
    var numberOfChannels = audioBuffer.numberOfChannels; 
    var sampleRate = audioBuffer.sampleRate; 
    var bitsPerSample = 16; 
    var byteRate = sampleRate * numberOfChannels * bitsPerSample/8; 
    var blockAlign = numberOfChannels * bitsPerSample/8; 
    var wavDataByteLength = frameLength * numberOfChannels * 2; // 16-bit audio 
    var headerByteLength = 44; 
    var totalLength = headerByteLength + wavDataByteLength; 

    var waveFileData = new Uint8Array(totalLength); 

    var subChunk1Size = 16; // for linear PCM 
    var subChunk2Size = wavDataByteLength; 
    var chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size); 

    writeString("RIFF", waveFileData, 0); 
    writeInt32(chunkSize, waveFileData, 4); 
    writeString("WAVE", waveFileData, 8); 
    writeString("fmt ", waveFileData, 12); 

    writeInt32(subChunk1Size, waveFileData, 16);  // SubChunk1Size (4) 
    writeInt16(1, waveFileData, 20);     // AudioFormat (2) 
    writeInt16(numberOfChannels, waveFileData, 22); // NumChannels (2) 
    writeInt32(sampleRate, waveFileData, 24);   // SampleRate (4) 
    writeInt32(byteRate, waveFileData, 28);   // ByteRate (4) 
    writeInt16(blockAlign, waveFileData, 32);   // BlockAlign (2) 
    writeInt32(bitsPerSample, waveFileData, 34);  // BitsPerSample (4) 

    writeString("data", waveFileData, 36);    
    writeInt32(subChunk2Size, waveFileData, 40);  // SubChunk2Size (4) 

    // Write actual audio data starting at offset 44. 
    writeAudioBuffer(audioBuffer, waveFileData, 44); 

    return waveFileData; 

} 

function writeString(s, a, offset) { 
    for (var i = 0; i < s.length; ++i) { 
     a[offset + i] = s.charCodeAt(i); 
    } 
} 

function writeInt16(n, a, offset) { 
    n = Math.floor(n); 

    var b1 = n & 255; 
    var b2 = (n >> 8) & 255; 

    a[offset + 0] = b1; 
    a[offset + 1] = b2; 
} 

function writeInt32(n, a, offset) { 
    n = Math.floor(n); 
    var b1 = n & 255; 
    var b2 = (n >> 8) & 255; 
    var b3 = (n >> 16) & 255; 
    var b4 = (n >> 24) & 255; 

    a[offset + 0] = b1; 
    a[offset + 1] = b2; 
    a[offset + 2] = b3; 
    a[offset + 3] = b4; 
} 

function writeAudioBuffer(audioBuffer, a, offset) { 
    var n = audioBuffer.length; 
    var channels = audioBuffer.numberOfChannels; 

    for (var i = 0; i < n; ++i) { 
     for (var k = 0; k < channels; ++k) { 
      var buffer = audioBuffer.getChannelData(k); 
      var sample = buffer[i] * 32768.0; 

      // Clip samples to the limitations of 16-bit. 
      // If we don't do this then we'll get nasty wrap-around distortion. 
      if (sample < -32768) 
       sample = -32768; 
      if (sample > 32767) 
       sample = 32767; 

      writeInt16(sample, a, offset); 
      offset += 2; 
     } 
    } 
} 

function uint8ToString(buf) { 
    var i, length, out = ''; 
    for (i = 0, length = buf.length; i < length; i += 1) { 
     out += String.fromCharCode(buf[i]); 
    } 
    return out; 
} 

누군가이 방법을 더 쉽게 또는 더 짧은 방법으로 파악하면 좋을 것입니다.

+0

감사합니다! 이걸 찾고 있었어. – Thomas