Art & Technology    [ BLOG ]

Electrosmith Daisy Seed to make Custom Synth Modules
Date created: April 10, 2024

Introduction

The Center for Concrete and Abstract Machines (CCAM) has invited me to be on their Synthesis Team for the audio software development of three DIY synths that will be showcased in a workshop called FUTURHYTM MACHINES: Chicago House Music. Each synth will have their own name and sonic output:

Each synth circuit uses a custom PCB circuit with potentiometers and buttons for ease of control of parameters. It will also have:

A major goal is for ease of interaction between these synths to create a wonderful sonic experience.


Max/MSP gen~ and the Electrosmith Daisy Seed

The heart of this synth is the Electrosmith Daisy Seed. The Kickstarter for this board started in 2020 and has already become a popular choice for audio programmers that want to make their programs come to life by taking a more physical and portable form. This is a perfect board for sound artists wanting to make sound installations, and for performers/musicians wanting to make custom synths for their Eurorack setups. Before this board, the Teensy was a popular choice.

There are several ways to write an audio program to flash into the Daisy, for example you can use Arduino or Pure Data, but I will use the Max/MSP gen~ environment, which uses lower-level objects allowing the ability to compile a patch into code that the Daisy can understand. The Max package for flashing the board is called Oopsy.

For more options and info about how to get started check out this wiki page: https://github.com/electro-smith/DaisyWiki/wiki


Generating Sound & Organizing Time

Graham Wakefield and Gregory Taylor’s book “Generating Sound and Organizing Time” is a great resource for learning gen~. I will be pulling some useful images from there to demonstrate some of the concepts. I will refer it as the GO book from now on.

Learn more about it here: https://cycling74.com/books/go


The Synth Modules

Chronos/Khairos

Description:

Button Control:

Potentiometer Control:

Audio Synthesis:

Pocket Calculater

Inspired by Erica’s Synth Desktop Bassline.

Description:

Potentiometer Control:

Building a Sequencer

The “Hello World” for any sequencer construction is to have a single event triggered repeatedly by a clock.

Phasor

The way to make a clock in Max gen~ is by using a [phasor] object. The number following phasor is the frequency parameter.

Creating a [phasor 1] will create a ramp going at a rate of 1Hz, going from a value of 0.0 to 1.0 in one second.

The live.scope~ object defaults to plotting 44.1k samples.

This plot better shows what the X and Y axes represent.

Trigger (click)

What we want is for this ramp to trigger an event when it resets its cycle. In the analog synthesis world, a trigger is a very short pulse (1-2ms) that is used to activate something, in Max/MSP gen~ a click is the closest equivalent. A click is simply an output of 1.0 for one sample.

In the GO book, this figure is provided to demonstrate what it should look like, describing the clicks as ticks.

Conveniently, the GO book comes with an abstraction called go.ramp2trig that creates a trigger (click) when the ramp resets.

gen~ patch with a 1000Hz phasor.

Plot showing the phasor (blue) and the trigger (orange)

Event

The next step is to have that trigger activate a sound event. As a simple example we can trigger an envelope on a running oscillator.

A running oscillator of 220Hz.

We pass the [cycle] through a [*] operator because the right inlet will be used for the envelope signal. This signal will go from 0.0 to 1.0 in a certain amount of time, starting when it receives a trigger.

A very simple way is by using a combination of [counter] and [%].

Using [counter] and [%].

Plot of envelope.

In this case, a trigger is used to repeatedly turn on the envelope, AND turn off.

The [counter] operator does exactly what it is called, it counts how many triggers it receives until is is told to reset. In reality, it is adding the value on the left most inlet every sample. Whenever it is 0, it adds 0, and when it is 1, it adds 1.

[counter]:

Accumulates and outputs a stored count, similarly to Max’s counter object, but triggered at sample-rate. The amount to accumulate per sample is set by the first input (incr). The count can be reset by a non-zero value in the second input (reset). The third inlet (max) sets a maximum value; the counter will wrap if it reaches this value. However if the maximum value is set to 0 (the default), the counter will assume no limit and count indefinitely. The first outlet outputs the current count, the second outlet outputs 1 when the count wraps at the maximum and zero otherwise, and the third outlet outputs the number of wraps (the carry count).

A plot of [counter] with triggers.

We can start to connect the envelope now to hear the result, but there is a problem. The immediate change from 0.0 to 1.0 creates clicks which is not ideal.

Hooking up the envelope to the oscillator.

A nice way to ease the transition is by using [slide].

Use the slide operator for envelope following and lowpass filtering. Related to the MSP slide~ object.

The [slide] operator takes two parameters.

  1. Slide up value (in samples)
  2. Slide down value (in samples)

gen~ patch with [slide] added.

The new shape of the envelope.

From top to bottom: Sound, Trigger, Envelope

The result in a much cleaner sound. This completes the barebones of a sequencer. By adding more sounds triggered at different times we can create interesting additive results.

Adding more sounds triggering at different times can lead to interesting results.

go.simple.kick, go.simple.snare, go.simple.hihat

For the sake of getting right to the chase of making a drum sequencer, I will be using the provided GO examples that synthesize a snare drum, kick, and hihat. These abstractions take a trigger to activate the sound.


Adding BPM

To add BPM, we can create a [param] called BPM, and divide it by 60.

Adding BPM.

BPM param in the attrui object in Max.

A BPM of 60 will give a frequency of 1Hz, a BPM of 120 will give a frequency of 2Hz, etc.

Steps and Hits

To create steps from a ramp, we can multiply a ramp by the number of steps we want, and then using the [floor] operator.

Multiplying the ramp and using [floor] to create steps.

Plot of the stepped output.

Here is the plot with the multiplied phasor:

Plot including the multiplied phasor and stepped output.

Note that the count of the orange plot starts at 0 and goes up to 7. To quantize them to be between 0 and 1, we can just divide by 8 again.

Quantizing the ramp and steps to be between 0.0 and 1.0.

Creating a Topographic Map

This module is a topographic drum sequencer, meaning that it derives its drum sequences based on a map.