因此,输入立体声信号是16位带符号整数,左右声道交错,这意味着单个立体声采样的相应缓冲区(8位无符号整数)具有这种格式:
我正在使用node-microphone(这只是录制的javascript接口)从nodejs录制音频,并想使用AudioBuffer
(这是Web Audio的nodejs实现)将流块存储在web-audio-api中API)。
我的音频源有两个通道,而我的AudioBuffer
只有一个(故意)。
这是我的工作配置,用于通过USB声卡记录音频(我使用的是在Raspbian buster上运行的Raspberry pi 3):
arecord -D hw:1,0 -c 2 -f S16_LE -r 44100
使用输出路径运行此命令,并使用aplay播放生成的wav文件,效果很好。因此,节点麦克风能够使用这些参数记录音频,最后我得到一个nodejs可读流流波数据。
但是
我正在努力完成从流块(Buffer
实例)到AudioBuffer
的桥接。更确切地说;我不确定传入数据的格式,不确定目标格式,也不确定如何转换:
流块是Buffer
,因此它们也是Uint8Array
。关于我的配置,我想它们是16位带符号整数的二进制表示形式(小端,我不知道这是什么意思。)>
AudioBuffer
拥有多个缓冲区(每个通道一个,所以在我的情况下只有一个),我可以通过调用Float32Array
作为AudioBuffer.prototype.getChannelData()
来访问。 MDN也说:
该缓冲区包含以下格式的数据:标称范围在-1和+1之间的非交织IEEE754 32位线性PCM,即32位浮点缓冲区,每个样本在-1.0和1.0之间。
关键是要知道我必须从传入的
Buffer
中提取什么,以及如何转换它,使其适合Float32Array
目标(并保持有效的波形数据),并且知道音频源是立体声且AudioBuffer
不是。
到目前为止,我最好的竞争者是Buffer.prototype.readFloatLE()
方法,其名称看起来可以解决我的问题,但这并不成功(只是噪音)。
我的第一个尝试(在进行研究之前)只是天真地将缓冲区数据复制到Float32Array
,并交织索引以处理立体声/单声道转换。显然,它主要产生噪音,但我可以听到一些我录制的声音(难以置信但确实存在),所以我想我应该提一下。
这是我天真的尝试的简化版本(我知道这并不意味着可以很好地发挥作用,我只是将其包括在我的问题中作为讨论的基础):
import { AudioBuffer } from 'web-audio-api' import Microphone from 'node-microphone' const rate = 44100 const channels = 2 // Number of source channels const microphone = new Microphone({ // These parameters result to the arecord command above channels, rate, device: 'hw:1,0', bitwidth: 16, endian: 'little', encoding: 'signed-integer' }) const audioBuffer = new AudioBuffer( 1, // 1 channel 30 * rate, // 30 seconds buffer rate }) const chunks = [] const data = audioBuffer.getChannelData(0) // This is the Float32Array const stream = microphone.startRecording() setTimeout(() => microphone.stopRecording(), 5000) // Recording for 5 seconds stream.on('data', chunk => chunks.push(chunk)) stream.on('close', () => { chunks.reduce((offset, chunk) => { for (var index = 0; index < chunk.length; index += channels) { let value = 0 for (var channel = 0; channel < channels; channel++) { value += chunk[index + channel] } data[(offset + index) / channels] = value / channels // Average value from the two channels } return offset + chunk.length // Since data comes as chunks, this offsets AudioBuffer's index }, 0) })
如果您能提供帮助,我将非常感激:)
[我正在使用节点麦克风(这只是用于录制的javascript接口)录制来自nodejs的音频,并希望使用网络音频API(这是一个nodejs ...)将流块存储在AudioBuffer中。
因此,输入立体声信号是16位带符号整数,左右声道交错,这意味着单个立体声采样的相应缓冲区(8位无符号整数)具有这种格式:
[LEFT ] 8 bits (LSB) [LEFT ] 8 bits (MSB) [RIGHT] 8 bits (LSB) [RIGHT] 8 bits (MSB)
由于记录配置为little endian
[AudioBuffer
单通道缓冲区,由Float32Array
表示,期望值介于-1
和1
之间(每个样本一个值)。
因此要将值从输入Buffer
映射到目标Float32Array
,我必须使用Buffer.prototype.readInt16LE(offset)
方法将字节offset
参数每个样本增加4(2个左字节+ 2个右字节= 4个字节) ),然后将输入值从[-32768;+32768]
范围(16位有符号整数范围)插入到[-1;+1]
范围:
import { AudioBuffer } from 'web-audio-api'
import Microphone from 'node-microphone'
const rate = 44100
const channels = 2 // 2 input channels
const microphone = new Microphone({
channels,
rate,
device: 'hw:1,0',
bitwidth: 16,
endian: 'little',
encoding: 'signed-integer'
})
const audioBuffer = new AudioBuffer(
1, // 1 channel
30 * rate, // 30 seconds buffer
rate
})
const chunks = []
const data = audioBuffer.getChannelData(0)
const stream = microphone.startRecording()
setTimeout(() => microphone.stopRecording(), 5000) // Recording for 5 seconds
stream.on('data', chunk => chunks.push(chunk))
stream.on('close', () => {
chunks.reduce((offset, chunk) => {
for (var index = 0; index < chunk.length; index += channels + 2) {
let value = 0
for (var channel = 0; channel < channels; channel++) {
// Iterates through input channels and adds the values
// of all the channel so we can compute the
// average value later to reduce them into a mono signal
// Multiplies the channel index by 2 because
// there are 2 bytes per channel sample
value += chunk.readInt16LE(index + channel * 2)
}
// Interpolates index according to the number of input channels
// (also divides it by 2 because there are 2 bytes per channel sample)
// and computes average value as well as the interpolation
// from range [-32768;+32768] to range [-1;+1]
data[(offset + index) / channels / 2] = value / channels / 32768
}
return offset + chunk.length
}, 0)
})
因此,输入立体声信号是16位带符号整数,左右声道交错,这意味着单个立体声采样的相应缓冲区(8位无符号整数)具有这种格式: