Music boxes have been around since their invention in the mid-nineteenth century. They work by having a series of differently tuned teeth that emit a sound at a specific frequency when struck by a nub on a rotating cylinder. Older, traditional music boxes are operated with a hand crank to turn the cylinder, and they are also very limited in the sounds they can play, as the comb’s frequencies cannot be dynamically updated.
This music box differs in a major way compared to a traditional one. Although it still utilizes a spinning cylinder with little pegs, there isn’t a comb with tuned teeth. Rather, each hole on a horizontal section of the rotating cylinder corresponds to a sound that a Teensy can play. These sounds can be comprised of various instruments, akin to a synthesizer. There are 8 holes on each “slat," which is 1/20th of the way around the cylinder.
The sounds can be individually assigned to each hole, which includes the volume, pitch, modulation, and duration. Additionally, the speed at which the wheel turns, the reverb, and selected channel can be controlled via a capacitive interface.
I began by laying out a rough sketch of the wheel, including the size and positioning of the axel holes. Next, I created a circular pattern that cut out 20 sections along the outside of the wheel for the slats to nest in.
In order to fabricate the parts, I laid them out in a flat pattern and then generated CNC machining toolpaths. The wheel is mounted on two pieces that support both the stepper motor and an 8mm machine screw that acts as an axle.
The primary material for the wheel was 1/4inch plywood, as it had enough strength to maintain its rigidity but was light enough to not strain the stepper motor too much. I cut out each gear and the 20 slats on a CNC router and then sanded and painted them to make the project look a bit better. The two axle stands were 3D printed with PLA plastic, in addition to the two halves of the limit switch mounts.
There are 5 primary components to the music player: the brain (a Teensy 4), a bank of 8 limit switches, an MPR121 capacitive touch controller, a 20x4 character LCD, and an I2S to analog breakout.
Whenever a limit switch (pulled high) goes to ground, an interrupt is triggered that causes its corresponding drum to play a sound.
Settings can be changed by interacting with capacitive copper pads and then viewing them on the LCD. Both the MPR121 and the LCD are connected via I2C, which helps to free up pins for the 8 switches.
The program starts by setting up the 8 drum sounds and configuring them to output over the I2S line. Interrupts could be created by just copy-pasting the attachInterrupt() function and changing the pins and creating separate ISRs, but that would be inelegant. Rather, an array with pointers to each drum object can be created and then the attachInterruptArg() function can be used to pass in that object pointer to a single ISR that can then call the soundOn() method for that specific object.
The LCD menu works by setting up the first line to display which channel is currently selected, which can be changed by pressing the CHAN pad and then using the +/- buttons to move it up or down.
The second line states which setting is currently being modified, such as speed or pitch. Some items are channel-specific, meaning they only affect a single channel, whereas other ones are global and affect each channel. The last line shows the new value of the setting. Global settings are stored in simple variables, but channel-specific settings are kept in a multidimensional array.
In order to play sounds, a simple waveform is not adequate, and using samples from an SD card would introduce far too much latency. Thankfully, the Teensy audio library has a drum synth class that lets you emulate drum sounds. Each drum can have its pitch, duration, and modulation changed. In order to output up to eight sounds at once, the first four drum objects get connected to mixer1, and the other four are connected to mixer2. The two mixers are connected to a third mixer which then sends the combined waveform into a reverb effect object in order to simulate the faint ringing in a real music box.
Sound data is outputted via the I2S protocol to the Teensy Audio shield which then converts it to an analog signal for a speaker.
Each song can only have 20 distinct intervals, so making the most out of a melody is vital. I went with a simple tune that rises steadily, preceded by a steady thud of base and proceeded by notes that gradually get higher in pitch. In order to make fine adjustments, I simply used the onboard controller to change the pitches and modulations of each channel, and I also changed the tempo of the tune by changing the RPM the wheel spun at.
If I were to go back and modify this project in the future, I would add the ability to also change the instrument, which could let more complex songs be created. I would also be interested in changing to a computer vision system which can interpret black and white dots as notes instead.
Comments