|Create a Synthesizer|
In this tutorial series, we'll dig into the audio abilities of the Propeller Platform and create your own on-screen synthesizer. We will start with the basics of sound generation, then into a fully functional instrument capable of creating funky, eight-bit sounds. Here's a demo of our finished product from this lesson;
Any Propeller based board which has an audio output, TV output, and keyboard input is capable of the Propeller Synthesizer. Two common configurations are using the Propeller Platform or the Parallax Demoboard.
Propeller Platform with Protoplus Module
This combination will give you the audio and TV outputs by simply connecting the two boards. The required keyboard interface can be achieved by the creation of this simple circuit either soldered into the Protoplus prototyping section, or added with a breadboard. The PS2 to breadboard adapter can be obtained from Parallax (#28060) for five dollars.
The Parallax Demoboard will handle the requirements for the Propeller Synthesizer right out of the box, meaning that any Propeller configuration which uses the Demoboard configuration will work just fine as well.
Additionally, this addendum provides all three of the required circuits. Those of you with a Propeller Education Kit, or even just a stock Propeller Platform board can jam with us.
A preview of the objects
Retrotext is a new and improved version of the same driver we used in the Lightcycles game. It has some improvements and a few new methods. It also has the added ability of using custom fonts created with the PixelFont Editor.
SIDcog is an emulation of the famous SID (Sound Interface Device) chip in the Commodore 64 computer. SIDcog was created by Propeller enthusiast, Johannes Ahlebrand. The SID chip was an important historic milestone in computer sound generation, and SIDcog is a fun way to learn about how synthesizers work
Before you begin creating some funky, synth jams, it's important to take a look at how any microcontroller generates sounds. Pay a visit to Audio Lesson 0.
Let's create a Propeller synthesizer!
Unzip the part 1 source files into an empty folder. Open the Propeller Tool and create a new program called "Synth1.spin" in the same folder.
We'll start by creating our CON (constants) section, defining our speed and some variables which will not change over the course of our program. Type in the following;
The first two lines setup the speed that our Propeller will run, 80mhz. The next four lines assign the words, video, keyboard, audioR, and audioL to mean 12,26,10, and 11. Each our program sees these words in the code, it will accept them as a number. Anything defined in the CON section is "set in stone" and does not change over the course of running the program. In our case, these words serve as the settings for our devices and can be changed to suit whatever board you are using.
Next, let's create our variables (VAR) section. Variables assigned here can be accessed anywhere in our program. Add the following code;
"byte octave" creates an empty box we can place a byte value into later in our program. Now, add the OBJ lines which will call on the objects which will do the background magic for the keyboard, TV, and audio. Add the following code;
So far we have setup the basic requirements for our Propeller Synthesizer, now it is time to start creating the actual PUB method which will become the brain of our instrument. Add the following code;
The words, keystroke, count, channel, and note are variables which will be used later in this PUB main method. They can be assigned any value while the program is running, but unlike variables called in VAR, they are limited to being used in this PUB section.
Text.start(video), key.start(keyboard), and synth.start(audioR,audioL) kick-start the objects we entered in the OBJ section. Remember that we defined words video, keyboard, audioR, and audioL to the numbers 12,26,10, and 11 back in CON.
Let's kick off our synth with a jazzy title. Make some space for later with a few carriage returns and then add this line;
DrawRainbowTextAt is a new method added to our video driver. In this case it sends the words, PROPELLER SYNTHESIZER directly to the screen, 9 spaces to the right on line 1. It's time for the main loop of our program. Make some space for later with a few carriage returns and then add the following lines;
Repeat starts a loop. Everything indented under repeat will loop over and over again. Let's look at what the next three lines do ever time the loop starts over;
Keystroke is a byte variable we added at the beginning of PUB main. It equals zero here.
Next we check with our keyboard object to see if a key has been pressed. The value of the keypress (if any) is assigned to the variable "keystroke", so it might not equal zero at this point.
Count++ is a simple counter which simply adds 1 to the variable "count" each time the loop recycles. It'll be useful later in our code.
At this point, we are looking for input from the keyboard, now it is time to give our synthesizer a brain. Stretch out your fingers and add the following code (or download it );
How are your fingers after that?! While you are resting your fingers, let's examine one of the IF statements and understand what is happening;
if keystroke == 113 checks to see if the key pressed was key 133. We know key 133 as the lowercase "q".
(Did you know there is a handy chart built into Propeller Tool which will display the ASCII numbers assigned to all of the common keys? Click on "Help", click on "View Character Chart..." As you mouse over the keys, you will see their values displayed at the bottom of the window. Check to see if lowercase q is actually 113.)
Below each IF statement you entered ColorLShapedKey, ColorSharpKey, ColorFullSizedKey, or ColorHalfSizedKey. These are PUBs we will add to our program later. I promise they will do something cool later.
The note:=60 line assigns the variable "note" the value of 60. Later this will become the frequency generated by our SIDcog sound object. 60 is note C to SIDcog.
Notice how the words, ColorLShapedKey and note:0 are indented under the IF statement? Just like repeat, indentation is very important. Each of these two lines are executed IF keystroke equals 113.
Our synthesizer has a brain of sorts. Now it's time to actually generate some tones.
Add a few carriage returns, then add the following code;
Again, we have another IF statement. It checks to see if value of keystroke is "greater than" zero. In other words, a key has been pressed. The counter "count" is reset back to zero. synth.playnote(channel, note+octave) actually plays the note.
We created the variable "channel" at the beginning of our PUB main method, but because we didn't assign it a value, its value is zero. SIDcog is actually capable of three simultaneous channels of sound. Our project simply uses a single channel, 0. Can you guess the value of note+octave? Remember, each IF statement assigns note a value depending on the key pressed. Octave is presently 0, but will be revisited later.
You might be tempted to try your Propeller Synthesizer right now, but we need to add some additional PUB methods to keep things from crashing. Remember the ColorLShapedKey, ColorSharpKey, ColorFullSizedKey, or ColorHalfSizedKey methods we entered at each IF statement? For now we'll create some empty methods and do something interesting with them later.
Add the following code;
We have the basic framework for our Propeller Synthesizer! Hit F10 and send this code to your Propeller. Pressing keys Q,W,E,R,T,Y,U,I,O,P and 2,3,5,6,7,9,0 will play notes and sharps while pressing any other key will stop the note.
If you had trouble up to this point, the file example1.spin is included in the source files.
Having fun with your basic Synthesizer? Let's jazz up our screen a little with a piano keyboard display and note diagram.
Add the following code at the very bottom of your program;
If you squint your eyes a little, you can see that this DAT section stores a strange looking piano keyboard in a series of bytes called "piano". I've taken the liberty of creating some custom font characters in the file called, "piano.pf" using the Pixel Font Editor mentioned earlier in the text. I've changed the characters !,$,#, and * to custom characters when they are displayed. Our code doesn't know this, and quite frankly doesn't care. In the code a * is always a * even when it looks like a #.
Next, we need to new PUB method which will display our piano keyboard.
Add the following code just above the DAT section;
This tricky little double repeat pulls the information from our DAT piano bytes and places them on the screen using PokeChar method in our video driver. While I'm not going to go into detail on this bit of magic yet, you should be able to see the IF statements that check if see if the byte is character "35" (#) and paints it black, with all other characters painted white. Sounds like a piano keyboard doesn't it? After all of the layout is sent to screen memory, a text.Updatescreen command it sent to sent it to the display.
We have a piano keyboard in our program code, and a new PUB method to display it. All we need now is to call the new method from somewhere in our program. Remember our DrawRainbowTextAt(9,1,string("PROPELLER SYNTHESIZER")) line? Add the second line below;
Press F10 again. Now our Propeller Synthesizer has an on-screen keyboard!
Play a song
Starting a Q on the keyboard, let's play a song.
When the Saints Go Marching In
Our synth is still pretty basic at this point, but already we are able to drive friends and family crazy and maybe even get the family dog to howl. Next time we will dig into how to create instruments with a little understanding of the ADSR Envelope. We'll even dress up our synthesizer with some additional on screen animation.
Until next time! Spin On! - Jeff Ledger (Propellerpowered.com)