As many of you know, I made some pretty substantial modifications to my Korg Polysix. One of the biggest changes was to replace the keybed to enable aftertouch. To make this happen, I had to replace the Polysix's Key Assigner with an Arduino. It was a lot of work, but once I made the core hardware modifications, I found that I was able to add lots of features to the Polysix, such as: aftertouch and portamento, more interesting detuning for unison mode, a poly-unison mode, a Moog-like single-trigger mode, and a sustain pedal. All of these modifications were effected through software changes on the Arduino.
Since I have made those modifications, I have had some people ask if I could share the software. At first I declined, because I was embarrassed of the poor quality of the code. I also didn't really know how to share it. Then, I learned how to use GitHub. So, I at least know how to share my code now. All I have to do is get over my embarrassment. Well, here we go...
If you want to look at some nasty code for how to replace the Polysix Key Assigner using an Arduino, you can find my GitHub repository at: https://github.com/chipaudette/ArduinoPolySix.
Yes, my code is tortured and very difficult to follow. But, that's what happens when you're just learning how to do this stuff. Sorry. If I were to re-write it from scratch it would look a lot different...but this is what I have now. Maybe you'll find something useful.
Thanks for reading!
Showing posts with label Portamento. Show all posts
Showing posts with label Portamento. Show all posts
Thursday, March 13, 2014
Sunday, April 14, 2013
Portamento Voice Spreading from the Mono/Poly
change_in_note = (desired_note - current_note) / time_constant;current_note = current_note + change_in_note;
In my Polysix, the Arduino's job is to continually looping over each voice to update its pitch (and whether it is "on" or "off"). Based on the last MIDI note received from the keyboard, the Arduino knows what the desired note is for each voice. Because of the portamento, though, we need to transition from the current note up to the desired note. As the Arduino loops over each voice (returning to a given voice every 6 ms or so), it updates the pitch of the voice using the equation above. Since all six voices use the exact some portamento equation, they all slide in the exact same way. Easy enough.
The result of this portamento approach is shown in spectrogram below (time on the horizontal axis, pitch on the vertical axis). This spectrogram was created based on an actual recording from my Polysix with all six voices active and set to a "C". I then step from C1 up to C4. As you can see, the pitch transition is nice and smooth from low to high (nice exponential!). It sounds nice and smooth, too. The problem, though, is that it's too "nice" and too "smooth"...it's a bit boring.
On my Korg Mono/Poly, the portamento sounds much more exciting and engaging. Why? I don't know why. To figure out why, I made a recording of the Mono/Poly and made a spectrogram.
The result of this portamento approach is shown in spectrogram below (time on the horizontal axis, pitch on the vertical axis). This spectrogram was created based on an actual recording from my Polysix with all six voices active and set to a "C". I then step from C1 up to C4. As you can see, the pitch transition is nice and smooth from low to high (nice exponential!). It sounds nice and smooth, too. The problem, though, is that it's too "nice" and too "smooth"...it's a bit boring.
![]() |
| Output from Polysix, Initial Portamento Algorithm. 6 Voices. Smooth Shift from C1 to C4. |
![]() |
| Output from Mono/Poly with Portamento. 4 Voices. Smooth Shift from C1 to C4. |
![]() |
| Zoom to Higher Frequencies Where the Mono/Poly's Voices Are Spread by the Portamento. |
Up at these higher frequencies, the harmonics are finally spread out enough for the spectrogram to have enough resolution to see what's happening. And what do we see? We see that the four individual voices of the Mono/Poly are getting spread out during the slide up to the new note. They aren't playing one uniform pitch during the slide -- they're playing four different pitches during the slide. Eventually, the four voices settle onto the same pitch, but during the transition they're all different. That would certainly make for a more interesting sound!
Looking at the schematic for the Mono/Poly (KLM-354), you can actually see that the designers purposely used different capacitor values in the portamento circuit for each voice. This means that each voice has a different time constant (ie, speed) for its portamento pitch changes. That's cool! Different time constants for each voice? I could do that in my portamento equation!
Looking at the spectrograms for the Mono/Poly, I see that the slowest pitch change takes about 30-50% longer than the fastest pitch change. So, that means that the time constants differ by 30-50%. In my portamento equation, that means that "change_in_note" needs to be scaled different for each voice so that they don't all move together. Below is one way of making the note change be voice dependent with fixed-point math. This will result in the slowest voice taking 42% longer to get to its steady value compared to the fastest voice.
int voice_time_constant = time_constant;
int spread[] = {12 13 14 15 16 17}; //spread the voices!
voice_time_constant = (voice_time_constant * spread[voice_index]) / 12;
change_in_note = (desired_note - current_note) / voice_time_constant
When I implement these equations in my Arduino portamento routine, here's how the Polysix responded. Looks pretty good!
So, how does it sound? You can hear it for yourself in the YouTube movie at the top of this post. I think that it sounds far more exciting and engaging than the original portamento algorithm. I really like the spreading of the voices. To my ears, it sounds fantastic. Does anyone know if other old analog synths purposely spread the voices in this way? Or, was the Mono/Poly unique?
![]() |
| Revised Portamento in my Polysix. 6 Voices. Notice the Spreading of the Voices! |
Next Step: The voice spreading for the portamento made me realize that I could add detuning to my Polysix!
Thursday, March 28, 2013
Polysix - Aftertouch and Portamento Demo
This last week has been an exciting time for my pursuit of adding aftertouch to my Korg Polysix. As you know by now, I *really* want aftertouch vibrato on my Polysix...so a while back, I ordered a bunch of parts and dived in. I've been posting about my progress. In my last post, I described the electronics elements that I used to implement the arbitrary pitch bending that would allow for my aftertouch-driven vibrato. As a bonus, having arbitrary pitch control also enabled me to add portamento to my Polysix, which is another effect that I absolutely love. So, without further ado, now that I've put her back together, here's my first demo of what she can do...
How did I make this happen? Well, the block diagram below shows the elements. I bought an aftertouch-enabled Fatar keybed from Keyparts UK. I bought their custom keyscanner, too, which scans the keybed and generates MIDI messages. I then use an Arduino Mega to parse the MIDI messages and to drive the Polysix's electronics. It interfaces with the Polysix by replacing the Intel 8049 microprocessor that is at the heart of the Polysix's "Key Assigner" circuit. This this digital interface, I can control what note they Polysix is sounding. To get the arbitrary pitch bending for the aftertouch vibrato and for the portamento, I generate an analog pitch control voltage (CV) using a digital-to-analog converter (DAC) from Adafruit. I inject that signal at a pitch CV summing node that it already built into the Polysix. After writing a bunch of code to run on the Arduino and after debugging these hardware elements, she works pretty well!
For a user interface, I'll eventually need to add some switches and knobs to the front panel of the Polysix. For the moment, though, I've chosen to re-purpose the knob and switches that are supposed to be used to control the arpeggiator. Since these particular elements are scanned by the Polysix's Key Assigner, and since I just replaced the Key Assigner with my Arduino, I now have total control over these particular user interface elements...so, I can make them do whatever I want. For the moment, I'm going to use them for my aftertouch and portamento.
As you can see in the image below, I chose to make the arpeggiator "Speed" knob control my software LFO, which is driving my aftertouch vibrato. The blinking of the LED still works to show the speed of my aftertouch vibrato! I then use the arpeggiator "Range" switch to set the sensitivity of the aftertouch response. Portamento is activated or deactivated using the "Latch" switch, while the amount of portamento is set using the "Arpeggiator Mode" switch. Now I'm not saying that this is an intuitive user interface, but it sure is nice being able to use these elements to control my new features without having to cut into my Polysix panel.
So, I'm pretty excited about how she's working. There are certainly more tweaks and adjustments to make, but the basics are all in place. In fact, now that it's working, I don't seem to spend any time tweaking the electronics anymore...I just spend all my time playing. I guess that's kinda the point, though. :)
More updates later...when I get tired of playing!
Update: Here's more info on re-using the arpeggiator "Speed" knob to control the aftertouch vibrato speed
Update: Mounting the Arduino in the Polysix
Update: Tuning the Aftertouch Response Curves
Update: Tuning the Portamento Based on the Mono/Poly
Update: Adding detuning to the Polysix
Update: Added a sustain pedal to the Polysix
Update: I shared my Arduino code here
Update: I added Velocity Sensitivity to my Polysix.
How did I make this happen? Well, the block diagram below shows the elements. I bought an aftertouch-enabled Fatar keybed from Keyparts UK. I bought their custom keyscanner, too, which scans the keybed and generates MIDI messages. I then use an Arduino Mega to parse the MIDI messages and to drive the Polysix's electronics. It interfaces with the Polysix by replacing the Intel 8049 microprocessor that is at the heart of the Polysix's "Key Assigner" circuit. This this digital interface, I can control what note they Polysix is sounding. To get the arbitrary pitch bending for the aftertouch vibrato and for the portamento, I generate an analog pitch control voltage (CV) using a digital-to-analog converter (DAC) from Adafruit. I inject that signal at a pitch CV summing node that it already built into the Polysix. After writing a bunch of code to run on the Arduino and after debugging these hardware elements, she works pretty well!
![]() |
| How I'm Implementing Aftertouch and Portamento |
As you can see in the image below, I chose to make the arpeggiator "Speed" knob control my software LFO, which is driving my aftertouch vibrato. The blinking of the LED still works to show the speed of my aftertouch vibrato! I then use the arpeggiator "Range" switch to set the sensitivity of the aftertouch response. Portamento is activated or deactivated using the "Latch" switch, while the amount of portamento is set using the "Arpeggiator Mode" switch. Now I'm not saying that this is an intuitive user interface, but it sure is nice being able to use these elements to control my new features without having to cut into my Polysix panel.
![]() |
| Re-purposing the Arpeggiator Controls for Use with my Aftertouch Vibrato and my Portamento |
More updates later...when I get tired of playing!
Update: Here's more info on re-using the arpeggiator "Speed" knob to control the aftertouch vibrato speed
Update: Mounting the Arduino in the Polysix
Update: Tuning the Aftertouch Response Curves
Update: Tuning the Portamento Based on the Mono/Poly
Update: Adding detuning to the Polysix
Update: Added a sustain pedal to the Polysix
Update: I shared my Arduino code here
Update: I added Velocity Sensitivity to my Polysix.
Labels:
Aftertouch,
Keybed,
Korg,
Mod,
Polysix,
Portamento,
Video
Saturday, March 23, 2013
Polysix - Arduino and DAC to Bend the Pitch
Earlier in the week, I'd made good progress on getting the new keybed and keyscanner into shape so that it could drive my Korg Polysix via an Arduino. While it was exciting to simply get the keybed to work in the Polysix, that was not really my goal. My real goal is to use the new keybed to enable aftertouch (and eventually velocity sensitivity) in my Polysix. Now is the time when I make the bits between the Arduino and the Polysix so that the aftertouch actually does something. This is where I make the Arduino have arbitrary control over the pitch of the Polysix's voices.
| Creation is a Messy Process! |
The first step is to make sure that I have a clear idea of what my approach is going to be for the aftertouch to command pitch on the Polysix. Below is a block diagram showing the major components that I settled on and how they connect.
Listening for MIDI Aftertouch: User, of course, is interacting with the keyboard via the keybed. The keybed is connected to the keyscanner (both from Keyparts UK), which looks for which notes are pressed on the keybed. The keyscanner outputs the notes via a MIDI stream, which is received by an Arduino Mega. The MIDI stream includes the "note on" and the "note off" messages, as one would expect. The keyscanner, though, also reads the aftertouch pressure sensor built into the keybed. Therefore, the MIDI stream also contains the aftertouch commands. So, after getting the keybed and keyscanner and Arduino hooked together, I used the Arduino to listen to the MIDI stream to ensure that the aftertouch messages were present. They weren't. After exchanging a few emails with the good folks at Keyparts, they sent me a new software build for the keyscanner (uploaded to the keyscanner using a very nice and very simple method via USB), which solved the problem.
Aftertouch for Vibrato: With the aftertouch messages successfully reaching the Arduino, now the question is what to do with the messages. In modern synths, the aftertouch can be mapped to a range of functions. For me, I want to start simple -- I just want the aftertouch to create vibrato, much like what the mod wheel currently does. The key is that I somehow need to command a smoothly-changing pitch from the Polysix. I could implement this in a whole bunch of ways (and I even tried a couple). Instead of going through the whole list that I came up with, I'm just going to talk about what ended up being successful.
Polysix Pitch CV: First, let's talk about how the stock Polysix creates each note's pitch. In the polysix, the sound that you hear starts with the VCOs (one for each voice). The VCO is told what pitch to create via an analog voltage signal that is between 0 to +5V. This is the "Pitch CV". In a stock Polysix, the 8049 key assigner has 8 output pins, which are connected to an R-2R ladder circuit (a type of digital-to-analog converter) to create the Pitch CV (see schamtic below). For each note being played by the Polysix, the 8 output pins of the 8049 are set in a particular combination of high (5V) or low (0V) states so that the correct CV value is created for the pitch that you want. While it is a very nice system, it can only generate pitches that are precisely on the note you want -- it cannot create any pitches that are in-between notes. As a result, I cannot exploit this circuitry to create the smoothly-varying pitches that I want for my aftertouch.
DAC for Adjusting Pitch: My solution is to use my own digital-to-analog converter (DAC) to create as smoothly-varying as a Pitch CV as I can. Granted, any DAC can only produce discrete voltages, but if the DAC has sufficient resolution (enough bits) then your ear will be tricked into hearing smoothly-varying pitch. For expediency, I chose to use this product from Adafruit, which is an MCP4725 12-bit DAC mounted on a nice break-out board. It's a fine device, but the best part is that Adafruit provides an easy-to-use software library for use with the Arduino. It took zero debugging to get this to work.
DAC to Generate Pitch CV: Ideally, I would have been able to use the DAC alone to be my sole device for create the Pitch CV in the Polysix. In theory, it should have made the R-2R ladder unnecessary. Unfortunately, when I actually tried to use the DAC this way, the pitches didn't sound right and weren't stable as I'd like. So, either 12-bits isn't enough resolution for the full 10 octave span, or my use of it wasn't quite right. Regardless, I abandoned the use of the DAC as sole generator of the Pitch CV and went to a hybrid approach.
Using both the DAC and the R-2R Ladder: In my hybrid approach, I return to using the R-2R ladder for the main part of the Pitch CV and use the DAC to provide a tweak to the Pitch CV to bend the pitch one way or the other. To implement this hybrid approach, I needed to find a summing junction in the Polysix circuit that could be used to mix the DAC's CV with the R-2R's CV. After trying a bunch of spots (including where the bend wheel injects its signal), I settled on injecting the DAC CV right after the R-2R ladder, at the junction of R33 and R34 (see schematic above).
Connect via 10K Resistor: An important detail is that the 0-5V DAC signal must connected to this location via its own 10K resistor. This makes the electrical summing at this junction scale correctly. The reason that you need a 10K is that, for simplicity, I'd like our 0-5V DAC output to have the same pitch scaling as the 0-5V output of the R-2R ladder. Since the R-2R ladder connects to this summing junction via 10K, then we should connect via 10K, too. A second reason for the 10K is that the R-2R ladder uses +5V to represent the lowest note and 0V to represent the highest note. So, we can call +5V to be the reference voltage with the higher pitches going down from there. This is fine except that the VCOs can't work with that signal. They need something more like 0V with higher pitch going up from there. So, the designers included this summing junction using the -15V to strip off the +5V reference (see how the ratio of 10K to 30K is important!) and, by entering at the "-" input, the sign of the CV gets flipped. It just so happens that this summing junction is a great place for us to inject our DAC signal as well...as long as we connect via 10K and as long as we make our DAC output with a 5V reference where increasing pitch requires the DAC to put out a lower voltage value. The 10K resistor is easy, and the rest we do in software on the Arduino.
Wiring it All Together: The picture above shows the messy real-world wiring for all of these bits and pieces. It shows the rainbow-colored ribbon of wires going from the Arduino to the 8049 socket. It also shows the DAC signal getting injected at R33/R34 via the black clip-lead. Sure, it's ugly, but it works! Well, I should say that, after a whole bunch of debugging of my software whatnot, it works! I can receive MIDI messages from the keyscanner, interpret them in the Arduino, command the main part of the pitch via the 8049 socket, and command pitch adjustments (such as vibrato) via the DAC. Nice!
Next Steps: As shown in the very first picture at the top of this post, my system may function, but it is barely holding itself together. Also, you'll notice that I've not yet included any demos...that's because there is still a big distance between being able to generate arbitrary pitches (including those critical in-between pitches) and getting a useful aftertouch-driven vibrato. So, in my next posts, I'll talk about implementing the aftertouch vibrato (with portamento as a bonus!) and about my approach for cleaning up all that wiring so that the installation is a bit more permanent. Stay tuned!
Update: Here's a demo once the synth was buttoned-up for the first time
Update: Mounting the Arduino in the Polysix
Update: The flexibility of this system also let me add detuning to my Polysix
![]() |
| Here's How I Am Implementing Aftertouch |
Aftertouch for Vibrato: With the aftertouch messages successfully reaching the Arduino, now the question is what to do with the messages. In modern synths, the aftertouch can be mapped to a range of functions. For me, I want to start simple -- I just want the aftertouch to create vibrato, much like what the mod wheel currently does. The key is that I somehow need to command a smoothly-changing pitch from the Polysix. I could implement this in a whole bunch of ways (and I even tried a couple). Instead of going through the whole list that I came up with, I'm just going to talk about what ended up being successful.
Polysix Pitch CV: First, let's talk about how the stock Polysix creates each note's pitch. In the polysix, the sound that you hear starts with the VCOs (one for each voice). The VCO is told what pitch to create via an analog voltage signal that is between 0 to +5V. This is the "Pitch CV". In a stock Polysix, the 8049 key assigner has 8 output pins, which are connected to an R-2R ladder circuit (a type of digital-to-analog converter) to create the Pitch CV (see schamtic below). For each note being played by the Polysix, the 8 output pins of the 8049 are set in a particular combination of high (5V) or low (0V) states so that the correct CV value is created for the pitch that you want. While it is a very nice system, it can only generate pitches that are precisely on the note you want -- it cannot create any pitches that are in-between notes. As a result, I cannot exploit this circuitry to create the smoothly-varying pitches that I want for my aftertouch.
![]() |
| R-2R Ladder Used by the Polysix to Make Each Note's Pitch Control Voltage (CV) |
DAC to Generate Pitch CV: Ideally, I would have been able to use the DAC alone to be my sole device for create the Pitch CV in the Polysix. In theory, it should have made the R-2R ladder unnecessary. Unfortunately, when I actually tried to use the DAC this way, the pitches didn't sound right and weren't stable as I'd like. So, either 12-bits isn't enough resolution for the full 10 octave span, or my use of it wasn't quite right. Regardless, I abandoned the use of the DAC as sole generator of the Pitch CV and went to a hybrid approach.
Using both the DAC and the R-2R Ladder: In my hybrid approach, I return to using the R-2R ladder for the main part of the Pitch CV and use the DAC to provide a tweak to the Pitch CV to bend the pitch one way or the other. To implement this hybrid approach, I needed to find a summing junction in the Polysix circuit that could be used to mix the DAC's CV with the R-2R's CV. After trying a bunch of spots (including where the bend wheel injects its signal), I settled on injecting the DAC CV right after the R-2R ladder, at the junction of R33 and R34 (see schematic above).
Connect via 10K Resistor: An important detail is that the 0-5V DAC signal must connected to this location via its own 10K resistor. This makes the electrical summing at this junction scale correctly. The reason that you need a 10K is that, for simplicity, I'd like our 0-5V DAC output to have the same pitch scaling as the 0-5V output of the R-2R ladder. Since the R-2R ladder connects to this summing junction via 10K, then we should connect via 10K, too. A second reason for the 10K is that the R-2R ladder uses +5V to represent the lowest note and 0V to represent the highest note. So, we can call +5V to be the reference voltage with the higher pitches going down from there. This is fine except that the VCOs can't work with that signal. They need something more like 0V with higher pitch going up from there. So, the designers included this summing junction using the -15V to strip off the +5V reference (see how the ratio of 10K to 30K is important!) and, by entering at the "-" input, the sign of the CV gets flipped. It just so happens that this summing junction is a great place for us to inject our DAC signal as well...as long as we connect via 10K and as long as we make our DAC output with a 5V reference where increasing pitch requires the DAC to put out a lower voltage value. The 10K resistor is easy, and the rest we do in software on the Arduino.
![]() |
| Real-World Implementation of Hybrid Pitch Control Via the 8049 Pins Plus DAC |
Next Steps: As shown in the very first picture at the top of this post, my system may function, but it is barely holding itself together. Also, you'll notice that I've not yet included any demos...that's because there is still a big distance between being able to generate arbitrary pitches (including those critical in-between pitches) and getting a useful aftertouch-driven vibrato. So, in my next posts, I'll talk about implementing the aftertouch vibrato (with portamento as a bonus!) and about my approach for cleaning up all that wiring so that the installation is a bit more permanent. Stay tuned!
Update: Here's a demo once the synth was buttoned-up for the first time
Update: Mounting the Arduino in the Polysix
Update: The flexibility of this system also let me add detuning to my Polysix
Labels:
Aftertouch,
Arduino,
Keybed,
Korg,
Polysix,
Portamento
Subscribe to:
Posts (Atom)









