Hi Paul,
Hi musicians,
Here is a description of my chord player.
I am musician and composer. I play brass instruments and guitar. When composing, I often start with layering some chord progressions to find ideas. Since I don't play keyboards, it's difficult and frustrating. So I decided to build an MIDI instrument to help with playing complex and rich chord progressions. There are plenty of third-party plugins or devices, but they all have limitations : the choice of chords is poor, and a lot of them require to choose a «*root key*» which is a big constrain.
With the my prototype, you can play ready-made chords with one finger. With the right hand, you can play chords and with the left hand you can play a bass line. The choices of chords is large and goes from basic triads to complex jazz extended chords.
THE LAYOUT :
For each root note of the scale, there is a choice of 10 ready-made chords, plus 4 basses. The root notes are organized following the 5th cycle which is more logical when playing chord progressions. A pedal add an alternative choice of 10 chords. Here are the basic functionalities :
- a choice of 20 chord structures per note. From triads to altered chord, suspended, diminished, semi diminished... and "custom" chords.
- 4 basses per note. Root, Maj third, min third, b9.
- 168 force sensitives pads keyboard
- separate MIDI channel for basses and chords
- various knobs to control octaves, volume, chord inversions, velocity range, and a basic arpeggiator
- 12 pots + 12 switches (toggle or momentary) assigned to MIDI CC for controlling software.
- sustain pedal, pitch and mod wheel
- a bank to store "styles". The styles enhance some kinds of chord structure. For instance, the "jazz style" will emphase characteristic chord extensions to give a jazz flavor to the progression. Song writer style will emphase for instance the 9th with the major and minor chords...
THE HARDWARE
To keep the budget low, I have made my own force sensitive pads. I have tested many assemblies and material. I have the best result with Velostat sheets. It is very cheap and easy to cut and glue. Here my "recipe" :
1 : PCB
2 : 1/10 millimeter plastic spacer
3 : Velostat
4 : printed plastic sheet
Result is quite OK. I have reliable and even response. Velostat is a delicate material. If you foil it or get it a bit dirty (finger prints), the readings are uneven.
THE CODE
I use 12 MUXs to read all the pads and knobs. I was worried about latency, but it is really fast. Absolute "real time" feeling. Code is simple, nothing new.
"mux_value[n]
" array stores pads readings. First index specifies the MUX number, second index specifies the channel number. "channel[][] " array stores channels adresses.
I know this could be simpler, but that was my first time dealing with MUXs...
void MuxRead() {
for (short i = 0; i < channels_nb; i++) {
digitalWrite(s0, channel[0]);
digitalWrite(s1, channel[1]);
digitalWrite(s2, channel[2]);
digitalWrite(s3, channel[3]);
mux_value[0] = analogRead(A15); //F# (root notes)
mux_value[1] = analogRead(A16); //B
mux_value[2] = analogRead(A17); //E
mux_value[3] = analogRead(A18); //A
mux_value[4] = analogRead(A19); //D
mux_value[5] = analogRead(A20); //G
mux_value[6] = analogRead(A21); //C
mux_value[7] = analogRead(A22); //F
mux_value[8] = analogRead(A6); //Bb
mux_value[9] = analogRead(A7); //Eb
mux_value[10] = analogRead(A8); //Ab
mux_value[11] = analogRead(A9); //Db
}
}
Then a function detect a "hit", and trigger a chord. Here is the idea :
//cycling through all MUXs readings :
for (short n = 0; n < mux_nb; n ++) {
//pads readings
for (short i = 0; i < pads_nb; i ++)
{
if ( mux_value[n] > (threshold) && hit[n] == 0) {
hit[n] = 1;
playChord(n,i);
}
if ( mux_value[n] < threshold && hit[n] == 1) {
hit[n] = 0;
muteChord(n,i);
}
}
Each chord structure is stored in an array, for instance a MAJ7 chord will be :
MAJ7 [] = {0, 4 , 7, 11};
where numbers represent intervals from the root note 0.
The playChord(n,i) function construct a MIDI message. The indexes n and i of "mux_value[n]" indicates with chord formula to call. The value of "mux_value[n]" gives the velocity (after some basic conditioning o fit the 0-127 MIDI range).
Hope this article will give some ideas !
I will be happy to answer questions if I can (I am quite new to coding).
Have a look at may second project here, which really fun to play with :
Emmanuel