3

I have an arduino attached to a Stradella system Piano Accordion. I have optical sensors on each of the 12 notes of the chords on the left hand. When I play a chord it triggers three sensors. That's ok if I want the synthesiser to play the chord but sometimes I want it to just play the root note; so if I play C major I want it to play just the note C.

In the table below you can see that the triggered sensors for the chord C major is sensors 0,4 and 7. But because they are all triggered at the same time they may not arrive in that order, i.e. they could arrive as 4,0,7 or any combination.

Finding the root note for C major is easy, find the two notes whose difference is 7 and the root is the lower of the two. Same for D and E Major etc. But the higher chords like F major have a high note that wraps round to the bottom again so the numerical difference is not 7 anymore.

           0  1  2  3  4  5  6  7  8  9  10 11
C  Major   X           X        X 
C# Major      X           X        X
D  Major         X           X        X
D# Major            X           X        X
E  Major               X           X        X
F  Major   X              X           X      
F# Major      X              X           X     
G  Major         X              X           X  
G# Major   X        X              X             
A  Major      X        X              X             
A# Major         X        X              X           
B  Major            X        X              X 

Does anyone have any ideas of how I could determine the root notes of these chords fairly cheaply (It's running in a loop at 600 times a second and the arduino is doing a LOT of other stuff).

I'm completely stumped, I've experimented with looping up incrementally until 11 is reached and then starting again from 0 and doing this three times for every chord but it seems messy.

I would also like to be able to resolve the other two rows of buttons on the accordion, the dominant and diminished 7th

These are the four shapes for C, the other 11 notes will be the same shape but shifted to the right until it wraps back to 0 again.

          0 1 2 3 4 5 6 7 8 9 10 11
C Major   X       X     X
C Minor   X     X       X
C 7th     X       X           X
C Dim7th  X     X           X

Any suggestions much apprecciated!.

jason
  • 427
  • 5
  • 20

4 Answers4

3

The difference is still 7 - you must only do all calculations modulo 12. Hence, for F Major, you just have 5,9,12 and modulo 12 this is 5,9,0. Or the other way round: you have 5,9,0 and no difference 7, so just add 12 to the lowest (0) which gives (12) and the base note is then 5.

An even easier was to do this is to take the lower note if you have a difference of 7, but the higher note if you have a difference of 5.

############# Edit:

Another method would be to have a Map(Int, Chord) or an array of 1024 elements, that you simply fill with all known chords. Like above, you already have done the work. The idea is to have 12 bit numbers, and you just shift a 1 so many times to the lft for each number to get the key.

Example:

char * notes[1024];
// earlier, in initialization:
notes[0x221] = "F-Major";
notes[....]  = ....;   // do that for all chords you're interested in
// this are the numbers you get:
int a = 5, b= 9, c=0;    // F Major
int key = (1 << a) | (1 << b) | (1 << c);   // 0b10 0010 0001 = 0x221
char *chord = notes[key];
Ingo
  • 36,037
  • 5
  • 53
  • 100
  • Ah, a moment of clarity! This looks good for the major and minor, great thanks! So by your system I could recognise the 7th by taking the lowest of an interval of 10, or the highest of an interval of 2. The final problem would be the Dim7th. It could be lowest of 9, but the highest of 3 would match a lot of other chords, any ideas? – jason Nov 16 '13 at 15:50
  • @jason You could still use the other method - if there is no chord that makes sense, just add 12 to the lowest number and look if it makes sense then. – Ingo Nov 16 '13 at 15:53
  • Cool, I'm going to accept this as the answer iron out the niggles as I go! Cheers! let you know how I get on! – jason Nov 16 '13 at 15:58
  • I like this, but I don't think it's the simplest solution. – jwdonahue Feb 29 '20 at 22:33
1

Looking at it, I would split the processing in two steps. First, get the lowest tone. If it is not 0, 1 or 2, use the (uniquely identified) chord. If it is one of these three, check which tone is the second lowest.

This only requires one loop (to find the lowest tone) and up to one lookup in the worst case.

Find out the lowest tone being played.
If it is 4 ⇒ D# major and return.
Else if it is 5 ⇒ E major and return.
Else if it is 0 ⇒ 
   check if 4 is being played ⇒ C major and return
         else ⇒ F major
Else if it is 1 ⇒
   check if 5 is being played ⇒ C# major and return
         else ⇒ F# major
Else if it is 2 ⇒ 
   check if 6 is being played ⇒ D major and return
         else ⇒ G major

Knowing the most likely chord, you can also check the third tone if you want to make sure that the chord is currently being played.

Jonas Schäfer
  • 20,140
  • 5
  • 55
  • 69
  • Hi Jonas, Thanks for your quick response, I've edited the question to show the full 12 chords. As you can see unfortunately 4 would be a match for A major as well, still trying to get my head around your response though, not sure I my edit changes anything..J – jason Nov 16 '13 at 15:34
1

I'd create a set (if the language you are using supports that) or just a sorted list (for 3 values I think you can sort with a couple of IFs), and then use that as a key to an hash table to find the chord.

LtWorf
  • 7,286
  • 6
  • 31
  • 45
  • I'm on arduino so I understand I should be able to make sets but I can't see any references to sets and arduino on google. So you're saying I should create a hash table with all 48 chords preprogrammed? – jason Nov 16 '13 at 15:43
  • I am saying that it's what I'd do. Not claiming it's the best possible way. – LtWorf Nov 16 '13 at 23:43
0

Regarding: Does anyone have any ideas of how I could determine the root notes of these chords fairly cheaply...

It looks as if the answers given have already satisfied the need, but I just wanted to offer another perspective, in the event you ever need to expand this to some general application...

An FFT (Fast Fourier Transform) or DFT (Discrete Fourier Transform) could also resolve a collection of frequencies (eg. a chord) into its fundamental frequencies, allowing you to select the root note, or any other component.

There are many implementations, but I have found this one particularly useful. It is open source. There are many examples of how to use FFT/DFT, including this one, and this implementation disscussion.

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87