Lab 5

Matlab/Python: Rudimentary Pitch Tracker

For your final Matlab assignment, we’re going to build a very basic pitch-tracker / resynthesizer. Our goal is to be able to take a monophonic (one note at a time) input file and generate a digital version that copies the original.

We will do this all in a single function, which will process the input signal in chunks, or blocks, and write to output a sawtoothTone that follows the loudest frequency in each block:

[output] = trackPitch(input, fs, windowSize)
input is the original source as a vector
fs is the original sample rate
windowSize is the size of the blocks we’ll break the input into to analyze and resynthesize, in samples. This is sometimes also called ‘blocksize’ or ‘hopsize.’ The value you choose affects the resolution of the spectrum you can generate - the larger, the more accurately you can track the correct frequency. However, it also determines the temporal resolution of the resynthesized output - the pitch of the output will only change each windowSize samples.

These are the steps you will need to follow to build your trackPitch() function:

  • Create a for loop that repeats floor(length(input)/windowSize) times (we won’t worry about any extra samples we might be missing at the end).
  • For each iteration of the for loop, we need to get a block of the input signal. For example, for the first repetition we want block = input(1:windowSize) in Matlab or block = input[0:windowSize] in Python, for the second iteration we want block = input(windowSize+1:2 * windowSize) in Matlab or block = input[windowSize:2 * windowSize] in Python, and so forth. How can we use our for loop to get the right block based on what number iteration we are on?
  • Next, we use our getSpectrum() function from lab 3 on that block. We want to get the loudest frequency in that block, so use [M,I] = max(Y), where Y is the Y returned from getSpectrum(). The I value will be the index of the biggest value in Y, so we are looking for the corresponding value in the Ffrom getSpectrum(), which will be F(I).
  • Generate one block of your output sawtooth signal for the current iteration of your for loop. There are two ways you can do this:
    • The easier (albeit slower and less correct) way to do this is to append a sawtooth at the frequency we found to output using the [A,B] notation in Matlab or the A.append(B) notation in Python, which will concatenate vectors A and B. You’ll need to create an empty output vector before the for loop with output = []. Then we can recursively append a sawtooth to our output on each iteration of the for loop by typing output = [output, sawtoothTone(fs, F(I), 0, windowSize/fs, 8)]; or output.append(sawtoothTone(fs, F(I), 0, windowSize/fs, 8)) (Here I’ve used 8 harmonics in my sawtooth tone, but feel free to use however many you want).
    • The cleaner and faster way to do this is to create the correct length output vector before your for loop (hint: use zeros() or np.zeros()), and then use the same indexing within your for loop that you use to access samples in the input to assign the sawtoothTone() you generate for that block to your output.
  • Either way, you should end up with a continuous sawtooth wave output that follows the pitch of your original input.

Once you’re done with your trackPitch() function, make a short recording (10-15 seconds) of yourself singing or playing a monophonic instrument (using Garageband, Audacity, or whatever you wish, talk to Mark if you need help doing this) and use trackPitch() to generate a digital sawtooth version. Experiment with different power of 2 values for windowSize to see what gives you the best balance of frequency and time resolution.

Matlab/Python Deliverables:

Submit your trackPitch() function along with your original recorded .wav file and generated digital sawtooth version. Report the value you used for windowSize for your final output in a comment in your function. You do not need to submit a separate Matlab script.

This lab is due Friday, May 15th by 10:30am.

Lecture

Fridays, 10:30 AM - 12:20 PM
CCRMA Classroom (Knoll 217)

Lab

Tuesdays, 6:00 - 7:50 PM
CCRMA Classroom (Knoll 217)

Office Hours

Monday 3:30-5:30 PM
Thursday 4:30-5:30
CCRMA Ballroom

Questions

Post on Piazza

Instructors

Poppy Crum
Instructor
poppy(at)stanford(dot)edu

Cara Turnbull
Teaching Assistant
cmt802(at)stanford(dot)edu