代码之家  ›  专栏  ›  技术社区  ›  Dan P.

使用Web音频API相互连接节点

  •  1
  • Dan P.  · 技术社区  · 6 年前

    我正在尝试一些音频方面的东西:

    • 增大/减小音频的总音量。
    • 增加/减少特定通道的音量和延迟(左)。

    我有以下代码:

    var audioContext = window.AudioContext || window.webkitAudioContext,
        context = new audioContext(),
        sourceNode = context.createMediaElementSource(document.getElementById('audio'));
    
    // Nodes to control the left channel
    var channelSplitterNode = context.createChannelSplitter(1);
    
    var leftChannelGainNode = context.createGain();
    leftChannelGainNode.gain.value = 1.10;
    channelSplitterNode.connect(leftChannelGainNode, 0);
    
    var leftChannelDelayNode = context.createDelay();
    leftChannelDelayNode.delayTime.value = 0.10;
    channelSplitterNode.connect(leftChannelDelayNode, 0);
    
    // Node to control the track's overall volume
    var volumeGainNode = context.createGain();
    
    // I think this might be where I mess up
    sourceNode.connect(leftChannelGainNode);
    sourceNode.connect(leftChannelDelayNode);
    sourceNode.connect(volumeGainNode);
    volumeGainNode.connect(context.destination);
    
    // Change gain at any time like so 
    // volumeGainNode.gain.value = 1.50;
    // leftChannelDelayNode.delayTime.value = 1.50;
    // leftChannelGainNode.gain.value = 2.00;
    

    如何建立联系以实现我的目标?

    现场演示: https://jsfiddle.net/Lvvozsot/183/

    1 回复  |  直到 6 年前
        1
  •  5
  •   user1693593 user1693593    6 年前

    您需要将节点连接为链;可以将其视为配线电缆的概念。

    您还需要 merger node 组合拆分通道(请参见 this example 用于其用途)。

    因此,连接列表将是:

    • 源拆分器节点
    • 左通道增益节点
    • 增益节点延迟节点
    • 延迟节点+右通道合并节点
    • 合并节点输出

    以图形形式:

    flow diagram

    使现代化 添加技术细节(由Dan P.的fiddle更新):

    然后,使用代码的链将是:

    // nodes
    sourceNode = context.createMediaElementSource(audioPlayer);
    splitter = context.createChannelSplitter(2);
    gainL = context.createGain();
    delayL = context.createDelay();
    merger = context.createChannelMerger(2);
    gainGeneral = context.createGain();        
    
    // source to splitter
    sourceNode.connect(splitter);
    
    // left channel to gain
    splitter.connect(gainL, 0);
    
    // gain to delay
    gainL.connect(delayL);
    
    // delay to merger
    delayL.connect(merger, 0, 0);
    
    // remeber right channel to merger here:
    splitter.connect(merger, 1, 1);
    
    // merged signal to common gain node
    merger.connect(gainGeneral);
    
    // gain to output
    gainGeneral.connect(context.destination);
    

    演示:

    var gainL, delayL, gainGeneral, merger, splitter, context, sourceNode, audioPlayer;
    audioPlayer = $('#audioPlayer')[0];
    $('#play').on('click', function(){audioPlayer.play();});
    
    context = new (window.AudioContext || window.webkitAudioContext)();
    
    // nodes
    sourceNode = context.createMediaElementSource(audioPlayer);
    splitter = context.createChannelSplitter(2);
    gainL = context.createGain();
    delayL = context.createDelay();
    merger = context.createChannelMerger(2);
    gainGeneral = context.createGain();        
    
    // source to splitter
    sourceNode.connect(splitter);
    
    // left channel to gain
    splitter.connect(gainL, 0);
    
    // gain to delay
    gainL.connect(delayL);
    
    // delay to merger
    delayL.connect(merger, 0, 0);
    
    // remeber right channel to merger here:
    splitter.connect(merger, 1, 1);
    
    // merged signal to common gain node
    merger.connect(gainGeneral);
    
    // gain to output
    gainGeneral.connect(context.destination);
    
    $('.adjust-stereo-btn').on('click', function () {
    	var action = $(this).data('action');
    
      switch (action) {
        case 'normal':
          gainL.gain.value = 1.00;
          delayL.delayTime.value = 0.00;
          break;
        case 'wide':
          // I recommend values <10ms as above our brain is able to separate the signal.
          // Delays may cause phase issues too (if using loudspeakers)
          gainL.gain.value = 1.0;  // set to 1 for this demo
          delayL.delayTime.value = 5/1000;
          break;
        case 'wider':
          gainL.gain.value = 1.0;
          delayL.delayTime.value = 10/1000;
          break;
      }
    });
    
    $('.adjust-volume-btn').on('click', function () {
    	var action = $(this).data('action');
      switch (action) {
        case 'normal':
          gainGeneral.gain.value = 1.00;
          break;
        case 'loud':
          gainGeneral.gain.value = 2.00;
          break;
        case 'louder':
          gainGeneral.gain.value = 3.00;
          break;
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="play" style="width: 100px; height: 25px;">Play Track</button>
    
    <div>
      <h1>Adjust Stereo Width</h1>
      <button class="adjust-stereo-btn" data-action="normal">Normal</button>
      <button class="adjust-stereo-btn" data-action="wide">Wide</button>
      <button class="adjust-stereo-btn" data-action="wider">Wider</button>
    </div>
    
    <div>
      <h1>Adjust Volume</h1>
      <button class="adjust-volume-btn" data-action="normal">Normal</button>
      <button class="adjust-volume-btn" data-action="loud">Loud</button>
      <button class="adjust-volume-btn" data-action="louder">Louder</button>
    </div>
    
    <audio crossorigin="anonymous" id="audioPlayer" src="https://www.faceflow.com/beam_me_up_mast.mp3"></audio>