如何使用网络音频获得音轨样本的正确振幅(不播放)api

How to get right amplitudes (without playing) of the audiotrack samples with web audio api

我用网络音频 api 提供给我的样本体积数据做了一些实验,看起来它们与从其他程序(例如 audasity)获得的数据不同。如果我们将采样数组长度除以采样率(在我的例子中是 leftChannel.length/44100),它显示音频的持续时间更长,约为 40 秒,并且在大胆显示音频中的响亮样本的情况下,我的脚本显示安静(几乎有时沉默)。而且我演奏的曲子被我的剧本报告为大胆而安静,而且声音肯定很大。

所以问题是:我找到音频样本幅度的方法是否正确?我的代码有什么问题?

我已阅读有关为音轨创建波形的帖子 Create a waveform of the full track with Web Audio API 并且有我使用的很好的例子,所以这是我的代码:

(function($) {

  window.AudioContext = window.AudioContext || window.webkitAudioContext;
  var context = new window.AudioContext(); // Create audio container
  var audioData;
  var checkPoint = 21; //this is point in seconds just for debugging, remove later!!
  function decode(audioData) {
    try{
        context.decodeAudioData(audioData,
        function(decoded){
            drawSound(decoded);
            playAudio(decoded);
        },
        function(){ // do nothing here
        });
    } catch(e) {
        console.log('decode exception',e.message);
    }
  }

  function drawSound(buffer) {
    var leftChannel = buffer.getChannelData(0);
    console.log('audio duration: ' + leftChannel.length/44100 + ' sec');
    for (var i = 0; i < leftChannel.length; i++) {
      var volume = leftChannel[i];
      //draw(volume, i);
      
      //this is just for debugging, remove later!!
      if (Math.abs(i - checkPoint * 44100) < 100) {
        console.log(leftChannel[i]);
      }
      
    }    
  }

  function playAudio(buffer) {
    console.log('start playing audio');
    var audioTrack = context.createBufferSource();
    audioTrack.connect(context.destination);
    audioTrack.buffer = buffer;
    audioTrack.start();
  }

  $(document).ready(function() {
    $('body').append($('<input type="text" id="checkpoint" />'));
    $('#checkpoint').change(function() {
      checkPoint = $(this).val();
    });
    $('body').append($('<input type="file" id="audiofile" />'));
    $('input[type="file"]').change(function() {
      var reader = new FileReader();
      reader.onload = function(e) {
        audioData = this.result;
        decode(audioData);
      };
      reader.readAsArrayBuffer(this.files[0]);      
    });
    
  });
})(jQuery);
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  </head>
  <body>
    
  </body>
</html>

我做了更彻底的测量和更多的测试,发现我的脚本没有错误,但是!!网络音频 api 在我的一台计算机上(在 Chrome 和 Firefox 中)给出的结果等于 audasity 的音轨长度和振幅,而在另一台计算机上(再次独立于浏览器)给出错误的结果,所以我得出结论,网络音频 api 使用了一些低级处理器相关的功能,因为我的两台计算机上都有相同的 OS (windows 7),唯一的区别是硬件。 我的 post 中提供的代码按预期工作。

如果您认为这是 Chrome 中的错误,请在 crbug.com/new 中提交错误。并提供一个音轨,产生不同的结果和关于不同机器的细节。

另请注意,在 chrome 中,ffmpeg 用于解码文件。解码文件的长度可能与 audacity 不同。

感谢 Raymond Toy 我设法解决了这个问题。 buffer.getChannelData(0) 返回的结果似乎取决于计算机声卡的采样率(您可以从 context.sampleRate 中找到)。如果你想找到轨道的长度,你应该这样做:

var samples = buffer.getChannelData(0);
var duration = samples/context.sampleRate;

样本从开始的偏移量(以秒为单位)为:

var sample = samples[i];
var offsetInSeconds = i/context.sampleRate

我的错误是我在公式中使用了 mp3 音轨的采样率,这导致在具有不同声卡采样率的计算机上出现错误。

正如 Raymond Toy 所注意到的,如果您只需要音频的持续时间,您可以像这样更简单:

var duration = buffer.duration;