Published on

pcm 音频数据采集

Authors
  • avatar
    Name
    Magikarp
    Twitter

音频源

getUserMedia

录音的音频源当然是设备的话筒(音频输入设备),所以需要用到 navigator.mediaDevices.getUserMedia() 这个方法。

该方法有一个参数,

  • constraints,指定请求的媒体类型,这儿只牵扯都音频,所以仅需 audio:true 即可。

该方法返回一个 promise,成功回调的参数是一个  MediaStream 对象。

注:不推荐使用 navigator.getUserMedia() 方法,因为该方法已经从 web 标准中删除了。

createMediaStreamSource

此时 createMediaStreamSource() 方法就有用啦,引用 MDN 上的一段话:AudioContext 接口的 createMediaStreamSource()方法用于创建一个新的 MediaStreamAudioSourceNode 对象, 需要传入一个媒体流对象( MediaStream 对象), 然后来自 MediaStream 的音频就可以被播放和操作。

他返回的是 MediaStreamAudioSourceNode 类型的,也就是音频源节点,到此处,音频源已经有了,下面看下保存音频的节点(音频处理节点)。

navigator.mediaDevices
  .getUserMedia({
    audio: true,
  })
  .then((stream) => {
    audioInput = context.createMediaStreamSource(stream)
  })
  .catch((err) => {
    console.log('error')
  })

此时,audioInput 就是音频源节点。

音频处理节点

createScriptProcessor

createScriptProcessor() ,该方法创建一个 ScriptProcessorNode 用于通过 JavaScript 直接处理音频,有三个参数:

  • bufferSize,缓冲区大小,以样本帧为单位。一般有以下值 256, 512, 1024, 2048, 4096, 8192, 16384。当传 0 时,系统会取当前环境最合适的缓冲区大小。每当缓冲区满时,则会触发 audioprocess 事件,即 bufferSize 控制着回调事件的频率。注:mdn 提示 chrome 31 版本的不支持传 0 的方式。
  • numberOfInputChannels,值为整数,用于指定输入 node 的声道的数量,默认值是 2,最高能为 32,且不能为 0。
  • numberOfOutputChannels,值为整数,用于指定输出 node 的声道的数量,默认值是 2,最高能取 32,不能为 0。

保证 numberOfInputChannels 和 numberOfOutputChannels 相等就行了,通过监听 audioprocess 后,就可以处理对应的音频流了。

recorder = context.createScriptProcessor(4096, 1, 1)
recorder.onaudioprocess = function (e) {
  // getChannelData返回Float32Array类型的pcm数据
  var data = e.inputBuffer.getChannelData(0)

  inputData.push(newFloat32Array(data))
  size += data.length
}

我这默认是一通道的,所以只对 0 进行了数据收集。MDN 上说,audioporcess 缓冲区的数据是,非交错的 32 位线性 PCM,标称范围介于-1 和之间+1,即 32 位浮点缓冲区,每个样本介于-1.0 和 1.0 之间。所以等录音结束后,inputData 中就是存放的 pcm 格式的录音数据了(还需处理下)。