JavaScript

How I made a synth running in the browser using Web Audio API

This is the story of my three-days quest into understanding what is the Web Audio API and what are its capabilities. During this time I have also experimented with creating an extremely simplified synthesiser using the Web Audio API and p5.js.

The Web Audio API is a high-level JavaScript API for processing and synthesizing audio in web applications started out by the W3C Audio Working Group in 2012. It has now developed into a solid JS interface for building music-specific applications, like drum machines and synthesisers, or complementing modern in-browser game engines.

The Web Audio API involves handling audio operations inside an audio context, and has been designed to allow modular routing. Basic audio operations are performed with audio nodes, which are linked together to form an audio routing graph. […] This modular design provides the flexibility to create complex audio functions with dynamic effects. (Mozilla Developer Webpage)

Here I could be taking time to explain how the basics of Web Audio work, but (thankfully!) other more experienced folks have already had a successful go at that which I would rather not replicate. I recommend following Greg Hovanesyan’s tutorial and Boris Smus’ Getting Started with Web Audio API, as well as the project’s official website if you want to learn more on how to implement Web Audio into your projects.

Here’s how my synth works

The synthesiser I created using Web Audio API

Available here is my modest attempt at building a simple “multi-waveform” synthesiser. It is composed of 3 main groups of elements (excluding other HTML components such as buttons, sliders, or text):

Oscillators, Filters, and LFOs.

First step to creating your own sound with this synth is choosing a waveform among the four available. The frequencies of the two oscillators can be set using the first two sliders. Once you are happy with the pitch you’ve chosen, you can play with the speed of the LFO which is connected to two inverse filters — a low and a high-pass — opening and closing simultaneously following an inaudible sinewave. You can also control the upper boundary of the filters by setting a frequency, which I named Contour, using the slider at the bottom— “opening up” the sound by doing so.

I used p5.js to automate the movements of the sliders, as well as positioning the elements on the page. Basic CSS styling has also been added.

A more precise approach would make use of other Web Audio elements to modify audio parameters. In this case I only needed to test the capabilities of the API. Therefore, I settled on using a simpler approach —p5.

Below is the Javascript code that runs behind the scenes:

https://gist.github.com/francescoimola/227872dd3f3374da323a6d9c71a31e5a

This synth is not playable via your computer keyboard, nor via MIDI. Frequencies cannot be set and parameters cannot be saved. It is only a minuscule example of the power of Web Audio.

It took me three entire days to complete this synth, but one can only imagine what impressive projects could be achieved in Web Audio if more time, and experienced hands, were to be used.

Few examples of things that can be done using Web Audio

Omnitone: JavaScript implementation of an ambisonic decoder that also allows you to binaurally render an ambisonic recording directly on the browser.

[embed]https://googlechrome.github.io/omnitone/#home[/embed]

Babylon Synth: a mini 3D visual interactive experience of Gershon Kingsley’s Popcorn.

[embed]https://googlechrome.github.io/omnitone/#home[/embed]


Source Image: Scott Schiller https://www.flickr.com/photos/schill/6839260527/


Francesco Imola is a London-based musician, weekend photographer, and current Sound Design student at the University of Greenwich.

w. http://francescoimola.com/

tw. https://twitter.com/francescoimola

Deconstructing functions

When thinking of code as a set of instructions is it useful to assign a name to those chunks of instructions. The two fundamental ones (in programming) are called procedures and functions.

Functions and procedures share many similarities — in some programming languages procedures are seen as a special type of functions — but generally speaking, functions return a value, whereas procedures don’t.¹

Functions are self-contained modules of code that accomplish a specific task.² The aim of a function is to “acquire” data, process it, and “return” a result (or value). To streamline and maintain modern code, functions are now usually limited to performing a single task and are kept as short as possible. [To some programmers], the idea that functions should be small is something that is almost considered too sacrosanct to call into question.³

The power of functions resides in their virtually infinite modularity. They allow programmers to shorten code, reusing it instead of rewriting it.² A function can be written once and used over and over again at different points within a programme. It is also possible to call functions from the inside of other functions. Some typical examples of functions would be arithmetic operators like “plus,” “times,” and “square root,” which can be combined with other arithmetic operations to compose expressions.⁴

To announce a function we firstly need to assign this a name (or identity) and declare any argument that it will require. When a function is called the programme “leaves” the current section of code and begins to execute the first line inside the function.² Once inside the function, the code is run from top to bottom. The resulting value is sent back to where the function was called in the code and is used in place of this.

Additionally, functions can be seen as look-up tables that map from a certain symbol, the look-up key, to a value associated with this key.⁴

Most modern programming languages — Javascript is a classic example — often allow for predefined (or built-in) functions to be called. In such languages, a function can be assigned as a value to a variable, or can be passed into arrays (lists) just like any other data type.⁵ Such type of procedures is often employed in functional programming, a language design that mostly relies on functions, rather than variables.

A function eventually represents the simplest machine design. However, completely functional programs can only recreate an ideally logical data in-data out machine, not the one which we usually have to deal with. Every variable that lives inside the workspace of a function is only usable during the execution of the function. Good designs are to be based on a reversible logic — one which a function-only driven programme will not be able to accomplish.

This intuition is at the heart of logic. If repeating the same operation with the same input gives a different output, you know without a doubt that something changed: it isn’t the function you thought it was, it isn’t a simple machine.(Derek Robinson, 2008)

Implementing functions into my coding projects

For the past week I’ve been working on an extremely small and simplistic program that develops on the concept of text and type, and uses functions as main building blocks.

The project is called TEXTBOX. Its aim is to generate an artwork out of the text the user writes in the actual textbox when hitting the submit button. It is inspired by this example — which I have encountered while leaning more about using Input and Buttons on p5.

Javascript code behind TEXTBOX

I’ve called the greet function through the mousePressed action/built-in function in p5. In greet is placed the for loop which generates the copy of the text, and changes its colour and position randomly. Simply reload the page to reset the background to white.

An nice update to this would be adding a refresh button inside the actual webpage, as well as the ability to save the artwork (with different aspect-ratios) as a picture on your computer.

The project can be accessed here https://alpha.editor.p5js.org/full/SJvi1DzrG


References:

  1. BBC Bitesize — GCSE Computer Science — Functions, procedures and modules — Revision 1(2018). Available at: https://www.bbc.co.uk/education/guides/z9hykqt/revision.
  2. Programming — Functions (2018). Available at: https://www.cs.utah.edu/~germain/PPS/Topics/functions.html (Accessed: 19 January 2018).
  3. Sridharan, C. (2018) Small Functions considered Harmful, Medium. Available at: https://medium.com/@copyconstruct/small-functions-considered-harmful-91035d316c29.
  4. Derek Robinson (2008) Software studies by Fuller, M. Cambridge, Mass.: MIT Press.
  5. Goldberg, O. (2017) Javascript and Functional Programming — Pt.2 : First Class Functions, Hacker Noon — Medium. Available at: https://hackernoon.com/javascript-and-functional-programming-pt-2-first-class-functions-4437a1aec217.

Francesco Imola is a London-based musician, weekend photographer, and current Sound Design student at the University of Greenwich.

w. http://francescoimola.com/

tw. https://twitter.com/francescoimola

Online drawing and first steps with p5.js

Take Processing and Javascript, put those in bowl, add some HTML5 and CSS, mix them, and here you have a shiny new tool for creating easy-to-interact shapes, text, video, sound, and a myriad of other online objects.

In an attempt to put onto use the very elementary functions of P5.js that I have learned in the past week, I sat down and built an half-ever-moving drawing formed of text and lines. I was well inspired by Picasso’s minimalist portraiture.

drawingsxdrawings, Francesco Imola

I made use of a Javascript array to initialise the words to be displayed and added 4 Random functions, each one receiving the array as input and outputting the words in a different order, following the frameRate fps to set the speed. The rest of the code consists of the actual drawing of lines and positioning of the text.

It can be viewed here https://francescoimola.github.io/drawingsxdrawings/

The P5.js script used to build all of drawingsxdrawings

Francesco Imola is a London-based musician, weekend photographer, and current Sound Design student at the University of Greenwich.

w. http://francescoimola.com/

tw. https://twitter.com/francescoimola