Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,4 @@ def parabolic_polyfit(f, x, n):
xv = -0.5 * b/a
yv = a * xv**2 + b * xv + c
return (xv, yv)

9 changes: 5 additions & 4 deletions frequency_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
# -*- coding: utf-8 -*-

from __future__ import division
from common import analyze_channels
from common import parabolic as parabolic
from common import analyze_channels, parabolic
from numpy.fft import rfft
from numpy import argmax, mean, diff, log, copy, arange
from matplotlib.mlab import find
from scipy.signal import fftconvolve, kaiser, decimate
from scipy.signal import _next_regular # TODO: will be named _next_opt_len() soon. See https://github.com/endolith/waveform-analyzer/pull/6#1
from time import time



def freq_from_crossings(signal, fs):
"""Estimate frequency by counting zero crossings

Expand Down Expand Up @@ -53,7 +54,7 @@ def freq_from_fft(signal, fs):

# Compute Fourier transform of windowed signal
windowed = signal * kaiser(N, 100)
f = rfft(windowed)
f = rfft(windowed, _next_regular(N))
# Find the peak and interpolate to get a more accurate peak
i_peak = argmax(abs(f)) # Just use this value for less-accurate result
i_interp = parabolic(log(abs(f)), i_peak)[0]
Expand Down Expand Up @@ -103,7 +104,7 @@ def freq_from_hps(signal, fs):
windowed = signal * kaiser(N, 100)

# Get spectrum
X = log(abs(rfft(windowed)))
X = log(abs(rfft(windowed, _next_regular(N))))

# Downsample sum logs of spectra instead of multiplying
hps = copy(X)
Expand Down
8 changes: 5 additions & 3 deletions thd_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
from scipy.signal import kaiser
from numpy.fft import rfft, irfft
from numpy import argmax, mean, log10, log, ceil, concatenate, zeros
from scipy.signal import _next_regular # TODO: will be named _next_opt_len() soon. See https://github.com/endolith/waveform-analyzer/pull/6#1
from common import analyze_channels, rms_flat, parabolic
from A_weighting import A_weight


def THDN(signal, sample_rate):
"""Measure the THD+N for a signal and print the results

Expand All @@ -32,7 +34,7 @@ def THDN(signal, sample_rate):
total_rms = rms_flat(windowed)

# Find the peak of the frequency spectrum (fundamental frequency)
f = rfft(windowed)
f = rfft(windowed, _next_regular(len(windowed)))
i = argmax(abs(f))
true_i = parabolic(log(abs(f)), i)[0]
print 'Frequency: %f Hz' % (sample_rate * (true_i / len(windowed)))
Expand All @@ -43,7 +45,7 @@ def THDN(signal, sample_rate):
f[lowermin: uppermin] = 0

# Transform noise back into the time domain and measure it
noise = irfft(f)
noise = irfft(f)[:len(windowed)]
THDN = rms_flat(noise) / total_rms

# TODO: RMS and A-weighting in frequency domain?
Expand Down Expand Up @@ -73,7 +75,7 @@ def THD(signal, sample_rate):
windowed = signal * kaiser(len(signal), 100)

# Find the peak of the frequency spectrum (fundamental frequency)
f = rfft(windowed)
f = rfft(windowed, _next_regular(len(windowed)))
i = argmax(abs(f))
true_i = parabolic(log(abs(f)), i)[0]
print 'Frequency: %f Hz' % (sample_rate * (true_i / len(windowed)))
Expand Down