PDA

View Full Version : MIDI synthesizer with Teensy 3.0



MickMad
03-07-2013, 01:36 AM
Hello everyone, I got my first Teensy 3.0 last week and I'm really really happy about it! I've been fiddling around getting the Teensy to do some simple but neat audio output and I got some nice things.

I already dealt with PWM and 8 bit audio output in general with the Arduino Uno, eventually I got the Uno to play a set of musical bars with 4 different channels, so I started "porting" some of that code into the Teensy.

Of course, the first problem I got was about the timers; I had to setup a timer just like I did with the Uno; luckily, the Kinetis K20 has a number of different timers to choose from; I started testing out the FlexTimer module, to achieve the same result I obtained with the ATmega328p using the Timer1; unfortunately, it is a pain to setup, so I switched to the PIT timer module, which has already been discussed sometimes on the forum (http://forum.pjrc.com/threads/14-Teensy-3-0-and-interrupts).

The PIT timer is so easy to setup, and after setting it up correctly, I soon got a square wave out by simply toggling on and off a pin in the interrupt routine, and varying the frequency at which the timer counts; unfortunately, getting a signal other than a 50% duty cycle square gets a bit difficult using this method; also, varying the frequency of the counter to vary the pitch of the output note is not a good method either, because this means that if I'd want to output more than one single note at the same time, I should use another timer only for that note.

So I abandoned the PWM method, I stuck one PIT timer at ~22 KHz count rate and used the interrupt routine of the timer to output an 8 bit sample on 8 pins of the Teensy in parallel, which are fed to the 8 inputs of an R2R ladder DAC; this method is easy and lets me increase the number of concurrent notes easily; actually I'm using a DDS (direct digital synthesis) method well described here (http://www.evilmadscientist.com/2007/quick-and-dirty-d-to-a-on-the-avr-a-timer-tutorial/) and here (http://www.evilmadscientist.com/2007/quick-and-dirty-d-to-a-on-the-avr-a-timer-tutorial/).

To get some notes, I first use a pot to read a value which is used as an index for a table containing a wide range of notes (from C0 to C9); I then store a tuning word which contains 2^16 * frequency / sampling frequency (the sampling freq. is the one at which the PIT updates the current sample value for the DAC) in a variable; this tuning word is the angular velocity of the digital oscillator used to generate the output signal; this tuning word is added at every sampling period to a 16 bits phase accumulator which holds the value of the phase angle of the oscillator; the first 8 bytes of the phase accumulator are used as an index in a 256 samples wavetable.

I got 6 different wavetables for now (sine, tri,square, saw, stair, noise); I will soon write a routine to calculate tri,square,saw,stair,and noise waves in real time (the noise wave is a little tricky, but mr Akesson got it working on an ATmega88 here (http://www.youtube.com/watch?v=_uU4BzSQQmY&list=UU8ge7La_vq48PVEmR-DJ5Wg&index=39), there is also a premade Arduino compatible version here (http://www.instructables.com/id/Arduino-Chiptunes/#step1)).

At first, I was using a pot to read a note, a pot to read the pitchbend amount of the note(middle value= no bend, max value = max.bend, min value =-max.bend) and a pot to read the max semitones interval in which the note can bend (min=0 semitones, max=12 semitones); I also have a pot to control the gain of a simple amplifier stage;

I wanted to implement some digital controllable filter, and since I ran out of potentiometers, I decided to take the thing to a further level: I first got a working PIT timer setup and control library of my own, which is actually pretty similar to the one here (http://forum.pjrc.com/threads/17543-PITimer-PIT-(Periodic-Interrupt-Timer)-library-for-Teensy-3-0), and I modified without any hassle Tymm's MIDI library for Arduino (https://github.com/tymmothy/TymmsArduinoMIDI) to work with the Teensy 3.0 using Serial1 for UART communication on a MIDI port.

Now I got notes and pitch bend via midi, thus freeing 2 potentiometers; I tried to apply the things I learned in university but still without any relevant success; I managed to get a resonance filter working, but what I want is a low pass resonance filter, with variable resonance and cutoff frequency; I'm studying that part on paper when I have time. Right now, I'm getting strange sounds out of the Teensy, since I modified the output filter part and decided to multiply every out sample with a sample took from a sinc function (the sinc function is the function sin(x) / x, which is the impulse response of a low pass filter with frequency x); I don't know what to expect from doing this, but it makes some strange noises nonetheless; I'm using the two spare pots to control the amount of multiplication between the two functions, and to control the frequency of the sinc. I will try to use this sinc function thingy to apply a discrete convolution algorithm to obtain the replica of the reponse of a low pass filter, but I will eventually pass on to some faster and easier way to do this stuff (that's why I'm studying the filter part on real paper :D ).

I will also abandon the R2R home made ladder for a more compact 8 bit parallel DAC in the near future; 16 bit output is considered as well. I want to get the filter part ready and working because I want to pass on to some other math stuff: ENVELOPE GENERATION. I'd like to implement some other Moog-like functionality, like ADSR envelopes for the oscillator stage and for the filter stage, and I will keep implementing all this stuff working for one single oscillator. As soon as I get all the filter stuff done, I will start writing an Oscillator library for realtime sound generation on Teensy to share with all the people out there.

Here are some links to my Google Drive where I store the 2 libraries and the source code of the current setup. This is of course a work in progress, and the code is not commented at all, but it's fairly straightforward.

Google drive page with source code and other stuff : https://docs.google.com/folder/d/0B-yo2xApQsSeWTNWcHlXNWJJM0E/edit?usp=sharing

Video of first setup (still without MIDI in: https://docs.google.com/file/d/0B-yo2xApQsSeZXk1WEZ6MlNwUTg/edit?usp=sharing

Tomorrow morning I will post a video of the second setup, with MIDI in, with a demonstration of the pitch bend, and a video of the third setup, with a demonsration of the result of the interpolation of the sinc function and a saw wave; the videos will also be in the google drive folder with the source code.

Stay tuned folks! And of course, every crit comment and suggestion is well accepted! :)

Mick

EDIT: Video of first MIDI IN test: https://docs.google.com/file/d/0B-yo2xApQsSeQnkxdnQwd2wwNWs/edit?usp=sharing

drjohn
03-11-2013, 10:32 PM
Impressive work! I have been hoping that the Teensy 3.0 will make a fine brain for a small sound module and had been eyeing the preenfm code--though I'm not that big a fan of the clangy FM sound, it's a great project (using the MapleMini). This is a nice jump forward, too.

Possibly relevant to your interests (or redundant, depending...):

The Meeblip LP filter was reworked from assembly into Arduino code for the Octosynth; links to that and other synths are in the code here (https://github.com/jonronen/arduino-synth/blob/master/generator.c). There are DSP code examples that I keep thinking will be helpful here (http://musicdsp.org/archive.php?classid=3#29).

Cheers,

J


Now I got notes and pitch bend via midi, thus freeing 2 potentiometers; I tried to apply the things I learned in university but still without any relevant success; I managed to get a resonance filter working, but what I want is a low pass resonance filter, with variable resonance and cutoff frequency; I'm studying that part on paper when I have time. Right now, I'm getting strange sounds out of the Teensy, since I modified the output filter part and decided to multiply every out sample with a sample took from a sinc function (the sinc function is the function sin(x) / x, which is the impulse response of a low pass filter with frequency x); I don't know what to expect from doing this, but it makes some strange noises nonetheless; I'm using the two spare pots to control the amount of multiplication between the two functions, and to control the frequency of the sinc. I will try to use this sinc function thingy to apply a discrete convolution algorithm to obtain the replica of the reponse of a low pass filter, but I will eventually pass on to some faster and easier way to do this stuff (that's why I'm studying the filter part on real paper :D ).

MickMad
03-14-2013, 08:09 PM
Impressive work! I have been hoping that the Teensy 3.0 will make a fine brain for a small sound module and had been eyeing the preenfm code--though I'm not that big a fan of the clangy FM sound, it's a great project (using the MapleMini). This is a nice jump forward, too.

Possibly relevant to your interests (or redundant, depending...):

The Meeblip LP filter was reworked from assembly into Arduino code for the Octosynth; links to that and other synths are in the code here (https://github.com/jonronen/arduino-synth/blob/master/generator.c). There are DSP code examples that I keep thinking will be helpful here (http://musicdsp.org/archive.php?classid=3#29).

Cheers,

J

Thanks mate! I've been checking out that musicdsp.org page for a while, I tried some code before but never sounded how I wanted; now I implemented this filter here (http://musicdsp.org/archive.php?classid=3#259) with some minor modifications and it's working :D
I still have some instability and distortion problems, probably due to the fact that I'm working with unsigned 8 bit integers, but it's a beginning! I'll try to average the output of the filter stage on 256ths so that it always fits 8 bits and see if this works better.

As I said in the previous post, as soon as I get the filter stage done, I will try and pack all the working stuff in some libraries, like an Oscillator library, a Filter library and so on, just like in a modular synth engine; I also need to design a simple but efficient MIDI note buffer to implement some legato function, and I will do that as soon as possible. Last but not least, I need to implement an ADSR envelope generator!

For the FM stuff you were talking about, well I might give it a try :) I'm not into FM sound too ,it's too clangy, but still I'd like to leave this option open; you know, when I get all of the stuff I mentioned done, I will link two oscillators together, and it would be fairly simple to select from addition, subtraction and FM between the two. btw, that preenfm sounds like a beast :D

Still, thanks for the support and for the hints :)