Week 2 Progress Report

This week I tackled what I expected to be the most difficult of the development stage of my project. I have decided to take my project entirely digital (meaning no analog feedback). This approach has many advantages, such as faster response time, regulated level control, advanced harmonic control, etc. However, this approach is also significantly more complicated than the analog version for two reasons: First, it requires real time pitch detection for each string. Not only does this involve fairly complicated and processor-intensive DSP but it also means that inputs from all 6 strings must be sampled independently. Second, this approach requires the synthesis and playback of a guitar string-like waveform. In order to achieve maximum resonance, the timbre of the digitally synthesized wave must be as close as possible to the natural timbre of a guitar string. These are two very large obstacles to overcome, and I solved them both this week.

Sampling and Pitch Detection:

The reason that sampling 6 audio inputs at once is difficult is that the Teensy 3.2 only has one ADC. This means that only one channel of continuous audio can be read in at one time. I overcame this complication by multiplexing 6 analogRead() functions through the single ADC using very precise timing sequences, thus creating my own audio sampling algorithm. This was fairly difficult to figure out, especially because the analogRead() function itself is fairly slow, but once I tested and calculated the precise timing factors (down to 7us), it all came together, allowing me to sample all 6 strings at once and store the samples in a buffer to be processed for pitch detection.

Once the samples buffer fills up, it gets sent to my pitch detection algorithm. The technique I decided on for pitch detection is called Autocorrelation. In a nutshell, autocorrelation works by cutting the buffer in half, overlaying the second half on top of the first, and then comparing (correlating) the two while iterating through increasing delay periods. When the two halves reach a point where they are highly correlated, the algorithm uses the delay period at that point along with the sampling rate to calculate the fundamental period (or frequency). This is of efficiency O(n^2), which is not great but better and more accurate than performing a full FFT or DFT on the buffer because it allows the buffer itself to be smaller (256 samples for roughly 7ms of latency).

Synthesis and Playback

I solved the problem of needing to synthesize the waveform of a guitar string by using the Teensy audio library and a series of 8 sine waves representing the fundamental frequency and harmonic series of a guitar string. I then wrote a simple function that calculates the pitch each sine wave should be based on the fundamental frequency as detected in the sampling phase. These waves are then all summed via the library outputted as PWM signal. PWM requires some analog processing before it is useful. This is because the ultra-high carrier wave needs to be filtered out and then the remaining signal must be amplified. In order to drive my home-made inductor enough to vibrate the string, the gain has to be pretty significant. I am currently using an LM386 with a gain of 200 and some filtering and it is working quite well. The only snag with that is that to apply that much gain the op-amp needs 9v instead of 5v or 3.3v. I will figure out how to deal with that this week.

Here is a video of the sampling and pitch detection:

Leave a comment