Morphing waveforms

2010-01-22

Ever since graduation, I’ve had more time to focus on projects that are of personal interest. My C++ music project has become a favorite, as I’ve recently been reunited with my old band.

My first task was to make use of the 88 individually sampled 10-second clips of my upright piano. I used sox to convert them from AIFF to WAV since libsndfile prefers WAV, and proceeded to provide the necessary filters to give it a more realistic feel. Dabbling in IIR filter design isn’t a specialty of mine, but I was able to import some C code and refactor it into a C++ class. Looking over the code really highlighted the semantic differences between the two languages, and allowed me to see where efficiency and readability can be at odds. With the primary low-pass filter class in place, I decided to make a few subclasses to hold precomputed filter coefficients for filter sweeps.

I’m now at the point where I want to sample other instruments such as a Hammond organ. I obtained a sample of a Hammond playing a few notes in the low octave range which were highly periodic, and very suitable for my form of wave-table synthesis which involves storing a single period of the waveform in 96,000 samples in memory and then varying the iteration speed to achieve different pitches. My first instinct was to take a period of the lowest possible note (C0) and stretch it to fit 96,000 samples. This produced harmonically distorted results due to the poor zero-crossing within the sample. Refining my method, I decided to take a higher note (A0) having integer frequency (55 or 110 Hz). Using Cool Edit Pro 2.0 (my editor of choice), I applied the stretch function to the waveform, but ended up with slightly more samples than I needed (96016), so instead I doubled the wave several times using the “adjust / convert sample type” functions until the samples numbered about 55,000. At this point, I told CEP to treat the wave as though the number of samples was equal to the sample rate, and then to convert it up to a rate of exactly 96,000. Problem solved, no distortion, sounds great at varying pitches!

I still need to implement LFOs (simple right?) and high-pass filters. I’ve also recently implemented sub-sine on the low keys as my bass instrument, but it needs tweaking to get the Shepherd-tone effect that I’m seeking.