Pages: [1]   Go Down
Author Topic: Incoming analog signal to MIDI Out  (Read 1367 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys

I know there are a lot of methods of having an incoming analog signal (let's say from a guitar) and convert to MIDI. Particularly I am more interested in how Stephen Hobley did on his project, as shown here:

http://www.stephenhobley.com/blog/2011/01/24/pitch-and-volume-tracking-midi-interface-for-the-theremin/

I would ask Hobley himself, but he has not responded to my email for weeks so I figured I will ask you guys in deciphering his code.

The Volume data is pretty straightforward, but the pitch detection is what baffles me. Here's the audio component of his project:
http://www.stephenhobley.com/blog/wp-content/uploads/2011/01/schematic_4_web.gif
[the threshold comparator is what I'm focused on now]

According to his code, he takes the pitch preview of the theremin [which is analog) and convert it to square waves and feed it into an interrupt pin in the Atmega328p

Code:
void setup ()
...
...
attachInterrupt(0, sample_freq, RISING);
.....


At this point, it makes sense and I've tried it on the breadboard to confirm it (using a function generator feeding as the  pitch-preview)

Next, after having enough number of samples it will start matching the MIDI note number:

Code:
void loop ()
 
  // We have captured enough samples, time to process...
  if (sample_counter == NO_OF_SAMPLES)
  {
    ProcessSamples();

    // Start sampling again
    sample_counter = 0;
  }
}

Code:
void sample_freq() // Interrupt handler function
{
  if (sample_counter == NO_OF_SAMPLES) //NO_OF_SAMPLES = 5
    return;
   
  if ((sample_counter > 0) && (micros() < samples[sample_counter-1]))
  {
    sample_counter = 0; // Reset and
    return;             // do nothing if we have overflowed.
  }
 
  samples[sample_counter] = micros();
  sample_counter++;
}


Hobley's methods is what throws me off here...

When the function ProcessSample calls out, he takes those 5 samples and take the average of it (?) as shown here:

Code:
unsigned long ProcessSamples()
{
    accumulator =  (samples[1] - samples[0]);
    accumulator += (samples[2] - samples[1]);
    accumulator += (samples[3] - samples[2]);
    accumulator += (samples[4] - samples[3]);
   
    accumulator = accumulator / 4;
   
Then he compares (from what I'm assuming a huge array of period numbers, which I still dont know how he got those numbers) to correspond the right note:

 
Code:
   for (int i = 0; i <69; i++)
    {
      if (accumulator > lower_bound_period[i])
      {
.............................

where

Code:
uint16_t lower_bound_period[]  = {
/*22282,*/ 21052, 19869, 18748, 17696, 16706, 15768, 14880, 14046, 13259,
12515, 11814, 11152, 10525, 9931,  9374,  8849,  8351,  7882,  7442,
7024,  6631,  6260,  5908,  5577,  5264,  4968,  4689,  4426,  4177,
3943,  3722,  3513,  3316,  3130,  2955,  2789,  2632,  2485,  2346,
2214,  2090,  1972,  1862,  1757,  1658,  1565,  1478,  1395,  1317,
1244,  1174,  1107,  1045,  987,   932,   880,   830,   784,   740,
699,   659,   622,   588,   555,   524,   495,   467,   441,   421 
};

Can anyone help me understand what exactly is he doing here? Is there an actual name for this A/D method?
Logged

Montreal
Offline Offline
Faraday Member
**
Karma: 30
Posts: 2602
Per aspera ad astra.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It looks like he is using Look Up Table (LUT) to get a note number from measured frequency.
Data is slightly off, compare to :http://en.wikipedia.org/wiki/Piano_key_frequencies
Other-way, he would have to get 12-th root, which is quite slow on arduino.
Logged

Pages: [1]   Go Up
Jump to: