Pseudo-Polyphony With Micro:bit
by microbit-noob in Circuits > Speakers
109 Views, 3 Favorites, 0 Comments
Pseudo-Polyphony With Micro:bit
The Micro:bit can only play one note at a time (with minor exceptions). However, with a clever trick that retro video games used back in the day, we can create the illusion of multiple notes played simultaneously. This allows chords and multiple voicelines to be played!
This effect works by rapidly alternating between played notes, making it seem as though they're playing at the same time. If you are familiar with music theory, it is equivalent to a very fast arpeggio.
In this project, I will replicate this technique on the Micro:bit.
Note: I will be writing code in JavaScript/TypeScript using the Microsoft MakeCode editor. A little coding experience is helpful for this project; however, you're welcome to copy and paste my code, which I will post in full at the end of this Instructable.
Supplies
(Click the image above to see annotations!)
All of these materials are included in the KS4007/KS4008 Keyestudio Starter Kit (except for the Micro:bit on the KS4007).
You will need:
- 1x Micro:bit v2.0
- 1x USB Cable (Micro to Type-A)
- 1x Breadboard
- 1x Micro:bit T-Type Shield
- 1x IR Receiver
- 1x Remote Control
- 4x Button Modules
- approx. 15 or more male-to-male breadboard wires
Install the Makerbit IR Receiver Extension
First, create a new project and install the ‘MakerBit’ extension, which will allow you to work with the IR receiver. The extension should show up in the side bar once installed.
Connecting the IR Reciever
This receiver has 3 pins:
- The left pin connects to a digital read pin of your choice. The IR receiver will output signals through this pin. (Recommended not to use pins 0 to 2 if you want to use the TouchPins for extra buttons.)
- The middle pin connects to GND (ground).
- The right pin connects to 3V.
Testing the IR Receiver
This code will tell the Micro:bit to read the IR receiver's outputs from your chosen pin with connectIrReceiver, and the onIrButton will fire when its parameter conditions are met (in this case, IrButton.Any meaning any button on the remote control, and IrButtonAction.Pressed meaning when a button is pressed).
After that, pointing the remote control towards the IR receiver and pressing a button should play a note!
Troubleshooting
If nothing plays, here are some possible fixes:
- Make sure the wire connections are in properly.
- Check if you connected the output of the IR receiver to the correct digital pin (the code above sets it to DigitalPin.P10).
- Make sure the receiver's pins are connected to the right input/output.
- Use a different digital pin.
- Double-check the battery in the remote control.
- Check if the Micro:bit is properly inserted into the T-type shield; the front should face the breadboard.
- Re-download the code or hit the reset button on the back of the Micro:bit.
Assigning Musical Notes to Buttons
We will assign the button codes on the remote control to musical notes. Below is a C major scale.
In technical terms, this is a dictionary that we will use to map the input buttons to the output musical notes.
Feel free to pick whatever notes you wish the remote control buttons to play!
Example of Custom Note Assignment
Here is an example of what you could do! This is a D minor blues scale with some added notes.
Code for Pseudo-Polyphony
Let's start coding in pseudo-polyphonic functionality!
The way I did this is to split a note up into many very short ones and play them in rapid succession. That way, with multiple notes, each short note would take turns in playing, making it seem like they're playing at the same time. (see image above)
Now we need to be able to add and remove notes from this list. Start with this empty function.
The function will need to know the note being pressed and for how long. control.inBackground allows the code inside to run without halting the entire program to wait for it to finish.
Add this inside the control.inBackground function.
After that, replace the code inside your current makerbit.onIrButton function with this.
Every time a button on the remote control is pressed, buttonPressed stores which button you pressed. Then, the code checks if that button corresponds to any note in buttonToNote. If it does, the noteOnOrOff function runs, playing the corresponding note. Here, I have the note last half a beat; however, you can change it to any duration you want.
Now, we need to loop over active_notes and play them.
Extra Buttons
The button modules should be placed crossing the center divider of the breadboard. Connect one side of the button to a touch pin and the other end to GND (ground).
Use pins 0, 1, and 2 as the main pins. You can use pin 5 as an external button A, and pin 11 as an external button B.
Example
Here is an example of what you can do with these buttons. Notice how we call noteOnOrOff to play a note of our choice.
Troubleshooting
If the buttons do not function as intended, here are some possible fixes:
- Check the button connections; the metal pins should be in line with the wires.
- Try pressing down and to the side.
- Try a different touch pin (if possible).
Final Result
Your code should look something like this:
Don't worry if it doesn't look the same as yours (assuming you hadn't already customized it). I recommend experimenting and adding components; make this project truly your own!
Bonus Simple Demo!
Here's a short and simple rendition of Toby Fox's Megalovania! (Yes, very unique pick, I know.)