2013-01-03 10 views
9

Gram z interfejsem Web Audio API i próbuję załadować wiele części utworu i dołączyć je do nowego ArrayBuffer, a następnie użyć tego ArrayBuffer do odtwarzania wszystkich części jako jednej piosenki. W poniższym przykładzie używam tych samych danych utworu (co jest małą pętlą) zamiast różnych części utworu.Web Audio API dołącza/łączy różne AudioBuffery i odtwarza je jako jedną piosenkę

Problem polega na tym, że nadal gra się tylko raz zamiast dwa razy i nie wiem dlaczego.

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); 

Odpowiedz

15

Problem w kodzie jest to, że jesteś kopiowania i dodanie kolejnej kopii pliku MP3 na końcu siebie. Ta kopia zostaje skutecznie zignorowana przez dekoder - nie jest to surowe dane z bufora, to tylko losowe fałszywe śmieci w strumieniu plików, po idealnie kompletnym pliku MP3.

Należy najpierw zdekodować dane audio do AudioBuffer, a następnie dołączyć bufory audio do nowego AudioBuffer. To wymaga trochę restrukturyzacji twojego kodu.

Co chcesz zrobić to:

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); 

Jest niewielka przerwa odtwarzanie - to dlatego, że masz prawie 50ms ciszy na początku swojej próbie dźwiękowej, a nie ze względu na zapętlenie problemów.

Mam nadzieję, że to pomoże!

+1

Dzięki, Twój komentarz pomógł mi! http://72lions.github.com/PlayingChunkedMP3-WebAudioAPI/ – 72lions

+0

@ cwilso Czy możliwe jest podłączenie wielu AudioBufferSourceNodes do jednego w różnych momentach odtwarzania? –

+0

Po prostu podłącz je do tego samego miejsca docelowego. Myślę, że to efekt, którego szukasz. – cwilso