polyphonic audio playback with node.js on raspberry pi
我一直在尝试在运行最新raspbian的raspberry pi 3上使用node.js创建和弦WAV播放:
- 插入aplay / mpg123 /其他程序-仅允许我一次播放单个声音
- 我尝试将https://github.com/sebpiq/node-web-audio-api和https://github.com/TooTallNate/node-speaker结合使用(下面的示例代码),但是音频质量很低,很多 失真
我在这里想念什么吗? 我知道我可以轻松地用另一种编程语言来做到这一点(我能够使用SDL和pygame编写C ++代码),但问题是,是否可以使用node.js :)
这是我当前的网络音频API +节点扬声器代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | var AudioContext = require('web-audio-api').AudioContext; var Speaker = require('speaker'); var fs = require('fs'); var track1 = './tracks/1.wav'; var track2 = './tracks/1.wav'; var context = new AudioContext(); context.outStream = new Speaker({ channels: context.format.numberOfChannels, bitDepth: context.format.bitDepth, sampleRate: context.format.sampleRate }); function play(audioBuffer) { if (!audioBuffer) { return; } var bufferSource = context.createBufferSource(); bufferSource.connect(context.destination); bufferSource.buffer = audioBuffer; bufferSource.loop = false; bufferSource.start(0); } var audioData1 = fs.readFileSync(track1); var audioData2 = fs.readFileSync(track2); var audioBuffer1, audioBuffer2; context.decodeAudioData(audioData1, function(audioBuffer) { audioBuffer1 = audioBuffer; if (audioBuffer1 && audioBuffer2) { playBoth(); } }); context.decodeAudioData(audioData2, function(audioBuffer) { audioBuffer2 = audioBuffer; if (audioBuffer1 && audioBuffer2) { playBoth(); } }); function playBoth() { console.log('playing...'); play(audioBuffer1); play(audioBuffer2); } |
audio quality is very low, with a lot of distortions
根据WebAudio规范(https://webaudio.github.io/web-audio-api/#SummingJunction):
No clipping is applied at the inputs or outputs of the AudioNode to allow a maximum of dynamic range within the audio graph.
现在,如果您正在播放两个音频流,则将它们相加可能会导致超出可接受范围的值,听起来像是-失真。
尝试通过首先将它们通过GainNode用管道传输来降低每个音频流的音量,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function play(audioBuffer) { if (!audioBuffer) { return; } var bufferSource = context.createBufferSource(); var gainNode = context.createGain(); gainNode.gain.value = 0.5 // for instance, find a good value bufferSource.connect(gainNode); gainNode.connect(context.destination); bufferSource.buffer = audioBuffer; bufferSource.loop = false; bufferSource.start(0); } |
另外,您可以使用DynamicsCompressorNode,但是手动设置增益可以让您更好地控制输出。
这并非完全值得回答,但我目前无法发表评论> <
使用js音频api制作的应用程序也遇到了类似的问题,而且相当容易解决的问题是降低音频质量并更改格式。
在您的情况下,我想到的是将位深度和采样频率设置为尽可能低的值,而不影响听众的体验(例如44.1kHz和16位深度)。
您也可以尝试更改格式,从理论上讲,wav应该可以很好地完成CPU密集型工作,但是,还有其他未压缩的格式(例如.aiff)
您可以尝试使用pi的多个核心:
https://nodejs.org/api/cluster.html
尽管这可能会有些复杂,但是如果与其他不相关的进程并行进行音频流处理,则可以尝试在单独的CPU上移动音频。
您可以尝试的(简单)操作是在具有更多RAM的节点上运行,尽管对于您而言,我怀疑是否可以。
但是,最大的问题可能是代码,可悲的是,我对您所使用的模块没有经验,因此可以就此提供真正的建议(因此,为什么我说这不值得回答:p)
您可以从节点2