MickMad
Well-known member
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 and here.
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, there is also a premade Arduino compatible version here).
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, and I modified without any hassle Tymm's MIDI library for Arduino 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 ).
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
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 and here.
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, there is also a premade Arduino compatible version here).
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, and I modified without any hassle Tymm's MIDI library for Arduino 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 ).
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
Last edited: