def freq_from_HPS(sig, fs): """ Estimate frequency using harmonic product spectrum (HPS) """ windowed = sig * blackmanharris(len(sig)) from pylab import subplot, plot, log, copy, show #harmonic product spectrum: c = abs(rfft(windowed)) maxharms = 8 subplot(maxharms,1,1) plot(log(c)) for x in range(2,maxharms): a = copy(c[::x]) #Should average or maximum instead of decimating # max(c[::x],c[1::x],c[2::x],...) c = c[:len(a)] i = argmax(abs(c)) true_i = parabolic(abs(c), i)[0] print 'Pass %d: %f Hz' % (x, fs * true_i / len(windowed)) c *= a subplot(maxharms,1,x) plot(log(c)) show()
def fit_fsr(self, sampling=1e-12): """Estimate fsr using autocorrelation from https://gist.github.com/endolith/255291 Pros: Best method for finding the true fundamental of any repeating wave, even with strong harmonics or completely missing fundamental Cons: Not as accurate, doesn't work for inharmonic things like musical instruments, this implementation has trouble with finding the true peak """ signal = self.lum # Calculate autocorrelation (same thing as convolution, but with one input # reversed in time), and throw away the negative lags signal -= mean(signal) # Remove DC offset corr = fftconvolve(signal, signal[::-1], mode='full') corr = corr[len(corr) / 2:] # Find the first low point d = diff(corr) start = find(d > 0)[0] # Find the next peak after the low point (other than 0 lag). This bit is # not reliable for long signals, due to the desired peak occurring between # samples, and other peaks appearing higher. i_peak = argmax(corr[start:]) + start i_interp = parabolic(corr, i_peak)[0] # print "i_interp: %f" % i_interp self.fsr = i_interp * sampling * 1e9 return self.fsr
def freq_from_HPS(sig, fs): """ Estimate frequency using harmonic product spectrum (HPS) """ windowed = sig * blackmanharris(len(sig)) from pylab import subplot, plot, log, copy, show # harmonic product spectrum: c = abs(rfft(windowed)) maxharms = 8 subplot(maxharms, 1, 1) plot(log(c)) for x in range(2, maxharms): a = copy(c[::x]) # Should average or maximum instead of decimating # max(c[::x],c[1::x],c[2::x],...) c = c[:len(a)] i = argmax(abs(c)) true_i = parabolic(abs(c), i)[0] print 'Pass %d: %f Hz' % (x, fs * true_i / len(windowed)) c *= a subplot(maxharms, 1, x) plot(log(c)) show()
def freq_power_from_fft(sig, fs): # Compute Fourier transform of windowed signal windowed = sig * blackmanharris(CHUNK) fftData = abs(rfft(windowed)) # powerData = 20*log10(fftData) # Find the index of the peak and interpolate to get a more accurate peak i = argmax(fftData) # Just use this for less-accurate, naive version # make sure i is not an endpoint of the bin if i != len(fftData)-1 and i != 0: #print("data: " + str(parabolic(log(abs(fftData)), i))) true_i,logmag = parabolic(log(abs(fftData)), i) # Convert to equivalent frequency freq= fs * true_i / len(windowed) #print("frequency="+ str(freq) + " log of magnitude=" + str(logmag)) if logmag < 0: logmag = 0 return freq,logmag else: freq = fs * i / len(windowed) logmag = log(abs(fftData))[i] if logmag < 0: logmag = 0 #print("frequency="+ str(freq) + "log of magnitude not interp=" + str(logmag)) return freq,logmag
def freq_from_autocorr(sig, fs): """ Estimate frequency using autocorrelation """ # Calculate autocorrelation (same thing as convolution, but with # one input reversed in time), and throw away the negative lags #plt.plot(sig) #plt.xlim([0,2000]) #plt.show() corr = fftconvolve(sig, sig[::-1], mode='full') corr = corr[len(corr)//2:] #plt.plot(corr) #plt.xlim([0,2000]) #plt.show() # Find the first low point d = diff(corr) #plt.plot(d) #plt.xlim([0,2000]) #plt.show() start = find(d > 0)[0] #print "start",start # Find the next peak after the low point (other than 0 lag). This bit is # not reliable for long signals, due to the desired peak occurring between # samples, and other peaks appearing higher. # Should use a weighting function to de-emphasize the peaks at longer lags. peak = argmax(corr[start:]) + start #print peak #plt.plot(corr) #plt.xlim([0,2000]) px, py = parabolic(corr, peak) #print fs,px,fs/px #plt.show() return fs / px
def freq_from_autocorr(sig, fs): """ Estimate frequency using autocorrelation """ # Calculate autocorrelation (same thing as convolution, but with # one input reversed in time), and throw away the negative lags corr = fftconvolve(sig, sig[::-1], mode='full') corr = corr[len(corr) // 2:] # Find the first low point d = diff(corr) start = find(d > 0) if len(start): start = start[0] else: return 0 # Find the next peak after the low point (other than 0 lag). This bit is # not reliable for long signals, due to the desired peak occurring between # samples, and other peaks appearing higher. # Should use a weighting function to de-emphasize the peaks at longer lags. peak = argmax(corr[start:]) + start if (peak >= corr.shape[0] - 1): peak = corr.shape[0] - 2 elif (peak == 0): peak = 1 px, py = parabolic(corr, peak) return fs / px
def getHz(self, soundData, rate): usedata = unpack("%dh" % (len(soundData) / 2), soundData) usedata = np.array(usedata, dtype="h") window = usedata * blackmanharris(len(usedata)) fouriour = np.fft.rfft(window) fouriour = np.delete(fouriour, len(fouriour) - 1) i = np.argmax(abs(fouriour)) true_i = parabolic(np.log(abs(fouriour)), i)[0] return rate * true_i / len(window)
def freq_from_fft(sig, fs): """Estimate frequency from peak of FFT """ # Compute Fourier transform of windowed signal windowed = signal * blackmanharris(len(signal)) f = rfft(windowed) # Find the peak and interpolate to get a more accurate peak i = argmax(abs(f)) # Just use this for less-accurate, naive version true_i = parabolic(log(abs(f)), i)[0] # Convert to equivalent frequency return fs * true_i / len(windowed)
def get_freq_from_fft(self, data, samprate): #Estimate frequency from peak of FFT # Compute Fourier transform of windowed signal windowed = data * blackmanharris(len(data)) f = rfft(windowed) # Find the peak and interpolate to get a more accurate peak i = argmax(abs(f)) # Just use this for less-accurate, naive version true_i = parabolic(log(abs(f)), i)[0] # Convert to equivalent frequency return samprate * true_i / len(windowed)
def Autocorrelation(data): corr = fftconvolve(data, data[::-1], mode='full') # 傅立叶卷积 corr = corr[len(corr)/2:] # 对称取一半 d = np.diff(corr) # 相关性变化情况 if len(find(d > 0)) <= 0: return (-1, -1, None, None) start = find(d > 0)[0] peak = np.argmax(corr[start:]) + start # 相关性最大的位移 frequencey, py = parabolic(corr, peak) # 加权平均位移 strength = np.max(d) # 变化最大值: 强度 return (int(frequencey), strength, corr, d)
def freq_from_fft(signal, fs): """Estimate frequency from peak of FFT """ # Compute Fourier transform of windowed signal windowed = signal * blackmanharris(len(signal)) f = rfft(windowed) # Find the peak and interpolate to get a more accurate peak i = argmax(abs(f)) # Just use this for less-accurate, naive version true_i = parabolic(log(abs(f)), i)[0] # Convert to equivalent frequency return fs * true_i / len(windowed)
def find_first_harmonic(signal, NFFT, sample_rate, noverlap=None): if noverlap is None: noverlap = NFFT // 2 harmonics = [] starts = np.arange(0, len(signal), NFFT - noverlap, dtype=int) # leave windows greater or equal to ndft sample size starts = starts[starts + NFFT < len(signal)] for start in starts: #perform fft for real input in a window window = rfft(signal[start:start + NFFT]) i = argmax(abs(window)) ind = parabolic(log(abs(window)), i)[0] harmonics.append(ind) return harmonics
def Autocorrelation(data): corr = fftconvolve(data, data[::-1], mode='full') # 傅立叶卷积 corr = corr[len(corr) / 2:] # 对称取一半 d = np.diff(corr) # 相关性变化情况 if len(find(d > 0)) <= 0: return (-1, -1, None, None) start = find(d > 0)[0] peak = np.argmax(corr[start:]) + start # 相关性最大的位移 frequencey, py = parabolic(corr, peak) # 加权平均位移 strength = np.max(d) # 变化最大值: 强度 return (int(frequencey), strength, corr, d)
def getFreq(audio, rate): #Filter with Hanning Window window = hann(len(audio)) audio = audio * window #run rfft spectrum = rfft(audio) hertz = 20*scipy.log10(abs(spectrum)) frequency = rfftfreq(len(spectrum)) #find peak of signal #try taking first peak because peaks after give overtones... i = argmax(abs(spectrum)) true_i = int(parabolic(log(abs(spectrum)), i)[0]) #Convert to Frequency return rate * true_i / len(audio)
def getFreq(audio, rate): #Filter with Hanning Window window = hann(len(audio)) audio = audio * window #run rfft spectrum = rfft(audio) hertz = 20 * scipy.log10(abs(spectrum)) frequency = rfftfreq(len(spectrum)) #find peak of signal #try taking first peak because peaks after give overtones... i = argmax(abs(spectrum)) true_i = int(parabolic(log(abs(spectrum)), i)[0]) #Convert to Frequency return rate * true_i / len(audio)
def freq_from_fft(sig, fs): """Estimate frequency from peak of FFT """ f = rfft(data) subplot (224) plot (f) # Find the peak and interpolate to get a more accurate peak i = argmax(abs(f)) # Just use this for less-accurate, naive version print 'i: %f' % i print 'f[i]: %d' % f[i] true_i = parabolic(log(abs(f)), i)[0] print true_i # Convert to equivalent frequency return fs * true_i
def freq_from_autocorr(sig, fs): """Estimate frequency using autocorrelation """ # Calculate autocorrelation (same thing as convolution, but with # one input reversed in time), and throw away the negative lags corr = fftconvolve(sig, sig[::-1], mode='full') corr = corr[len(corr)/2:] # Find the first low point d = diff(corr) start = find(d > 0)[0] # Find the next peak after the low point (other than 0 lag). This bit is # not reliable for long signals, due to the desired peak occurring between # samples, and other peaks appearing higher. # Should use a weighting function to de-emphasize the peaks at longer lags. peak = argmax(corr) px, py = parabolic(corr, peak) return fs * px
def midi_from_file(fileName): signal, fs, enc = wavread(fileName) # Compute Fourier transform of windowed signal windowed = signal * blackmanharris(len(signal)) f = rfft(windowed) # Find the peak and interpolate to get a more accurate peak i = argmax(abs(f)) # Just use this for less-accurate, naive version true_i = parabolic(log(abs(f)), i)[0] # Convert to equivalent frequency freq = fs * true_i / len(windowed) shift = 12*math.log((freq/440),2) midiNum = shift+69 midiInt = int(round(midiNum)) return midiInt
def freq_from_autocorr(sig, fs): """ Estimate frequency using autocorrelation """ # Calculate autocorrelation and throw away the negative lags corr = correlate(sig, sig, mode='full') corr = corr[len(corr) // 2:] # Find the first low point d = diff(corr) start = nonzero(d > 0)[0][0] # Find the next peak after the low point (other than 0 lag). This bit is # not reliable for long signals, due to the desired peak occurring between # samples, and other peaks appearing higher. # Should use a weighting function to de-emphasize the peaks at longer lags. peak = argmax(corr[start:]) + start px, py = parabolic(corr, peak) return fs / px
def main(): data = {"left": 0, "right": 0} task = soundProcessor.getSound(data) task.daemon = True task.start() time.sleep(2) while True: usedata = unpack("%dh" % (len(data["all"]) / 2), data["all"]) usedata = np.array(usedata, dtype="h") window = usedata * blackmanharris(len(usedata)) fouriour = np.fft.rfft(window) fouriour = np.delete(fouriour, len(fouriour) - 1) i = np.argmax(abs(fouriour)) true_i = parabolic(np.log(abs(fouriour)), i)[0] print(44100 * true_i / len(window))
def freq_from_autocorr(sig, fs): """Estimate fundamental frequency using autocorrelation From: https://gist.github.com/endolith/255291 """ # Calculate autocorrelation (same thing as convolution, but with # one input reversed in time), and throw away the negative lags corr = fftconvolve(sig, sig[::-1], mode='full') corr = corr[len(corr) // 2:] # Find the first low point d = np.diff(corr) start = find(d > 0)[0] # Find the next peak after the low point (other than 0 lag). This bit is # not reliable for long signals, due to the desired peak occurring between # samples, and other peaks appearing higher. # Should use a weighting function to de-emphasize the peaks at longer lags. peak = np.argmax(corr[start:]) + start px, py = parabolic(corr, peak) return fs / px
def freq_from_HPS(sig, fs): """ Estimate frequency using harmonic product spectrum (HPS) """ windowed = sig * signal.blackmanharris(len(sig)) from matplotlib.pylab import subplot, plot, log, copy, show c = abs(rfft(windowed)) maxharms = 4 for x in range(2, maxharms): a = copy(c[::x]) # Should average or maximum instead of decimating c = c[:len(a)] i = argmax(abs(c)) true_i = parabolic(abs(c), i)[0] print('Pass %d: %f Hz' % (x, fs * true_i / len(windowed))) c *= a return fs * true_i / len(windowed)
def ultimateFreqAndPowerForData(inputData, byteWidth, sampleRate): ### this must be refactored for the appropiate type of data ### for signed data maxValueForInputData = 2**((byteWidth*8)-1) sampleData = [] for i in range(0,len(inputData), byteWidth): try: sampleData.append(les24toles32Value(inputData[i:i+byteWidth]) * 1.0/maxValueForInputData) except Exception as e: print e.message signal = np.array(sampleData) signalPower = np.sum(np.power(signal,2)) rms = math.sqrt(signalPower/(len(inputData)/byteWidth)) highestdbRep = dbRepresentation(rms) # Compute Fourier transform of windowed signal windowed = signal * blackmanharris(len(signal)) f = np.fft.rfft(windowed) # Find the peak and interpolate to get a more accurate peak i = np.argmax(abs(f)) # Just use this for less-accurate, naive version try: #defensive code around divide by zero issue, basically creating noise np.seterr(all='ignore') a = np.arange(len(f), dtype=np.float) a.fill(10**-10) nf = np.where(f == 0., a, f) i = i if i != 0. else 10**-10 if i > len(nf)-2: i = len(nf) -2 true_i = parabolic(np.log(abs(nf)), i)[0] # Convert to equivalent frequency freqHz = (sampleRate * true_i / len(windowed)) except ValueError: freqHz = 0.0 return {"mainFreq":{"freqHz":freqHz, "dbRep":highestdbRep}, "nextFreq":{"freqHz":"0", "dbRep":"0"}}
def freq_from_fft(channel, fs): """ Estimate frequency from peak of FFT. Parameters ---------- channel : Channel object Channel to be processed fs : int Sampling rate """ # Compute Fourier transform of windowed signal windowed = channel.signal * blackmanharris(len(channel.signal)) f = np.fft.rfft(windowed) channel.fft_y = np.abs(f) # amplitude spectrum channel.fft_x = np.fft.rfftfreq(channel.signal.size, 1 / fs) # Find the peak and interpolate to get a more accurate peak i = np.argmax(abs(f)) true_i = parabolic(np.log(abs(f)), i)[0] # Convert to equivalent frequency return fs * true_i / len(windowed)
def argmax(x): import numpy return parabolic(x, numpy.argmax(x))[0]
def argmax(x): return parabolic(x, numpy.argmax(x))[0]
def argmax(x): return parabolic(x, np.argmax(x))[0]
def freq_from_fft(sig, fs): """Estimate frequency from peak of FFT Pros: Accurate, usually even more so than zero crossing counter (1000.000004 Hz for 1000 Hz, for instance). Due to parabolic interpolation being a very good fit for windowed log FFT peaks? https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html Accuracy also increases with signal length Cons: Doesn't find the right value if harmonics are stronger than fundamental, which is common. """ # Compute Fourier transform of windowed signal windowed = sig * blackmanharris(len(sig)) f = rfft(windowed) # Find the peak and interpolate to get a more accurate peak i = argmax(abs(f)) # Just use this for less-accurate, naive version true_i = parabolic(log(abs(f)), i)[0] # Convert to equivalent frequency return fs * true_i / len(windowed) # def freq_from_autocorr(sig, fs): # """Estimate frequency using autocorrelation # Pros: Best method for finding the true fundamental of any repeating wave, # even with strong harmonics or completely missing fundamental # Cons: Not as accurate, currently has trouble with finding the true peak # """ # # Calculate circular autocorrelation (same thing as convolution, but with # # one input reversed in time), and throw away the negative lags # corr = fftconvolve(sig, sig[::-1], mode='full') # corr = corr[len(corr)/2:] # # Find the first low point # d = diff(corr) # start = find(d > 0)[0] # # Find the next peak after the low point (other than 0 lag). This bit is # # not reliable for long signals, due to the desired peak occurring between # # samples, and other peaks appearing higher. # # Should use a weighting function to de-emphasize the peaks at longer lags. # # Also could zero-pad before doing circular autocorrelation. # peak = argmax(corr[start:]) + start # px, py = parabolic(corr, peak) # return fs / px # filename = sys.argv[1] # print 'Reading file "%s"\n' % filename # signal, fs, enc = flacread(filename) # print 'Calculating frequency from FFT:', # start_time = time() # print '%f Hz' % freq_from_fft(signal, fs) # print 'Time elapsed: %.3f s\n' % (time() - start_time) # print 'Calculating frequency from zero crossings:', # start_time = time() # print '%f Hz' % freq_from_crossings(signal, fs) # print 'Time elapsed: %.3f s\n' % (time() - start_time) # print 'Calculating frequency from autocorrelation:', # start_time = time() # print '%f Hz' % freq_from_autocorr(signal, fs) # print 'Time elapsed: %.3f s\n' % (time() - start_time)