2015-05-25 4 views
5

Я создаю пианино в браузере, используя javascript. Для того, чтобы я играл один и тот же ключ несколько раз одновременно, вместо того, чтобы просто воспроизводить объект Audio, я клонировал его и воспроизводил клон, в противном случае мне пришлось бы дождаться завершения звука или перезапустить его, я хочу.Клонирование источника аудио, не загружая его снова

Я сделал что-то вроде этого:

var audioSrc = new Audio('path/'); 
window.onkeypress = function(event) { 
    var currentAudioSrc = audioSrc.cloneNode(); 
    currentAudioSrc.play(); 
} 

Проблема, я проверял инспектор хром, и я заметил, что каждый раз, когда я клонировать объект, браузер загрузить его снова

enter image description here

Я проверил некоторых людей, которые хотели достичь аналогичных вещей, и заметил, что большинство из них имеют ту же проблему, что и я, они перезагружают файл. Единственный пример, который я нашел, который может воспроизводить один и тот же источник звука несколько раз одновременно, - SoundJs http://www.createjs.com/SoundJS

Я попытался проверить источник, но не мог понять, как это было сделано. Есть идеи?


+1

Да, я вижу, как это будет трудно отследить, если вы не знакомы с архитектурой SoundJS. WebAudioLoader._sendComplete декодирует загруженный файл в AudioBuffer, который затем передается как _result, который обрабатывается в AbstractPlugin._handlePreloadComplete, сохраняя его в хэшировании _audioSources (WebAudioPlugin расширяет AbstractPlugin). Этот сохраненный AudioBuffer затем передается каждому новому WebAudioSoundInstance и используется для создания аудиоузлов. Его та же идея, что и принятый ответ, хранит звуковой буфер и использует его для создания новых аудиоузлов. – OJay

ответ

3

С webAudioAPI вы могли бы сделать что-то вроде этого:

  • Загрузите один раз файл через XMLHttpRequest.
  • Append ответ на буфер
  • Создать новую bufferSource и воспроизвести его при каждом вызове
  • Откат к вашей первой реализации, если webAudioAPI не поддерживается (IE)

window.AudioContext = window.AudioContext||window.webkitAudioContext; 
 
if(!window.AudioContext) 
 
    yourFirstImplementation(); 
 
else{ 
 
var buffer, 
 
ctx = new AudioContext(), 
 
gainNode = ctx.createGain(); 
 
gainNode.connect(ctx.destination); 
 
var vol = document.querySelector('input'); 
 
vol.value = gainNode.gain.value; 
 
vol.addEventListener('change', function(){ 
 
    gainNode.gain.value = this.value; 
 
    }, false); 
 

 
function createBuffer(){ 
 
    ctx.decodeAudioData(this.response, function(b) { 
 
    buffer = b; 
 
    }, function(e){console.warn(e)}); 
 
    var button = document.querySelector('button'); 
 
    button.addEventListener('click', function(){playSound(buffer)}); 
 
    button.className = 'ready'; 
 
    } 
 

 
var file = 'https://dl.dropboxusercontent.com/s/agepbh2agnduknz/camera.mp3', 
 
xhr = new XMLHttpRequest(); 
 
xhr.onload = createBuffer; 
 
xhr.open('GET', file, true); 
 
xhr.responseType = 'arraybuffer'; 
 
xhr.send(); 
 

 
function playSound(buf){ 
 
    var source = ctx.createBufferSource(); 
 
    source.buffer = buf; 
 
    source.connect(gainNode); 
 
    source.onended = function(){if(this.stop)this.stop(); if(this.disconnect)this.disconnect();} 
 
    source.start(0); 
 
    } 
 
} 
 

 
function yourFirstImplementation(){ 
 
    alert('webAudioAPI is not supported by your browser'); 
 
    }
button{opacity: .2;} 
 
button.ready{opacity: 1};
<button>play</button> 
 
<input type="range" max="5" step=".01" title="volume"/>

+2

Я не могу перестать играть: D – myfunkyside

+0

он работал как шарм. Большое спасибо –

+0

есть ли способ контролировать громкость этого аудио буфера? –

0

cloneNode один логический аргумент:

var dupNode = node.cloneNode(deep); 
/* 
    node 
    The node to be cloned. 
    dupNode 
    The new node that will be a clone of node 
    deep(Optional) 
    true if the children of the node should also be cloned, or false to clone only the specified node. 
*/ 

Также обратите внимание от MDN:

Deep является дополнительным аргументом. Если этот параметр опущен, метод действует так, как будто значение глубины было истинным, по умолчанию используется глубокое клонирование в качестве поведения по умолчанию . Чтобы создать мелкий клон, необходимо установить глубину .

Это поведение было изменено в последней спецификации, и если этот параметр опущен, метод будет действовать так, как если бы значение глубины было ложным. Хотя он по-прежнему по желанию, вы всегда должны обеспечить глубокий аргумент как для прямой и обратной совместимости

Итак, попробуйте использовать deep = false для предотвращения загрузки ресурса:

var audioSrc = new Audio('path/'); 
window.onkeypress = function(event) { 
    var currentAudioSrc = audioSrc.cloneNode(false); 
    currentAudioSrc.play(); 
} 
+1

Из моих тестов это не работает для проблемы в хроме. Вам удалось избежать повторной загрузки таким образом? – Kaiido

+0

Это тоже не сработало. –