My stab at an Arduino Synth

http://narbotic.net/?p=95

It's quite limited at this point, but hey - it's my first project. :D The code is pretty hacked together bits from other sketches, and I had to 'cheat' a bit by using a little Lowpass filter. see source for more detail

I'd love to hear any feedback if anyone has any. Thanks!

wow. i'm quite impressed by the sound you're getting. do you have sound sample without the low pass? i did some arduino sound experiments using a piezo speaker, but that wasn't much thrilling...

i'd like to create a simple bass synth with a warm bassy sound. i think your results can motivate me again. i'd really be interested in more sound samples.

did you think of using midi as input, or do you want to be an one-piece instrument? i did not have a look into your code yet, but i think if you are using the built-in PWM to generate the tones, Midi should be no big deal. i'm currently finishing a midi drum interface using arduino and am quite fascinated by the idea of being able to design and create interchangeable in- and output devices using arduino and midi.

kuk

here's that dry sample: http://narbotic.net/audio/ArduinoSynth_alpha_dry.mp3

not so pretty. It's not made with the PWM function actually. (not sure how you'd get that to do different frequencies) It's made using the "freqout" function, found here: http://www.arduino.cc/playground/Main/Freqout

As far as MIDI goes - It would be very cool to add it in. I understand how to implement midi out, but midi in is a bit of a mystery to me at this point.

I was envisioning a bass synth as well actually - working on a lil drum machine right now.

Thank you for the dry sample. the low pass really is a good thing. i didn't know it was that simple to add. did you you yet experiment with the capacitors values? you can simply add an euqualizer with a variable resistor before the capacitor!

i finally managed to built the smallest (yet quite powerful) possible amplifier yesterday, using a single darlingtion transistor (tip120) and 2 resistors. it was quite hard to figure out the right resistor values, but when they were set it was great fun to add and remove additional capacitors as their impact on the sound was quite big.

your absolutely right, concerning the PWM. it's not possible to generate tone frequencies using PWM. but it might be difficult using frequout together with midi-in. i think creating the frequencies is a very time-critical task. you'd have to be able to read the serial port in between the phases to get and interpret the midi messages... but i f you want to try i could help you with the general "midi-in" circuit and code. it's alpha, but does work reliably for me.

another idea would be to create the frequencies in a seperate circuit - that is controllable by PWM - to be able to use arduinos computing capabilities for more interesting stuff than switching one pin on and off. i'm not an electronics genius but i guess this should be possible. the second advantage would be to be able to mix multiple frquencies as we are not limited to one PWM.

best, kuk

Thank you for the dry sample. the low pass really is a good thing. i didn’t know it was that simple to add. did you you yet experiment with the capacitors values? you can simply add an euqualizer with a variable resistor before the capacitor!

I did mess with the caps a bit, but found the results . . . ‘uneven’ sounding?
By equalizer do you mean a seperate equalizer circuit with 3-band control? So then I’d dial in a setting on the EQ and then adjust the varistor accordingly? interesting!

i finally managed to built the smallest (yet quite powerful) possible amplifier yesterday, using a single darlingtion transistor (tip120) and 2 resistors. it was quite hard to figure out the right resistor values, but when they were set it was great fun to add and remove additional capacitors as their impact on the sound was quite big.

This too sounds mega-interesting, mind sharing a bit more info? (ie - res values?)

your absolutely right, concerning the PWM. it’s not possible to generate tone frequencies using PWM. but it might be difficult using frequout together with midi-in. i think creating the frequencies is a very time-critical task. you’d have to be able to read the serial port in between the phases to get and interpret the midi messages… but i f you want to try i could help you with the general “midi-in” circuit and code. it’s alpha, but does work reliably for me.

Yes I was thinking the same regarding serial in + freqout. Freqout seems to account for the processing ‘overhead’ - adding midi may require a new value.

another idea would be to create the frequencies in a seperate circuit - that is controllable by PWM - to be able to use arduinos computing capabilities for more interesting stuff than switching one pin on and off. i’m not an electronics genius but i guess this should be possible. the second advantage would be to be able to mix multiple frquencies as we are not limited to one PWM.

This sounds like CV, control voltage - the old standard for synthesizer inputs. Now if we could use Arduino to convert midi-in to CV compatible PWM out, we would have the simplest MIDI2CV converter ever! I’ve been considering building this one:
http://www.musicfromouterspace.com/analogsynth/midi2cv.htm
but of course I’d much rather explore the arduino option :wink:

Mind sharing a schematic for your synth ? I’m not a musician or anything like that but I just love the sounds from your sample and would love to try this.

sure, they keys just need to be switches that connect each input pin to ground, like so:

ARDUINO PINS: 1 2 3 4 5 6 7 8 9 10 12 13 | | | | | | | | | | | | | | | | | | | | | | | | \ \ \ \ \ \ \ \ \ \ \ \ | | | | | | | | | | | | [u]| | | | | | | | | | | | GND[/u]

The pitch transpose pot: _______Analog Pin 0 | V +5v/\/\/____+5V 10K

then pin 11(output) does a little low pass RC filter:

11 | | 1M resistors [u]|[/u]/\/\/_/\/\/_______+SOUND OUT (ground audio jack as well) | | [u]|[/u] [u] |[/u] T T .1uF caps | | GND GND

man, why do I love ascii schematics so much?

you can find some other info here: http://narbotic.net/?p=95

hi,

i posted the midi in code here http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1187962258/0 i actually wanted to post it to the playground, but wikis seem to dislike me.

the code should be really easy to adapt for PWM output.

best, kuk

;D

You are a kind soul, thanks!

CORRECTION - The pot wiring should have one pin to ground like so:

_______Analog Pin 0 | V +5v/\/\/____GND 10K

you're welcome.

do you know about a simple VCO yet? i'd really appreciate a solution that is 0-5 volts controllable. the less components the better. bread board friendly!

concerning my 1-transistor-amp: it works, but i think i'm doing something seriously wrong. i think there is supposed to be a capacitor in series before the speaker. I didn't mind for my tests, but i think i have a constant currentflow through my speakers, which is not ideal. it'll take me some reading(and probably shopping) to finish a design. i keep you updated.

!

kuk: here's a VCO circuit that's fairly simple but musically useful: http://www.uni-bonn.de/~uzs159/vco4069.html

if you're interested in a DIY bass synth that's based around an AVR, you might check out http://ladyada.net/make/x0xb0x/index.html

thanks, that looks interesting. i like the x0xb0x project a lot. still they put a lot of afford in remaking a tb303 not keeping the design simple. it's not that i'm lazy, i just want to start at a point where i know each of the components and know what they do.

do you have any experience in using a 555 circuit as a VCO? i think the circuit would be super easy. i'm a little unsure about the bandwidth and accuracy though. i think i will give it a try as soon as i find the time. unfortunately not in the next couple of days.

best, kuk

Check this pdf for simple 555 schematics:

BTW - Kuk I agree with you about the xoxbox. It's so encrusted with complexity it kind of loses the thrill of building the thing yourself. I played with it a bit a local event recently and it was quite sturdy and professional but a little too 'stiff' for my liking.

Hey narbotic

Im trying to modify your code so I can have a bunch of bend sensors control the frequency and the timing so I get random sound based on the sensor but I didnt have any success. I can easily do that by PWM but that doesnt make any interesting sound. Anyways Im gonna include my code for one sensor…If you or anyone can look at it and tell me whats wrong with it Ill appreciate it. again Im not looking for any particular note…Im interested in the noise that it can randomly generate.

#include <math.h> // requires an Atmega168 chip
#define outpin 4
int val1;
int speakerOut = 4;
int sensor1 = 1;
int freq,t;

void setup() {
Serial.begin(9600);
pinMode (speakerOut, OUTPUT);
}

void loop(){
val1 = analogRead(sensor1);
freqout((int)val1, t);
delay(10);
}

void freqout(int freq, int t)
{

int hperiod; //calculate 1/2 period in us
val1 = 440;
hperiod = 500000 / freq;
Serial.println(freq);
Serial.println(hperiod);
long cycles, i;
cycles = ((long)freq * (long)t) / 1000; // calculate cycles
for (i=0; i<= cycles; i++){ // play note for t ms

digitalWrite(speakerOut, HIGH);
delayMicroseconds(hperiod);
digitalWrite(speakerOut, LOW);
delayMicroseconds(hperiod); // - 1 to make up for fractional microsecond in digitaWrite overhead
}
}

Here’s my synth code.
Sorry there’s not more comments.

It has a bunch of pots hooked up to A/D
and an encoder (to change programs - on pins 2 & ??

I have an R2R (4 bit) ladder on board, but haven’t tried it out yet - it needs some serious pin rearranging to get the R2R on better pins for bitmath manipulation.

// Synth code by Paul Badger   2007
#include <math.h>

#define outpin 9 // high order output

//analog inputs
#define pitchPot 5
#define modPot  4  
#define speedPot 1
#define phasePot 2
#define jukePot  3

#define stopPin 5

#define LEDbit0 10
#define LEDbit1 11
#define LEDbit2 12
#define LEDbit3 13

int randomWalkLowRange;
int randomWalkHighRange;



int val, runlevel; 
volatile int encoder0PinA = 2;
volatile int encoder0PinB = 4;
volatile unsigned int encoder0Pos = 0;
int n = LOW;

int ptime, range, strt, inc;
int   k,  x, dur, freq, t,; 
int i, j;
int sens, adder;

float ps, fpitch;         // variable for pow pitchShift routine

float noteval;
//note values
float A     = 14080;
float AS    = 14917.2;
float B     = 15804.3;
float C     = 16744;
float CS    = 17739.7;
float D     = 18794.5;
float DS    = 19912.1;
float E     = 21096.2;
float F     = 22350.6;
float FS    = 23679.6;
float G     = 25087.7;
float GS    = 26579.5;
float A2    = 28160;
float A2S   = 29834.5;
float B2    = 31608.5;
float C2    = 33488.1;
float C2S   = 35479.4;
float D2    = 37589.1;
float D2S   = 39824.3;
float E2    = 42192.3;
float F2    = 44701.2;
float F2S   = 47359.3;
float G2    = 50175.4;
float G2S   = 53159;
float A3    = 56320;
//rhythm values
int wh = 1024;
int h  = 512;
int dq = 448;
int q = 256;
int qt = 170;
int de = 192;
int e = 128;
int et = 85;
int dsx = 96;
int sx = 64;
int thx = 32;



float majScale[] = {
  A,  B,  CS,  D,  E,  FS,  GS,  A2,   B2,  C2S,  D2,  E2,  F2S,  G2S,  A3};
  float minScale[] = {
  A,  B,  C,  D,  E,  F,  GS,  A2,   B2,  C2,  D2,  E2,  F2,  G2S,  A3};
float creme[] =  {
  A,  CS,  D, CS,  D,  E,  CS,  D,   CS,  B,   A};
float cremeDur[] = {
  q,  q,  qt, qt,  qt,  q,  q,  qt,   qt, qt,  q};

void setup() { 
  pinMode(outpin, OUTPUT); 
  Serial.begin(9600);

  pinMode(LEDbit0, OUTPUT); 
  pinMode(LEDbit1, OUTPUT); 
  pinMode(LEDbit2, OUTPUT); 
  pinMode(LEDbit3, OUTPUT); 

  pinMode(stopPin, INPUT); 
  digitalWrite(stopPin, HIGH);   // turn on pullups

  pinMode(encoder0PinA, INPUT); 
  digitalWrite(encoder0PinA, HIGH);   // turn on pullups
  pinMode(encoder0PinB, INPUT); 
  digitalWrite(encoder0PinB, HIGH);   // turn on pullups

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.println("start");

  pinMode(outpin, INPUT); // turn off audio out
} 


void loop(){ 


  runlevel = encoder0Pos;
  switch (runlevel){
  case 0:

  case 1:
    doJoker1();
    break;
  case 2:
    doScale2();
    break;
  case 3:
    doArp3();
    break;
  case 4:
    doCreme4();
    break;
  case 5:
    doCreme5();
    break;
    case 6:
    doScale6();
    break;
   
  }
}

//*******************************************************
void doJoker1(){
  sens = analogRead(pitchPot);
  //sens =500;  // hardwire for testing
  adder = max((sens/5),1);

  for (x=sens; x<=(sens + (analogRead(speedPot) * 5)) ; x+=analogRead(jukePot)){    
    if ( digitalRead(stopPin) == 0){
      break;
    }                     
    noteval = x;    // transpose scale up 12 tones - pow function generates transpostion
    dur = 100;
    freqout((int)noteval, sens/47);

    // delay(10);
  }
  delay(analogRead(modPot));
} 
// endJoker1 ****************************************************
/*void arp2(){
 sens = analogRead(pitchPot);
 range = abs(512 - sens) * 4.0;
 strt =  sens * 1;
 inc=abs(512 - sens);
 if (inc == 0){
 inc = 1;
 } 
 
 for (x=strt; ( x > (strt / 4)) && (x < (inc * 30)); x* = (1 + ((sens - 512) / 1023.00))){                      
 noteval = x;    // transpose scale up 12 tones - pow function generates transpostion
 dur = 100;
 freqout((int)noteval, inc);
 
 //   if ((abs(sens - analogRead(0))) > 2){ break;}
 }
 delay(analogRead(modPot); 
 }  */

// end  ***************************************************

void doScale2(){ 
  ps = ((float)analogRead(jukePot)) * 24.0 / 1023.0;         // choose new transpose interval every loop
  for(x= 0; x<=15; x++){  
    if ( digitalRead(stopPin) == 0){
      break;
    }                   
    noteval = (majScale[x] / (float)(analogRead(pitchPot))) * pow(2,ps);    // transpose scale up 12 tones - pow function generates transpostion
    dur = analogRead(speedPot);
    freqout((int)noteval, dur);

    delay(analogRead(modPot));
  }
}

/****************************************************/

void doArp3(){ 
  Serial.println("arp");

  fpitch = (float)analogRead(pitchPot) / 64;
  Serial.print("fpitch = ");
  Serial.println(fpitch, DEC);
  if (fpitch == 0){
    fpitch = 1;
  }
  strt = pow(2, fpitch);
  Serial.print("strt = ");
  Serial.println(strt, DEC);

  for(x=strt; x<= strt * 4; strt = (strt * ( 1 + ((float)analogRead(jukePot)/1023)))){  
    if ( digitalRead(stopPin) == 0){
      break;
    }                   
    dur = analogRead(speedPot);
    freqout(strt, dur);
    delay(analogRead(modPot));
  }
} 
/****************************************************/
void doCreme4(){
  randomWalkLowRange = 0;
  randomWalkHighRange = 10;

  i = randomWalk(analogRead(speedPot) / 32);
  noteval = creme[i] / ((float)analogRead(pitchPot));
  dur = ((cremeDur[i] * (float)analogRead(jukePot)) / 64.0);
  freqout(noteval, dur);
  delay(analogRead(modPot));

Hi Paul;

I looked at your synth code but it does not compile as listed. It appears to me that in several places you call functions which are not there. Could you elucidate on this listing a little?

Sorry, There seems to be a nasty glitch in the forum software that reacts to comment lines in code or something Funny behavior. Either there's a limit to the size you can paste into the editor or something else is reacting to (comments maybe) something in my code.

I started an "Arduino Synth" page on the playground - find the code there.

http://www.arduino.cc/playground/Main/ArduinoSynth

Not a lot of action in this thread. What a shame. I just left this comment at http://narbotic.net.

I get loads of ideas that will take ages to implement (considering my 2-week arduino ownership) , you may want to cooperate? I just saw your sketch.

Here’s your oscillator:
for (i=0; i<= cycles; i++){ // play note for t ms
digitalWrite(speakerOut, HIGH);
delayMicroseconds(hperiod);
digitalWrite(speakerOut, LOW);
delayMicroseconds(hperiod - 1);

On the fly PWM implementation idea: Declare PulsWidth parameter
Shorten the HIGH period , lengthen the LOW period by (PulsWidth)
Have PulsWidth read from analogPin
Make PulsWidth LFO from “Fading” sketch: http://www.arduino.cc/en/Tutorial/Fading

There’s a proper synth parameter for you. If you have more analogIn’s available (or select DigitalIn switches) you can combine Pulswidth parameters, so PulsWidth will be: PulsWidth read from analogPin + LFO derived value + LFO speed ( by varying increment/deminish amount at “Fading” portion).

Now if someone could apply this to the enigmatic pitch determenation scheme we can have pitchbend and vibrato…

A first seed on a “Waveform generator” will be posted elsewhere, as this is no longer appropriate for the “Exhibition” section.

I do hope to make this a joint project, my sketch making so far is minimal to say the least.