Parabolic Peak Interpolation
Python. I applied interpolation technique to the spectral peak based on fundamental frequency after FFT was taken. It is basically to find a better estimation of the peak by using the max spectral bin (of fundamental), its left and right bins with parabola equation. In other words, it is to fit a parabola onto those frequency bins.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import os import numpy as np import matplotlib.pyplot as plt from scipy.io.wavfile import read def CalculatePeakInterpolation(fileName, startTime = 0.4, threshold = 0.7): #Reading a wav file and converting it to a normalized floating point array #fs: sampling rate of the wav file, x: integer point array if (os.path.isfile(fileName) == False): raise ValueError("Input file is not valid") fs, x = read(fileName) #We only accept mono and 44.1khz audio files for this implementation if (len(x.shape) != 1): raise ValueError("Audio file is not mono") if (fs != 44100): raise ValueError("Sampling rate of input sound is not 44100") xSegment = x[int(startTime* fs):] Xf = np.fft.fft(xSegment)/len(xSegment) #frequency domain after fft mX = abs(Xf) mX = mX[:int(len(Xf)/2)] #amplitude of the first half mXdb = 20 * np.log10(mX) #amplitude in dB #FINDING FUNDAMENTAL FREQUENCY thresholdValue = threshold * max(mXdb) for i in range(len(mXdb)): if( mXdb[i] >= thresholdValue ): bandwidth = i #finding bandwidth, first-hit if (bandwidth < 2): bandwidth = 2 break start = int(bandwidth/2); #start of the fundamental band finish = int(3 * bandwidth/2); #end of the fundamental band peakFreqBin = np.argmax(mX[start:finish]) freq = fs * peakFreqBin / len(mXdb) #FINDING INTERPOLATED FREQUENCY lv = mX[peakFreqBin - 1] #magnitude of left bin rv = mX[peakFreqBin + 1] #magnitude of right bin maxValue = max(mXdb[start:finish]) ifreq = freq + 0.5 * (lv - rv)/(lv - 2 * maxValue + rv); print("Fundamental frequency:", freq) print("Interpolated frequency:", ifreq) return |
I used a strings fragment to test. Sometimes, the second and/or third harmonic might be louder than the fundamental. For example, some of trumpet or guitar string effects. That’s why, I implemented the fundamental frequency finding stage at first. In this audio file, the fundamental is around 1180.3144 Hz. After the interpolation implementation, it shows 1180.3156 Hz. However, this implementation is only for a pedal note (if we use an instrument sound, like I did). As a conclusion, this implementation for the idea is very weak. It will be good to apply this interpolation technique for different manipulations.
References:
[1] Mathematics of the Discrete Fourier Transform, Julius O. Smith III [2] Improving FFT Frequency Measurement Resolution by Parabolic and Gaussian Interpolation, M. Gasior, J.L. Gonzalez [3] Is It Possible for a Harmonic Louder than the Fundamental Frequency