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:
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:
[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
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:
void loop ()
// We have captured enough samples, time to process...
if (sample_counter == NO_OF_SAMPLES)
{
ProcessSamples();
// Start sampling again
sample_counter = 0;
}
}
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:
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:
for (int i = 0; i <69; i++)
{
if (accumulator > lower_bound_period[i])
{
.............................
where
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?
