Tutorial: Build a responsive Web Audio Synthesizer with Nexus UI

Top image for websynth tutorial articleSynthesizers plays a huge role in modern music making. It plays lead for most electronic dance music and it´s used for texture and effects in many rock songs.

 

With Web Audio API you can make your own synthesizer for the web and play your own musical masterpieces.
In this tutorial I will show you how you can make your own web-based synthesizer with the help of Web Audio API, JavaScript, html and CSS. The design will be responsive so the web synthesizer looks good for both desktop and smart phone.

 

For the user interface we will be using Nexus UI which is a API specifically designed for Web Audio based applications.

 

If you want to read about specific details for Nexus UI you can visit nexusosc.com, or if you want to know more about Web Audio you can visit W3C – Web Audio API.

 

Setting up HTML base and download NexusUI.js

First, open your favorite code editor whether it is notepad++, sublime text or brackets. Personally I prefer to use brackets.

Then you need to create a basic html structure and save it as a html-file.

Basic html structure

 

In my example I have set up a basic web page with a header with a <h1> title, a section where all the synthesizer controls will go and a footer.
The most important part here is to add <meta name=”viewport” content=”width=device-width, initial-scale=1.0″> in the head-tag which will make it easier to design the synthesizer for smart phones.

 

Next go to nexusosc.com and download NexusUI.js and put the js-file in your project folder. Add it to your head tag with <script type=”text/javascript” src=”js/nexusUI.js”></script> to make the API usable.

Now that Nexus UI is active let´s add a musical keyboard for the synthesizer with <canvas nx=”keyboard”></canvas>.
In this tutorial I am thinking we will have two oscillators for our synth which will be producing sounds, so lets add two basic html Select tags with Options for some oscillator types. In my case I added support for square, sawtooth and triangle waves.

 

To give the generated sounds some character the user of the synthesizer should be able to detune the oscillators, therefore lets add two Nexus UI dial controllers with two <canvas nx=”dial”></canvas>.

 

Basic html structure with Nexus UI added

 

Above you can see how my code looks this far. As you can see I have also added some div tags, a couple of id´s and onchange events to the code – this is to prepare it for the coming JavaScript and CSS.

 

JavaScript for Web Audio API and Nexus UI

Now to get to the meat and potatoes of this synth, the code which will make it run.

First create a new blank js-file and save it as synth.js (or something similar).

In the js-file add the following variables:
var audioCtx = new(window.AudioContext || window.webkitAudioContext)();
var gainNode = audioCtx.createGain();
This is needed to  make Web Audio API work.

Then add var oscillators = [];  to prepare oscillator arrays – this will be used later.
Add gainNode.gain.value = 0.3; to lower the volume output somewhat. This is not absolutely needed but makes the synthesizer sound more comfortable for headphone wearers.

 

Next we will add the following code:

var keyOctave;
var mediaScreen = window.matchMedia(“(min-width: 600px)”);
if (mediaScreen.matches) {
keyOctave = 2;
} else {
keyOctave = 1;
};

This is a trick which makes the keyboard octave design responsive for smart phone users. This creates a variable which we will use to tell the Synthesizer to show a two octave keyboard for desktop users and a single octave keyboard for smart phone users.

To make use of the oscillator type selectors we created earlier we need to add a couple of variables and functions:

var oscType1 = document.getElementById(“oscillator1Type”).value;
var oscType2 = document.getElementById(“oscillator2Type”).value;
function selectOsc1(osc1) {
    oscType1 = osc1;
};
function selectOsc2(osc2) {
    oscType2 = osc2;
};

This code will get the oscillator values based on what the user has chosen in the html selector options.

 

Now we need work with Nexus UI to make use of the musical keyboard and interface. Begin by adding nx.onload = function () { } to start Nexus UI in your code. Every call to Nexus UI needs to be done inside this nx.onload function.

 

To set up the specifications for detune dials insert:

dial1.min = -20;
dial1.max = 20;
dial1.responsivity = 0.025;

dial2.min = -20;
dial2.max = 20;
dial2.responsivity = 0.025;

Just by naming the dials dial1 and dial2 Nexus UI will automatically understand which dial you are referring to.

 

To set layout colors for the entire Nexus UI add:

nx.colorize(“accent”, “#347”);
nx.colorize(“border”, “#333”);
nx.colorize(“fill”, “#fff”);

 

Then to make use of the musical keyboard add the following code:

keyboard1.octaves = keyOctave;
keyboard1.init();
keyboard1.on(‘*’, function (data) {

        if (data.on > 0) {
            var oscillator1 = audioCtx.createOscillator();
            oscillator1.type = oscType1;
            oscillator1.frequency.value = nx.mtof(data.note);
            oscillator1.detune.value = dial1.val.value;

            var oscillator2 = audioCtx.createOscillator();
            oscillator2.type = oscType2;
            oscillator2.frequency.value = nx.mtof(data.note);
            oscillator2.detune.value = dial2.val.value;

            oscillator1.connect(gainNode);
            oscillator2.connect(gainNode);
            gainNode.connect(audioCtx.destination);

            oscillators[nx.mtof(data.note)] = [oscillator1, oscillator2];

            oscillator1.start(audioCtx.currentTime);
            oscillator2.start(audioCtx.currentTime);
        } else {
            oscillators[nx.mtof(data.note)].forEach(function (oscillator) {
                oscillator.stop(audioCtx.currentTime);
            });
        }
    });

With an if else statement we tell the keyboard what will happen when a key is pressed down (data.on > 0) and when you release a button. Every time a key is pressed two oscillators are created (oscillator 1 and oscillator 2) which generate sound. The sound is created with information about oscillator types, frequency value, and detune values. The oscillators are then connected to the gainNode and put in the oscillators array. Lastly the actual sounds starts with the code: oscillator1.start(audioCtx.currentTime);
oscillator2.start(audioCtx.currentTime);

In the else part the you stop the sound with:
oscillators[nx.mtof(data.note)].forEach(function (oscillator) {oscillator.stop(audioCtx.currentTime);});.

 

If everything is set up right your code should look similar to the following example:

Javascript code for Nexus UI Web Synth

 

To make use of this code you need to connect your js-file to your project by adding it at the bottom of your html-file with a script tag (in my case I use the following tag <script type=”text/javascript” src=”js/websynth.js”></script> ).

 

CSS and responsive design

To make your synth look pretty you need to design it with CSS.
Now, cosmetic design is very much a personal preference, so I feel weird telling you what colors or structure use. Instead I´m just going to show you what my CSS looks like. That way you can start from there and create your own design.

CSS code for web synth, part1

CSS code for web synth, part2

 

This CSS sets the design for the desktop version of the synthesizer. The interesting part comes next when we need to make the synthesizer responsive.

Responsive CSS Web Synth

There are different ways to set up a responsive site, in this tutorial I will keep it very basic with only one breaking point.
Often you use percentage values instead of px values when you create responsive design but when using Nexus UI we need to mix both percentages and px values because of how it works.
The width is set to 360px because it works pretty ok and looks good on both iPhone and android devices. As you can see many divs use percentage values, this is to get the order of the divs aligned right where I want them to be.
The width for Nexus UI id´s,  like keyboard1, dial1 and dial2, are set to specific px values because they look better in the design this way. I could use percentages but it will be a hassle because of how Nexus UI works.

 

Result

When you have finished your CSS and connected it to your html-file you should be done and have a working web-based synthesizer which you can control via the mouse on your computer or with a smart phone touch screen. You can see how my Synthesizer turned out below:

 

Websynth on desktop

Websynth on desktop

 

Websynth on Android

Websynth on android device

 

If you want to try the synthesizer click here.

 

If you want to see my entire code you can download this zip file with the websynth.