An FM Synth for Web (Part 1: The Website)
Tags: webdev, typescript, music, svelte
Published: 2023-03-10 18:45:42

## [Demo Fazeoid here](https://fazeoid.netlify.app/)

## What is Fazeoid?

I designed Fazeoid. [Neonfuz](https://github.com/neonfuz) and I implemented it in Svelte + Typescript.

Fazeoid is a fun web-based synthesizer. [I describe the synthesizer in detail in part 2](https://dev.to/hertz4/an-fm-synth-for-web-part-2-audio-2o5a). In this post, I talk about the technologies that made Fazeoid possible.

## Why make Fazeoid?

Put simply, Fazeoid was made to learn and to show off. It is really amazing what's possible on the modern web.

I would classify Fazeoid under "software nobody asked for", but there is potential. I mean, why not? Writing application UI for web is already common practice, and synthesizers have UI with similar requirements.

The way Fazeoid generates its sound is novel, and by creating this app I was able to test it out easily. By using the Vite bundler, code changes translated to immediate differences in sound and behavior, making for a nice workflow. If you're interested, [Read the source code here](https://github.com/bismuthsoft/fazeoid).

Also, writing the frontend and sound generation code both in typescript allows the visual and audio components of the synth to be integrated with one another, with a huge potential.

## Development Process

Fazeoid started out as a simple idea on paper. We got the basic technology working in the web app, just to make sure it was even possible. Then, we mapped out possible designs in Figma, and finally implemented them gradually.

Fazeoid was developed as a team of two, using Git of course, and Netlify CI. Mostly, features were developed on a separate branch, and then later integrated using a Pull Request.

Github has a beta feature called "Projects", which has a variable-view interface integrated with the issue tracker. The main view we used was the Kanban-style view. We also planned "sprints", where I acted mostly as the "product owner". It wasn't really what you'd expect on a pro team, but the experience was valuable.

![The Kanban used to create Fazeoid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4yxvevj9ej7fl1u5eels.png)

Also, with help from Netlify, we were able to quickly deploy the app, as well as get previews of our features branches that are publicly available, so that things can be easily tested.

## Svelte

We chose Svelte for this project because of the tight integration of state and UI required, which Svelte excels at through its magical bindings. Placing code within HTML, rather than HTML within code, makes it feel a bit like writing an enhanced version of Vanilla Javascript. After having written quite a bit of React, Svelte felt very fresh, like breaking out of old chains. That didn't last, though...

Svelte made it very easy to get going, but we often times questioned whether React or Solid would be a better choice. Svelte errors are often inexplicable, sometimes even dumping code even into the UI itself. When Svelte scales, it often becomes ambiguous where to store the state, or where to track it. Svelte also doesn't allow creating multiple components within the same file, which was annoying at times.

Being a single static page, Svelte didn't limit us at all in terms of functionality, and we didn't have to use Sveltekit. Overall, I would use Svelte again for a project at small scale, but I would not use it to create a large website.

## The DJ knob

Fazeoid has an ergonomic interface using a [custom knob element](https://svelte-dj-knob.netlify.app/).

Svelte-dj-knob is a custom component that captures the cursor to make it easy to tweak parameters just by clicking and dragging. This was an essential part of Fazeoid. It also works on touchscreens, and is super responsive. The visual design of the knobs is flexible, but for Fazeoid I designed the knob in Inkscape, then imported the SVG into Svelte, simplified the SVG, and added animation to it using transforms. ![A DJ Knob](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4grihjx6km2gi81ztzpz.png) If you want to use this knob in your own project, feel free to use the npm package svelte-dj-knob.

In the case that Svelte becomes a real way to build synthesizer or effect UIs, this and other elements would be the starting point for a whole toolkit of elements.

And why not use this element on a mundane website? I think that the web should be fun, not boring, and that user experiences should feel more like video games and less like filling out paperwork.

## AudioWorklet

Fazeoid would not be possible without AudioWorklet. Before AudioWorklet, software synths in javascript were severely limited. Now, the possibilities are endless.

AudioWorklet is an awesome new web API that enables web applications to generate their own sound, and this has fueled a lot of cool homegrown audio projects on the web. The sound synthesis for Fazeoid is written entirely in Typescript, using the AudioWorklet more as a self-contained entity. Though the AudioWorklet API has a lot of abstractions such as [BiquadFilterNode](https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode) which could be used to extend this synthesizer, I kept its functionality contained for the sake of portability.

It is definitely a bit odd to write sound code in Typescript, but it works great. The DAW Reaper already allows plugins to be written in JS, with the advantage of being able to interpret the code on the fly -- albeit with a performance hit compared to C and others. Though, as I have found, Fazeoid's performance is good enough for my phone and my PC, and that's without much optimization. If you learn how Fazeoid works, this is especially surprising.

Configuring Vite to build this worklet separately and integrate it into the project was a bit of a headache, but we arrived at a simple solution. Neonfuz will eventually write a blog post explaining the process.

One odd aspect of this worklet is that it is truly running on a second thread compared to the main program, and has to communicate using messages. Javascript may be single-threaded, but AudioWorklet is running more than one Javascript, and they can't just freely interoperate. Sadly, these messages can't be passed in a type-checked way, as far as I know.

## Oscilloscopes

Because of the fact that the audio worklet and frontend code are in the same language and source file, it was easy to make wave views by calling functions within the worklet synth. This gives the user satisfying visual feedback when turning knobs, in addition to the immediate audio feedback even on currently playing notes.

The oscilloscopes are not canvases. They were made by generating SVG paths on the fly, with smooth, scalable, and responsive results.

## Conclusion

Despite the headaches, I love the modern web. I love what it is becoming. It's a playground full of potential. Not only can I create a fully featured synthesizer, but I can put it in a website that works on any random device, even someone's phone, without installing anything. It will even be possible to add MIDI to this synth, making it a more complete project -- though I think I would prefer to port it instead so that it can be used on conventional platforms by actual musicians.

I love Fazeoid, and I plan on extending it based on my time and on people's interest in the project. I hope that you love it too.