Arduino Forum

Community => Exhibition / Gallery => Topic started by: amacmullen14 on Jul 17, 2011, 03:27 am

Title: Arduino Polyphonic Synth
Post by: amacmullen14 on Jul 17, 2011, 03:27 am
EDIT: See the last post for the most current info.  I just kept it in the same thread.


So I've learned to use the internal timers on the arduino, and I've gotten it to make 8 bit noises using PWM and a lowpass filter.
So, I built a MIDI synth!
Hardware is super simple, just an RC lowpass filter connected to pin 11.  (I can't exactly remember what values)
One timer is set up for fast PWM on pin 11, another timer updates the compare register for the first timer at the correct frequency.  
It can play any 16-step (could be more or less, 16 just seemed like a good number) 8 bit waveform, like sawtooth, square, or triangle.
Here's the code:
Code: [Select]
#include <Frequencies.h>
#include <MIDI.h>

//  A MIDI simple monophonic synth, with wavetable synthesis.
//  Uses timer2 to generate PWM representing an analog output.  A simple RC lowpass filter
//  filters to an analog output.  (in the initial setup, R=100ohm  C=0.33uF
//
//  Eventually, the tone may be controlled in a timer interrupt routine
//  For now, manually coded in loop()

const int notes[] = {
 NOTE_B0, NOTE_C1, NOTE_CS1, NOTE_D1,    // other octaves by multiplying by power of 2
 NOTE_DS1, NOTE_E1, NOTE_F1, NOTE_FS1,
 NOTE_G1, NOTE_GS1, NOTE_A1, NOTE_AS1,
};

byte waves[][16] = {
 {
 0x00, 0x20, 0x40, 0x60,
 0x80, 0xa0, 0xc0, 0xe0,
 0xff, 0xe0, 0xc0, 0xa0,
 0x80, 0x60, 0x40, 0x20
 }
 ,
 {
 0xff, 0xff, 0xff, 0xff,
 0xff, 0xff, 0xff, 0xff,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00
 }
 ,
 {
 0xff, 0xee, 0xdd, 0xcc,
 0xbb, 0xaa, 0x99, 0x88,
 0x77, 0x66, 0x55, 0x44,
 0x33, 0x22, 0x11, 0x00
 }

};
//  Triangle wave, just wanted something different from the typical square wave.

MIDI_Class input;
int currentNote;
long currentPeriod;
int currentIndex;
unsigned long lastToggle;
int currentWave = 0;

void setup()  {
 pinMode(11, OUTPUT);  //set OC2A pin to output

 TCCR2A |= 1 << WGM20;  //     \
 TCCR2A |= 1 << WGM21;  //   }- Set timer to phase fast PWM mode
 TCCR2B &= ~(1 << WGM22);  //  /  

 TCCR2A |= 1 << COM2A1;  //      }- Set to non-inverting PWM
 TCCR2A &= ~(1 << COM2A0);  //  /

 TCCR2B |= 1<< CS20;  //      \
 TCCR2B &= ~(1 << CS21);  //   }- Set to prescalar of 1 (no prescalar).
 TCCR2B &= ~(1 << CS22);  //  /           62500 Hz PWM

 //============================================================================

 //Setting up timer1 for CTC mode
 TCCR1A &= ~(1 << WGM10);  
 TCCR1A &= ~(1 << WGM11);
 TCCR1B |= 1 << WGM12;
 TCCR1B &= ~(1 << WGM13);

 //Prescalar 1
 TCCR1B |= 1<< CS10;
 TCCR1B &= ~(1 << CS11);
 TCCR1B &= ~(1 << CS12);

 TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
 sei();

 input.begin();  //initialize MIDI input
 
 pinMode(2, INPUT);
 digitalWrite(2, HIGH);
 pinMode(3, INPUT);
 digitalWrite(3, HIGH);

}


void loop()  {
 int count = 0;
 if(digitalRead(2) == LOW)  {
   count++;
 }
 if(digitalRead(3) == LOW)  {
   count++;
 }
 currentWave = count;
 
 
 //Midi input handling

 if(input.read() == true)  {  //do we get signal
   if(input.getType() == NoteOn && input.getData2() != 0)  {  //is it a noteOn event,
     currentNote = input.getData1();                          //  and not with 0 velocity?

     int noteIndex = (currentNote - 23) % 12;  //figure which value in note array corresponds to
     //  recieved MIDI note
     int noteOctave = (currentNote - 23) / 12; //figure out what octave the note is
     unsigned long Hz = notes[noteIndex] * (1 << noteOctave);
     wOCR1A(hz2ocr(Hz * 4));
     wTCNT1(0);


   }
   else if(input.getType() == NoteOff || input.getData2() == 0)  {  //is it a NoteOff event,
     if(input.getData1() == currentNote)  {                         //  or 0 velocity NoteOn?
       currentNote = 0;
     }
   }
 }

 //  End of midi input handling



 if(currentNote != 0)  {
   TIMSK1 |= 1 << OCIE1A;
 }
 else  {
   TIMSK1 &= ~(1 << OCIE1A);
   OCR2A = 0;
 }


}


unsigned int hz2ocr(unsigned long hertz)  {
 unsigned long ocr = (16000000L / (hertz *2)) - 1;
 return int(ocr);
}


ISR(TIMER1_COMPA_vect)  {
 currentIndex = (++currentIndex) % 16;
 OCR2A = waves[currentWave][currentIndex];
}

void wOCR1A(unsigned int value) {
 unsigned char sreg;
 
 /* Save global interrupt flag */
 sreg = SREG;

 /* Disable interrupts */
 cli();

 /* Set TCNT1 to i */
 OCR1A = value;

 /* Restore global interrupt flag */
 SREG = sreg;
 
 sei();
}


void wTCNT1(unsigned int value) {
 unsigned char sreg;
 
 /* Save global interrupt flag */
 sreg = SREG;

 /* Disable interrupts */
 cli();

 /* Set TCNT1 to i */
 TCNT1 = value;

 /* Restore global interrupt flag */
 SREG = sreg;
 
 sei();
}


frequencies.h is a file with #defines for all the note frequencies.  It is copied and pasted from those found in the tone library, so including the tone library would work.
In the current rough state of the synth (stuff haphazardly put into a breadboard) different waveforms are selected by connecting pins 2 or 3 to ground.  0 pins connected, triangle.  1 pin, square.  2, sawtooth.

A song snippet I made while playing around with the synth and my kp3:
song (http://soundcloud.com/beefinator/diy-2-fixed)

And hopefully soon to come:
http://www.youtube.com/watch?v=AtBuGlE_FVM
Original video got stuck processing.  Reuploaded, fixed.
Title: Re: Arduino 8bit Synth
Post by: Utopia on Jul 17, 2011, 05:18 am
Really nice sound! If you ever find out the values for the rc circuit, please post them.
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Jul 17, 2011, 01:50 pm
Okay, I checked out the circuit,and
R=100ohm
C=0.33uF

And a 100uF dc blocking cap directly after the filter, before the output jack.
Title: Re: Arduino 8bit Synth
Post by: Utopia on Jul 17, 2011, 05:55 pm
I apologize if I sound dense, but is the wiring (both of the parts and to the speaker) complicated?
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Jul 17, 2011, 09:41 pm
Not at all complicated!

All it was (I've made progress on putting it inside the enclosure, it's no longer on the breadboard) was
Arduino pin 11 -----/\/\/\---------*-------------| |--------------------1/4 inch jack  ---->> mpc or kp3
                        resistor                            |             DC blocking cap                                    |
                                                                |                                                                            |
                                                               =  filter cap                                          Ground for jack
                                                               |
                                                        Ground

Hopefully my ASCII schematic does not get messed up!
Title: Re: Arduino 8bit Synth
Post by: keeper63 on Jul 18, 2011, 12:02 am
Was that entire song demo done with it? Regardless, it's catchy... :)
Title: Re: Arduino 8bit Synth
Post by: Utopia on Jul 18, 2011, 12:07 am

Not at all complicated!


Thanks - I will have to put one together
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Jul 18, 2011, 12:20 am
Quote
Was that entire song demo done with it?


No, the drums and looping are from the kaoss pad, and the compressor is the mpc.  It was just something I did when I was bored and decided to play around with it.  
The synths in the video's music are also the arduino synth, run thru the kaoss pad for effects.

Oh, and so far, I have everything wired up in the enclosure except the audio circuitry.  So it has an external USB port, power jack and switch, MIDI in/out/thru jacks, with a switch to connect or disconnect the midi serial lines.  And an 8*16 RG led matrix, and 6 pots.  And in the future, 6 buttons.
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Jul 26, 2011, 12:46 am
So I made some not apparently relevant progress on the synth.
I've been working on the graphics side of it, the 8*16 led matrix.

As of now, it can do sprite manipulation, with a function that takes the sprite data and a pair of coordinates and displays the sprite at those coordinates.
And, which I'm more proud of, it can draw lines between any two given points on the screen! (or off the screen, it just doesn't show all of it)

All from scratch, no help from teh internets
(I found out about the Bresenham line algorithm after I made the code.  I unknowingly recreated the algorithm in my code before I had even heard of it!   :smiley-roll-blue:)

I'll post the code once I have some little bugs fixed, but in the meantime I'll post a video!
http://www.youtube.com/watch?v=X6L4a3UT9qw
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Aug 18, 2011, 03:18 am
More Progress!!!

I added 2 1/4 inch jacks, one for the audio output, one for something else in the future, meybe a cv output, i dunno.

So, I have a fully working simple midi synth inside the plastic enclosure!  Selectable waveform by the first knob.
I still have to work out a couple bugs.  The main issue right now is that for some reason, only the square wave is outputted correctly.  The triangle has a weird peak where it should be at its lowest point, and the saw only seems to output the first few steps of the waveform, then it zeroes out.

Fixing that will be for another day, I'm happy with the progress for now.


By the next time I post (unless consulting for a problem) I will have a (hopefully polyphonic) 8bit synth with a GUI!
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Aug 24, 2011, 10:58 pm
Update:

I lied, I don't have a working synth with gui yet, because I'm having some problems with MIDI input.
But I finally went to radioshack to get some more knobs, so now it has knobs on all 6 pots.
I also got some buttons, so now it has 6 buttons, 4 in a d-pad orientation to the left of the screen, and 2 larger buttons to the right of the screen. 
So in addition to making a synth with audio generation capabilities of a gameboy, I could have a little gamesystem that runs on a 2 bit color 8*16 display!
Title: Re: Arduino 8bit Synth
Post by: salemlab on Aug 26, 2011, 01:46 pm
very nice project !!!

"(°_°)"
Title: Re: Arduino 8bit Synth
Post by: FireyFate on Sep 01, 2011, 10:08 pm
Keep the updates coming!  I'm interested to see where you are going with the screen implementation. 
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Sep 01, 2011, 10:58 pm
I'm working on getting polyphony an arpeggiation right now, so no screen yet. 

But I'm a bit stuck on a bit of code...   :(
(see my topic under audio about me being puzzled over a bit of code)
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Sep 04, 2011, 11:25 pm
Still haven't made progress on the audio code, still stuck on the same problem.  (here: problem? (http://arduino.cc/forum/index.php/topic,70989.0.html))

But I rewired the led matrix shield some (wirewrapping ftw) changing some pins, and now all 6 shift registers are daisychained and controlled thru hardware SPI, for extra speed.  This also means that I can use SPI to interface to a parallel-in, serial-out register for button inputs.

Thankfully, this practically does not interfere with the rest of the code at all, because the other OC pin for timer2 is pin 3, I'd just have to change the timer configuration a bit to use the B half of timer2.
Title: Re: Arduino 8bit Synth
Post by: amacmullen14 on Oct 01, 2011, 12:59 am
Alright, HUGE progress!

I went from using 2 timers for monophonic sound, to using only one timer for 4 part polyphony!

I haven't written the midi handling code yet to handle polyphony, but the synth is capable of playing 4 notes.

Right now it plays the root note (as sent by the midi keyboard), a major third, a perfect fifth, and an octave.  I just chose these notes arbitrarily, it's not limited to certain intervals or notes, it's just a test for now.

Here's a sound sample:
POLYPHONY WOOO (http://soundcloud.com/beefinator/polyphony-wooo)

I can officially say this arduino synth have surpassed the audio production capabilities of a gameboy!
Title: Re: Arduino Polyphonic Synth
Post by: sushyoshi on Oct 12, 2011, 03:26 pm
Very nice.

I´ve just ordered my Arduino to start playing with stuffs like that. I was feeling very limited doing sequencers with analog compnents such as CMOS. Anyway i did make a good Atari Punk Console like sequencer that had some good sounds to it but it uses so much electronics.
I guess the road to synthesizers is really throuh uC.

Anyway keep posting with improvements as I am looking foward to see them. :P
Title: Re: Arduino Polyphonic Synth
Post by: amacmullen14 on Nov 22, 2011, 10:31 pm
A little progress today, and I filmed a simple demo of the synth so far.  I got the arduino doing sprite-based graphics (to display numbers) at the same time it's acting as a MIDI polyphonic synth.  The 4x4 characters that I made for it to display are convenient since each can be stored in a single unsigned int.

There are 4 numbers on the screen, each turns on when a corresponding voice on the synth is playing.
Songs:  Dr wily stage 1 theme, megaman 2; UN owen was her, embodiment of scarlet devil.
http://www.youtube.com/watch?v=o7_udMf-5h8
Title: Re: Arduino Polyphonic Synth
Post by: joemarshall on Nov 28, 2011, 04:47 pm
Blimey, that looks pretty neat.

I dunno if you'd be interested, but I've put up some code for an 8 voice + 1 filter synth that I'm building - see the thread below.
http://arduino.cc/forum/index.php/topic,80569.0.html

The oscillator etc. code is hacked together in assembler to be extremely efficient, whilst using a nice 256 byte wavetable, and with 64 volume levels per oscillator for nice polyphonic playback.

I really need to get a nice box sorted for mine - that looks so much cooler with the lovely well built box. Hmm.

Joe

Title: Re: Arduino Polyphonic Synth
Post by: amacmullen14 on Nov 28, 2011, 10:24 pm

Blimey, that looks pretty neat.

I dunno if you'd be interested, but I've put up some code for an 8 voice + 1 filter synth that I'm building - see the thread below.
http://arduino.cc/forum/index.php/topic,80569.0.html

The oscillator etc. code is hacked together in assembler to be extremely efficient, whilst using a nice 256 byte wavetable, and with 64 volume levels per oscillator for nice polyphonic playback.

I really need to get a nice box sorted for mine - that looks so much cooler with the lovely well built box. Hmm.

Joe




Thanks, and well done on your project.  I would look at the code, but I like figuring things out on my own!   :)

I was thinking about rewriting my ISR in assembly for speed, I might get around to that sometime.  First I'd have to learn assembly...   :smiley-roll-sweat:

The 16 byte wavetable was a bit arbitrary, I could easily set it to do more (within the frequency limits of my code; I would probably just have it step by powers of 2 for higher frequencies) but I just haven't made up the larger wavetables.  I just typed up some hex values for triangle, sawtooth, and square waves, and I didn't feel like doing more than 16 bytes each.   :smiley-roll:

Plans I have for it:
Hardware -- make a new better audio board
Software -- a lot planned.  customizable software midi routing, envelopes on each voice, a built in sequencer, to name a few things.
Title: Re: Arduino Polyphonic Synth
Post by: joemarshall on Nov 28, 2011, 10:57 pm
256 byte wavetable is worth doing for speed - if you force the waves to be aligned to a 256 byte boundary, then taking an index into the wavetable can be done by just copying a byte into the low byte of the wavetable pointer, which saved me 3 instructions per sample per oscillator (which was quite a lot given each oscillator takes about 15 instructions total. 256 bytes also saves needing to do any maths on the wavetable lookup variable, you can just use the high byte as the lookup directly. It's all small improvements, but compared to the original wavetable code I played with off the internet, it is something like five times as efficient with all the optimisation.

The avr assembler is dead easy, especially if you use inline assembler in c code, I learnt a lot of it from reading the code of meeblip, which is a whole synth written in avr assembler, the rest I got from the atmel instruction set reference. It's well worth doing - my c code could only just scrape 8 voices with no filter, whereas in assembler the 8 voices take something like 10-20% of processor (not sure how much time the filter takes, but I still seem to have a fair bit of time for other stuff).
Title: Re: Arduino Polyphonic Synth
Post by: amacmullen14 on Nov 29, 2011, 04:49 am
Thanks for pointing out the meeblip site!  I looked a bit at the avrsynth code it's based on, and did some research on assembly.  I'll definitely work on rewriting my ISR code, now that I have a bit of an idea how to do it.