Наложение двух звуковых буферов в один буферный источник

Попытка объединить два буфера в один; Мне удалось создать два буфера из аудиофайлов, загрузить и воспроизвести их. Теперь мне нужно объединить два буфера в один буфер. Как их можно объединить?

  context = new webkitAudioContext();
  bufferLoader = new BufferLoader(
    context,
    [
      'audio1.mp3',
      'audio2.mp3',
    ],
    finishedLoading
    );

  bufferLoader.load();

function finishedLoading(bufferList) {
  // Create the two buffer sources and play them both together.
  var source1 = context.createBufferSource();
  var source2 = context.createBufferSource();
  source1.buffer = bufferList[0];
  source2.buffer = bufferList[1];

  source1.connect(context.destination);
  source2.connect(context.destination);
  source1.start(0);
  source2.start(0);  
}

Теперь эти источники загружаются отдельно и воспроизводятся одновременно; но как мне объединить эти два источника в один буферный источник? Я НЕ хочу их добавлять, я хочу наложить / объединить их.

объяснения и / или отрывки были бы замечательными.


person user3353218    schedule 02.03.2014    source источник


Ответы (2)


В аудио, чтобы смешать два аудиопотока (здесь, буферов) в один, вы можете просто добавить каждое значение выборки вместе. Фактически, вот что мы можем сделать, опираясь на ваш фрагмент:

/* `buffers` is a javascript array containing all the buffers you want
 * to mix. */
function mix(buffers) {
  /* Get the maximum length and maximum number of channels accros all buffers, so we can
   * allocate an AudioBuffer of the right size. */
  var maxChannels = 0;
  var maxDuration = 0;
  for (var i = 0; i < buffers.length; i++) {
    if (buffers[i].numberOfChannels > maxChannels) {
      maxChannels = buffers[i].numberOfChannels;
    }
    if (buffers[i].duration > maxDuration) {
      maxDuration = buffers[i].duration;
    }
  }
  var out = context.createBuffer(maxChannels,
                                 context.sampleRate * maxDuration,
                                 context.sampleRate);

  for (var j = 0; j < buffers.length; j++) {
    for (var srcChannel = 0; srcChannel < buffers[j].numberOfChannels; srcChannel++) {
      /* get the channel we will mix into */
      var out = mixed.getChanneData(srcChannel);
      /* Get the channel we want to mix in */
      var in = buffers[i].getChanneData(srcChannel);
      for (var i = 0; i < in.length; i++) {
        out[i] += in[i];
      }
    }
  }
  return out;
}

Затем просто измените возврат из этой функции к новому AudioBufferSourceNode.buffer и воспроизведите его как обычно.

Пара примечаний: в моем фрагменте для простоты предполагается, что:

  • Если у вас есть монобуфер и стереобуфер, вы услышите только монобуфер в левом канале смешанного буфера. Если вы хотите, чтобы он копировался влево и вправо, вам придется это сделать, это называется повышающее микширование;
  • Если вы хотите, чтобы буфер был тише или громче, чем другой буфер (например, если вы переместили фейдер громкости на микшерной консоли), просто умножьте значение toMix[i] на число меньше 1,0, чтобы он стал тише, или больше 1,0, чтобы он стал громче .

Опять же, API веб-аудио делает все это за вас, поэтому мне интересно, почему вам нужно делать это самостоятельно, но, по крайней мере, теперь вы знаете, как :-).

person padenot    schedule 08.03.2014
comment
Как смешать 2 медиа-потока вместе? - person IvRRimUm; 30.11.2016
comment
Исправлена ​​проблема, извините за это. - person padenot; 06.03.2017
comment
@padenot вообще ничего не исправили. Есть еще неопределенные переменные, такие как mixed и context. Другая ошибка заключается в том, что переменная цикла i используется вне контекста. Ниже также есть еще один цикл, использующий свой собственный счетчик i, и я не понимаю, что происходит. Опять же, API веб-аудио делает все это за вас, также было бы полезно для нас, если бы вы упомянули метод, который включает эту функцию. - person I Want Answers; 08.10.2017

@Padenot прав, но в его коде есть опечатка, поэтому он не может работать, если вы скопируете / вставите его. Ниже вы можете найти тот же код с исправлениями, чтобы вы могли его использовать. Спасибо за помощь @Padenot;)

function mix(buffers) {

    var nbBuffer = buffers.length;// Get the number of buffer contained in the array buffers
    var maxChannels = 0;// Get the maximum number of channels accros all buffers
    var maxDuration = 0;// Get the maximum length

    for (var i = 0; i < nbBuffer; i++) {
        if (buffers[i].numberOfChannels > maxChannels) {
            maxChannels = buffers[i].numberOfChannels;
        }
        if (buffers[i].duration > maxDuration) {
            maxDuration = buffers[i].duration;
        }
    }

    // Get the output buffer (which is an array of datas) with the right number of channels and size/duration
    var mixed = context.createBuffer(maxChannels, context.sampleRate * maxDuration, context.sampleRate);        

    for (var j=0; j<nbBuffer; j++){

        // For each channel contained in a buffer...
        for (var srcChannel = 0; srcChannel < buffers[j].numberOfChannels; srcChannel++) {

            var _out = mixed.getChannelData(srcChannel);// Get the channel we will mix into
            var _in = buffers[j].getChannelData(srcChannel);// Get the channel we want to mix in

            for (var i = 0; i < _in.length; i++) {
                _out[i] += _in[i];// Calculate the new value for each index of the buffer array
            }
        }
    }

    return mixed;
}
person Faks    schedule 05.07.2018