Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

polyphonic audio playback with node.js on raspberry pi

I've been trying to create polyphonic WAV playback with node.js on raspberry pi 3 running latest raspbian:

  • shelling out to aplay/mpg123/some other program - allows me to only play single sound at once
  • I tried combination of https://github.com/sebpiq/node-web-audio-api and https://github.com/TooTallNate/node-speaker (sample code below) but audio quality is very low, with a lot of distortions

Is there anything I'm missing here? I know I could easily do it in another programming language (I was able to write C++ code with SDL, and Python with pygame), but the question is if it's possible with node.js :)

Here's my current web-audio-api + node-speaker code:

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);
}
like image 507
Szymon Kaliski Avatar asked Sep 14 '16 09:09

Szymon Kaliski


People also ask

CAN node JS play audio?

To play a sound in our Node. js code, we will use an NPM package called (perhaps not surprisingly) play-sound. This package works with a number of different command-line audio players including: mplayer.

Does NodeJS work on Raspberry Pi?

Raspberry Pi is a small, multi-use computer. With Node. js you can do amazing things with your Raspberry Pi.

How do I use Playsound on Raspberry Pi?

The simplest way to play audio on the Raspberry Pi is with wired speakers or headphones. These can be connected to the Raspberry Pi with the onboard headphone jack. From the desktop, make sure to set the Audio output to Analog by right-clicking the sound icon on the menu bar's top right portion.

What is Raspberry Pi audio?

Raspberry Pi does not have a speaker. However, there are several audio output modes that you can connect a speaker to. You can connect Raspberry Pi to a speaker physically with an audio jack or a USB port, or you can connect wirelessly through Bluetooth.


1 Answers

audio quality is very low, with a lot of distortions

According to the WebAudio spec (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.

Now if you're playing two audio streams, it's possible that summing them results in a value that's beyond the acceptable range, which sounds like - distortions.

Try lowering the volume of each audio stream by first piping them through a GainNode as so:

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);
}

Alternatively, you could use a DynamicsCompressorNode, but manually setting the gain gives you more control over the output.

like image 129
Tomáš M. Avatar answered Oct 06 '22 04:10

Tomáš M.