Raw stereo audio to mono channel in JS

Image for post
Image for post

Lately I’ve stumbled upon an interesting engineering problem that may be useful to some of you.

I the creator and owner of two Discord bots that utilize speech recognition technology to perform certain actions. There are especially useful for hearing impaired and deaf people, to still communicate with their friends using Discord.

The first bot is just a framework that transcribes speech to text and posts it in the channel: https://github.com/healzer/DiscordEarsBot
The second bot is a music player that listens to voice commands to play songs, playlists, pause, skip, shuffle, etc.: https://github.com/healzer/DiscordSpeechBot

The problem I recently faced was due to audio conversion. Each user that speaks in Discord is treated as a separate stream. And this audio stream is raw binary data (signed 16 bit, 48khz, stereo/two-channel) also known as PCM data. But the free Speech-to-Text service that we use only accepts mono (single) channel audio data.

Initially I used the sox dependency to convert and manipulate the audio data. But this was a pain in the butt, because many of our users couldn't get sox correctly installed on their machine. Unfortunately I haven't found any other npm or javascript package, so it was time to do it myself.

A quick Google search was needed to understand the raw audio format. In my case we are dealing with signed 16 bit data and two channels. This means that each audio sample consists of 16 bits (= 2 bytes), but also that the first 2 bytes are left audio data, and the following 2 bytes are right audio data.

To convert two channels into a single channel we have to decide how we are going to approach this, because left and right may differ. However a regular microphone input does not distinguish left from right, meaning that left data should be the same as the right data. When you analyze the audio wave form, you will see that left waves are the same as the right waves. This simplifies our life, we can drop either left or right to get a mono audio file.

// stereo to mono channel
function convert_audio(infile, outfile) {
try {
// read stereo audio file into signed 16 array
const data = new Int16Array(fs.readFileSync(infile))

Written by

Become a rockstar programmer and try to reach genius status on codr https://nevolin.be/codr/

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store