Project showcase
PhaseMod Drone Synth (w/ Arduino Nano & Mozzi)

PhaseMod Drone Synth (w/ Arduino Nano & Mozzi) © MIT

A small noise/drone synth with percussion mode. Made using the Mozzi library and two Arduino Nanos.

  • 4,732 views
  • 9 comments
  • 17 respects

Components and supplies

About this project

This project was made as a thank-you present to a friend of mine for helping me with a repetitive stress injury that flared up really badly late last year.

It's a phase modulation synthesizer with an internal LFO controlling the modulation and an optional internal envelope with controllable decay to turn it into a (pretty janky and bizarre) drum machine. It has two voices (one per Nano) and the following parameters are controllable via the pots for each voice:

  • Carrier frequency
  • Carrier waveform
  • Modulator frequency (in integer multiples of the carrier)
  • Modulator waveform
  • LFO frequency
  • LFO amplitude
  • LFO waveform
  • Decay

Below is a video of my friend trying to figure out what it does (I gave it to him as a surprise without any instructions or explanation).

Code

ThankYou SynthArduino
Not the cleanest code here. Project was thrown together pretty quickly.
/*
Synth for a friend using the amazing Mozzi library by Tim Barrass
 */

#include <MozziGuts.h>
#include <Oscil.h>
#include <Smooth.h>
#include <AutoMap.h>
#include <ADSR.h>

#include <tables/sin256_int8.h>
#include <tables/halfsin256_uint8.h>
#include <tables/waveshape1_softclip_int8.h>
#include <tables/saw256_int8.h>



// VARIABLES
AutoMap kMapCarrierFreq(0,1023,20,440);
AutoMap kMapIntensity(0,1023,700,1);
AutoMap kMapModSpeed(0,1023,10000,0);
AutoMap kMapEnvelopeTimes(0, 1023, 20, 500);

Oscil <256, AUDIO_RATE> carrier;
Oscil <256, AUDIO_RATE> modulator;
Oscil <256, CONTROL_RATE> modDepth;

ADSR <AUDIO_RATE, AUDIO_RATE> envelope;

int attack = 20;
int decay = 20;
bool mode = 0;
bool noteTrigger = 0;
bool noteTrigger2 = 0;

int freqs[3];
byte wfs[3];

int mod_ratio = 1; //frequency of the modulator as an integer multiple of the carrier
long fm_intensity; // carries control info from updateControl to updateAudio

float smoothness = 0.95f;
Smooth <long> aSmoothIntensity(smoothness);


// FUNCTIONS
void setWavetables() {n
  if (wfs[0]==0) {carrier.setTable(SIN256_DATA);}
  else if (wfs[0]==1) {carrier.setTable(HALFSIN256_DATA);}
  else if (wfs[0]==2) {carrier.setTable(SAW256_DATA);}
  else if (wfs[0]==3) {carrier.setTable(WAVESHAPE1_SOFTCLIP_DATA);}

  if (wfs[1]==0) {modulator.setTable(SIN256_DATA);}
  else if (wfs[1]==1) {modulator.setTable(HALFSIN256_DATA);}
  else if (wfs[1]==2) {modulator.setTable(SAW256_DATA);}
  else if (wfs[1]==3) {modulator.setTable(WAVESHAPE1_SOFTCLIP_DATA);}

  if (wfs[2]==0) {modDepth.setTable(SIN256_DATA);}
  else if (wfs[2]==1) {modDepth.setTable(HALFSIN256_DATA);}
  else if (wfs[2]==2) {modDepth.setTable(SAW256_DATA);}
  else if (wfs[2]==3) {modDepth.setTable(WAVESHAPE1_SOFTCLIP_DATA);}
}

void readPins() {
  freqs[0] = mozziAnalogRead(A0);
  freqs[1] = mozziAnalogRead(A1);
  freqs[2] = mozziAnalogRead(A2);
  
  wfs[0] = mozziAnalogRead(A3) >> 8;
  wfs[1] = mozziAnalogRead(A4) >> 8;
  wfs[2] = mozziAnalogRead(A5) >> 8;

  mod_ratio = (mozziAnalogRead(A6) >> 7) + 1;
  decay = mozziAnalogRead(A7);

  mode = digitalRead(4);
  noteTrigger = digitalRead(2);
  noteTrigger2 = digitalRead(3);
}

void setFrequencies() {
    int carrier_freq = kMapCarrierFreq(freqs[0]);
    int mod_freq = carrier_freq * mod_ratio;

    int intensity_calibrated = kMapIntensity(freqs[2]);
    fm_intensity = ((long)intensity_calibrated * (modDepth.next()+128))>>8;

    float mod_speed = (float)kMapModSpeed(freqs[1])/1000;

    carrier.setFreq(carrier_freq);
    modulator.setFreq(mod_freq);
    modDepth.setFreq(mod_speed);    
}

void setAD() {
  envelope.setReleaseTime(kMapEnvelopeTimes(decay));
}



// ################### THE GOODS! #####################

void setup() {
  pinMode(4, INPUT);
  pinMode(3, INPUT);
  pinMode(2, INPUT_PULLUP);
  startMozzi();
  envelope.setLevels(255, 250, 250, 0);
  envelope.setTimes(20, 20, 5000, 20);
}

void updateControl() {
  readPins();
  setWavetables();
  setFrequencies();
  setAD();

  if (noteTrigger == 0 or noteTrigger2 == 1) { envelope.noteOn(); }
  else if (noteTrigger == 1 and noteTrigger2 == 0) { envelope.noteOff(); }
}

int updateAudio() {
  int audio;

  if (mode == 0) {
    long mod = aSmoothIntensity.next(fm_intensity) * modulator.next();
    audio = carrier.phMod(mod);
  }
  else {
    envelope.update();
    long mod = aSmoothIntensity.next(fm_intensity) * modulator.next();
    audio = ((carrier.phMod(mod) * envelope.next()) >> 8);
  }
  return audio << 6; // 14-bit number for HI-FI mode
}

void loop() {
  audioHook();
}

Schematics

Schematic
KiCad file
thankyou_synth_Y5sDahaIOz.sch
Schematic picture
PNG of the schematic
Thankyou synth cng6oqhtf1

Comments

Similar projects you might like

Lo-Fi Arduino Nano Synth Modules

Project in progress by Daniel Sinderson

  • 9,484 views
  • 40 comments
  • 17 respects

Arduino MIDI Arpeggiator

Project tutorial by Dmitry

  • 51,648 views
  • 63 comments
  • 150 respects

Arduino Uno and Mozzi Drum Machine (+dancing head)

Project showcase by Roni Bandini

  • 4,771 views
  • 7 comments
  • 10 respects

Arduino Nano "One Digit" Big LED Clock

Video tutorial by Mirko Pavleski

  • 3,916 views
  • 0 comments
  • 8 respects

Let's Build an SN76489 USB MIDI Synth With Arduino Nano

Project tutorial by tyrkelko

  • 8,237 views
  • 1 comment
  • 9 respects

AR DRONE and 1SHEELD - Discover the world around your drone

Project tutorial by OMEGA D2

  • 46,799 views
  • 15 comments
  • 200 respects
Add projectSign up / Login