Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将PCM音频从44100降低到8000_Javascript_Audio_Pcm_Downsampling - Fatal编程技术网

Javascript 将PCM音频从44100降低到8000

Javascript 将PCM音频从44100降低到8000,javascript,audio,pcm,downsampling,Javascript,Audio,Pcm,Downsampling,我已经做了一段时间的音频识别演示,api需要我传递一个采样率为8000或16000的.wav文件,所以我必须减少采样。我尝试了以下两种算法。虽然没有一个能像我希望的那样解决问题,但结果有一些不同,我希望这能让问题变得更清楚 这是我的第一次尝试,当sampleRate%outputSampleRate=0时效果很好,但是当outputSampleRate=8000或1600时,结果音频文件是无提示的(这意味着输出数组的每个元素的值都是0): 这让我困惑了很长时间,请让我知道我错过了什么 -----

我已经做了一段时间的音频识别演示,api需要我传递一个采样率为8000或16000的.wav文件,所以我必须减少采样。我尝试了以下两种算法。虽然没有一个能像我希望的那样解决问题,但结果有一些不同,我希望这能让问题变得更清楚

这是我的第一次尝试,当sampleRate%outputSampleRate=0时效果很好,但是当outputSampleRate=8000或1600时,结果音频文件是无提示的(这意味着输出数组的每个元素的值都是0):

这让我困惑了很长时间,请让我知道我错过了什么

-----------------------------解决之后--------------------------------

我很高兴它现在运行良好,下面是函数interleave()的正确版本:

函数交织(e){
var t=e.长度;
采样率+=0.0;
输出采样器+=0.0;
var s=0,
o=采样器/输出采样器,
u=数学单元(t*输出采样器/采样器),
a=新的浮动阵列(u);
对于(i=0;i
所以你可以看到我传递给它的变量不是正确的类型~
再次感谢亲爱的@jaket和其他朋友~虽然我自己也有办法,但他们让我更好地了解了原始情况~~~:)

采样率转换比简单地扔掉或插入样本要多得多

让我们举一个简单的例子,以2为因子进行下采样。(例如,44100->22050)。一种幼稚的方法是扔掉所有其他样本。但是想象一下,在最初的44.1kHz文件中,有一个20khz的正弦波。该采样率在奈奎斯特(fs/2=22050)范围内。在你扔掉每一个样本后,它仍然会以10kHz的频率存在,但现在它会高于nyquist(fs/2=11025),并且它会混叠到你的输出信号中。最终的结果是,你将有一个大脂肪正弦波坐在8975赫兹

为了避免下采样期间出现这种混叠,您需要首先设计一个低通滤波器,根据您的抽取比选择截止值。在上面的例子中,你会先切断11025以上的所有数据,然后再进行毁灭

硬币的另一面称为上采样和插值。假设您希望将采样率提高2倍。首先在每个输入样本之间插入零,然后运行插值过滤器来计算值,以使用周围的样本替换零

速率变化通常涉及抽取和插值的某种组合,因为两者都是通过整数个样本工作的。以48000->32000为例。输出/输入比为32000/48000或2/3。所以你要把48000的样本增加2,得到96000,然后再减少3,得到32000。另一件事是,您可以将这些过程链接在一起。所以,如果你想从48000->16000,你应该上升3,下降2,下降2。此外,44100特别困难。例如,要从48000->44100移动,您需要上升147,下降160,并且您不能将其分解为更小的术语


我建议您找到一些代码或库来为您执行此操作。您需要寻找的是多相滤波器或采样率转换器。

问题在于您试图使用浮点数访问数组。当您访问
inputL[5.5125]
时,它与
input['5.5125']
相同,即您将尝试从数组对象中读取名为
5.5125
的属性,而不是从数组数据中读取项

将数字四舍五入,以获得最接近的整数索引:

function interleave(inputL){
  var compression = sampleRate / outputSampleRate;
  var length = inputL.length / compression;
  var result = new Float32Array(length);

  var index = 0,
  inputIndex = 0;

  while (index < length){
    result[index++] = inputL[Math.round(inputIndex)];
    inputIndex += compression;
  }
  return result;
}
函数交织(inputL){
var压缩=采样器/输出采样器;
变量长度=输入长度/压缩;
var结果=新的浮点数组(长度);
var指数=0,
inputIndex=0;
while(索引<长度){
结果[index++]=inputL[Math.round(inputIndex)];
inputIndex+=压缩;
}
返回结果;
}

@jacket说的是真的,你不能仅仅通过减少阵列中的项目数量来降低音频采样,我可以想到两种方法:

  • 如果你对
    wav
    这是一种未压缩格式,会耗尽你的带宽,你可以试试我写的这个mp3文件,只需修改
    scripts/recorder.js

     config: {
        sampleRate: this.context.sampleRate
      }
    

  • 另一个选项是,如果您已经在后端进行某种音频处理,并且不介意将ffmpeg添加到堆栈中,则可以将wav文件(未压缩格式)/ogg文件(压缩格式)发送到服务器,在那个里,你们可以在进行其余处理之前,使用ffmpeg将其更改为你们喜欢的任何格式,以及你们想要的任何采样率


  • 当您说“静音”时,您假定了解音频编码和播放域,该域定义了使音频文件对耳朵或扬声器静音的特征。最好专注于输入和输出序列的数学特性(你能描述它们吗?),剥离一层抽象。@doldt Hi!感谢您的回答,“silnt”表示数组中每个元素的值都是0,我将尽快将其添加到我的描述中~感谢您的解释~这非常有帮助~~~O(∩_∩)O~我试过了,但没用。我也附上了文件
    function encodeWAV(samples){
      var sampleBits = 16;
      var dataLength = samples.length*(sampleBits/8);
    
      var buffer = new ArrayBuffer(44 + dataLength);
      var view = new DataView(buffer);
    
      var offset = 0;
    
      /* RIFF identifier */
      writeString(view, offset, 'RIFF'); offset += 4;
      /* file length */
      view.setUint32(offset, 32 + dataLength, true); offset += 4;
      /* RIFF type */
      writeString(view, offset, 'WAVE'); offset += 4;
      /* format chunk identifier */
      writeString(view, offset, 'fmt '); offset += 4;
      /* format chunk length */
      view.setUint32(offset, 16, true); offset += 4;
      /* sample format (raw) */
      view.setUint16(offset, 1, true); offset += 2;
      /* channel count */
      view.setUint16(offset, outputChannels, true); offset += 2;
      /* sample rate */
      view.setUint32(offset, outputSampleRate, true); offset += 4;
      /* byte rate (sample rate * block align) */
      view.setUint32(offset, outputSampleRate*outputChannels*(sampleBits/8), true); offset += 4;
      /* block align (channel count * bytes per sample) */
      view.setUint16(offset, outputChannels*(sampleBits/8), true); offset += 2;
      /* bits per sample */
      view.setUint16(offset, sampleBits, true); offset += 2;
      /* data chunk identifier */
      writeString(view, offset, 'data'); offset += 4;
      /* data chunk length */
      view.setUint32(offset, dataLength, true); offset += 4;
    
      floatTo16BitPCM(view, offset, samples);
    
      return view;
    }
    
        function interleave(e){
          var t = e.length;
          sampleRate += 0.0;
          outputSampleRate += 0.0;
          var s = 0,
          o = sampleRate / outputSampleRate,
          u = Math.ceil(t * outputSampleRate / sampleRate),
          a = new Float32Array(u);
          for (i = 0; i < u; i++) {
            a[i] = e[Math.floor(s)];
            s += o;
          }
    
          return a;
        }
    
    function interleave(inputL){
      var compression = sampleRate / outputSampleRate;
      var length = inputL.length / compression;
      var result = new Float32Array(length);
    
      var index = 0,
      inputIndex = 0;
    
      while (index < length){
        result[index++] = inputL[Math.round(inputIndex)];
        inputIndex += compression;
      }
      return result;
    }
    
     config: {
        sampleRate: this.context.sampleRate
      }
    
      config: {
        sampleRate: 16000 // or any other sampling rate
      }