2013-01-03 23 views
9

Tôi đã chơi với API âm thanh trên web và tôi đang cố gắng tải nhiều phần của một bài hát và thêm chúng vào ArrayBuffer mới và sau đó sử dụng ArrayBuffer để chơi tất cả các phần như một bài hát. Trong ví dụ sau tôi đang sử dụng cùng một dữ liệu bài hát (đó là một vòng lặp nhỏ) thay vì các phần khác nhau của một bài hát.Web Audio API nối/ghép nối các AudioBuffer khác nhau và phát chúng như một bài hát

Vấn đề là nó vẫn chỉ phát một lần thay vì hai lần và tôi không biết tại sao.

Download song

function init() { 

    /** 
    * Appends two ArrayBuffers into a new one. 
    * 
    * @param {ArrayBuffer} buffer1 The first buffer. 
    * @param {ArrayBuffer} buffer2 The second buffer. 
    */ 
    function appendBuffer(buffer1, buffer2) { 
    var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); 
    tmp.set(new Uint8Array(buffer1), 0); 
    tmp.set(new Uint8Array(buffer2), buffer1.byteLength); 
    return tmp; 
    } 

    /** 
    * Loads a song 
    * 
    * @param {String} url The url of the song. 
    */ 
    function loadSongWebAudioAPI(url) { 
    var request = new XMLHttpRequest(); 
    var context = new webkitAudioContext(); 

    request.open('GET', url, true); 
    request.responseType = 'arraybuffer'; 

    /** 
    * Appends two ArrayBuffers into a new one. 
    * 
    * @param {ArrayBuffer} data The ArrayBuffer that was loaded. 
    */ 
    function play(data) { 
     // Concatenate the two buffers into one. 
     var a = appendBuffer(data, data); 
     var buffer = a.buffer; 
     var audioSource = context.createBufferSource(); 
     audioSource.connect(context.destination); 

     //decode the loaded data 
     context.decodeAudioData(buffer, function(buf) { 
     console.log('The buffer', buf); 
     audioSource.buffer = buf; 
     audioSource.noteOn(0); 
     audioSource.playbackRate.value = 1; 
     }); 

    }; 

    // When the song is loaded asynchronously try to play it. 
    request.onload = function() { 
     play(request.response); 
    } 

    request.send(); 
    } 


    loadSongWebAudioAPI('http://localhost:8282/loop.mp3'); 
} 

window.addEventListener('load',init,false); 

Trả lời

15

Các vấn đề trong mã của bạn là bạn đang sao chép và phụ thêm một bản sao của tập tin MP3 vào cuối của chính nó. Bản sao đó bị bộ giải mã bỏ qua một cách hiệu quả - nó không phải là dữ liệu đệm thô, nó chỉ là rác giả ngẫu nhiên trong luồng tệp, sau một tệp MP3 hoàn chỉnh hoàn chỉnh.

Những gì bạn cần làm trước tiên là giải mã dữ liệu âm thanh vào một AudioBuffer, sau đó nối các bộ đệm âm thanh lại với nhau thành một AudioBuffer mới. Điều này đòi hỏi một chút cơ cấu lại mã của bạn.

Những gì bạn muốn làm điều này là:

var context = new webkitAudioContext(); 

function init() { 

    /** 
    * Appends two ArrayBuffers into a new one. 
    * 
    * @param {ArrayBuffer} buffer1 The first buffer. 
    * @param {ArrayBuffer} buffer2 The second buffer. 
    */ 
    function appendBuffer(buffer1, buffer2) { 
    var numberOfChannels = Math.min(buffer1.numberOfChannels, buffer2.numberOfChannels); 
    var tmp = context.createBuffer(numberOfChannels, (buffer1.length + buffer2.length), buffer1.sampleRate); 
    for (var i=0; i<numberOfChannels; i++) { 
     var channel = tmp.getChannelData(i); 
     channel.set(buffer1.getChannelData(i), 0); 
     channel.set(buffer2.getChannelData(i), buffer1.length); 
    } 
    return tmp; 
    } 

    /** 
    * Loads a song 
    * 
    * @param {String} url The url of the song. 
    */ 
    function loadSongWebAudioAPI(url) { 
    var request = new XMLHttpRequest(); 

    request.open('GET', url, true); 
    request.responseType = 'arraybuffer'; 

    /** 
    * Appends two ArrayBuffers into a new one. 
    * 
    * @param {ArrayBuffer} data The ArrayBuffer that was loaded. 
    */ 
    function play(data) { 
     //decode the loaded data 
     context.decodeAudioData(data, function(buf) { 
     var audioSource = context.createBufferSource(); 
     audioSource.connect(context.destination); 

     // Concatenate the two buffers into one. 
     audioSource.buffer = appendBuffer(buf, buf); 
     audioSource.noteOn(0); 
     audioSource.playbackRate.value = 1; 
     }); 

    }; 

    // When the song is loaded asynchronously try to play it. 
    request.onload = function() { 
     play(request.response); 
    } 

    request.send(); 
    } 


    loadSongWebAudioAPI('loop.mp3'); 
} 

window.addEventListener('load',init,false); 

Có một khoảng cách phát lại nhẹ - đó là bởi vì bạn có gần 50ms của sự im lặng vào lúc bắt đầu của mẫu âm thanh của bạn, không phải do vòng lặp vấn đề này.

Hy vọng điều này sẽ hữu ích!

+1

Cảm ơn, nhận xét của bạn đã giúp tôi! http://72lions.github.com/PlayingChunkedMP3-WebAudioAPI/ – 72lions

+0

@cwilso Có thể kết nối nhiều AudioBufferSourceNodes với nhau thành một đĩa đơn tại các thời điểm phát khác nhau không? –

+0

Vâng, bạn chỉ có thể kết nối chúng với cùng một đích. Tôi nghĩ rằng có hiệu quả mà bạn đang tìm kiếm. – cwilso

Các vấn đề liên quan