From 4437abc01dfdc126b841662b00a4a0e201839e12 Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Sun, 18 Oct 2015 23:33:46 -0700 Subject: [PATCH] update 2 --- lib/__init__.py | 2 +- lib/bq.py | 1 + lib/butterworth.py | 5 ++--- lib/data.py | 8 +++++--- lib/fft.py | 4 ++-- lib/planes.py | 4 +++- lib/plot.py | 1 - lib/smoothfft.py | 32 ++++---------------------------- lib/sweeps.py | 2 +- lib/wav.py | 4 ++-- 10 files changed, 21 insertions(+), 42 deletions(-) diff --git a/lib/__init__.py b/lib/__init__.py index 8e2edb8..c8a39d7 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -45,7 +45,7 @@ def test_filter(ff, A=toA(12), Q=toQ(1), **kwargs): npc = [makemag(*f) for f in cascades['raw']] def neonpink(xs): - print("neonpink(): DEPRECATED") + lament("neonpink(): DEPRECATED.") combined = np.zeros(len(xs)) for f in npc: combined += f(xs) diff --git a/lib/bq.py b/lib/bq.py index 3e48b31..fd338cd 100644 --- a/lib/bq.py +++ b/lib/bq.py @@ -12,6 +12,7 @@ HP1 = lambda A, Q: ((1,0),(1,1)) LS1 = lambda A, Q: ((1,A),(1,1/A)) HS1 = lambda A, Q: ((A,1),(1/A,1)) +# patterns observed, in case some simplification could be done: # a always gets divided by A instead of multiplied # b1 and a1 always /= Q diff --git a/lib/butterworth.py b/lib/butterworth.py index 8472f76..159aa54 100644 --- a/lib/butterworth.py +++ b/lib/butterworth.py @@ -1,7 +1,7 @@ import numpy as np def LPB(n): - # crap ripped from https://github.com/vinniefalco/DSPFilters/blob/master/shared/DSPFilters/source + # via https://github.com/vinniefalco/DSPFilters/blob/master/shared/DSPFilters/source """n-th degree butterworth low-pass filter cascade -3 dB at center frequency.""" @@ -23,7 +23,7 @@ def LPB(n): return series def LPC(n, ripple, type=1): - # crap ripped from https://github.com/vinniefalco/DSPFilters/blob/master/shared/DSPFilters/source + # via https://github.com/vinniefalco/DSPFilters/blob/master/shared/DSPFilters/source # FIXME: type 2 has wrong center frequency? """n-th degree chebyshev low-pass filter cascade @@ -84,4 +84,3 @@ def LPC(n, ripple, type=1): den = (1/-real, 1) series += [(num, den)] return series - diff --git a/lib/data.py b/lib/data.py index 403fb58..e1533cc 100644 --- a/lib/data.py +++ b/lib/data.py @@ -3,6 +3,7 @@ from .bq import * import numpy as np +# as calculated by LPB in butterworth.py _bq2a = 1/.76536686473017945 _bq2b = 1/1.8477590650225735 _bq2a_bw = isqrt2/_bq2a @@ -17,6 +18,7 @@ cascades = { 'raw': [ nf(LP1, 20, 0, 1, 29), nf(HS1, 800, 12, 1, 0), + # i don't use the exact _bq2 coeffecients here for legacy reasons ( 45, HP2( 0, 1.32), 0.5), # roughly estimates ( 45, HP2( 0, 0.54), 0.5), # a 4-pole butterworth highpass nf(LP2, 14000, 0, 1.33, 0), @@ -41,7 +43,7 @@ cascades = { ], # here's the ideas written out: # low (<40) freqs dont contribute much to ears (feel doesnt count.) - # high (>14000) freqs are mostly unheard. 14000 is the top for someone with bad hearing. + # high (>14000) freqs are mostly unheard. # 750 Hz isn't too painful to the ears, but cutting them would give # overly-produced songs not enough gain to hear vocals, so keep it flat. # we're supposedly less sensitive to 1400 Hz, but i need to @@ -60,7 +62,7 @@ cascades = { ( 40, HP2(0, toQ(1.00)), 0.0), (10000, LP1(0, 0), 0.0), ], - # tested against your 227 top-rated songs + # average curve of my 227 favorite songs 'np2': [ nf(LP1, 20, 0, 1, 32), nf(HS1, 800, 9, 1, -4.5), @@ -70,7 +72,7 @@ cascades = { nf(LS2, 38, -9, 1.00, 0), nf(PE2, 64, 4.5, 1.20, 0), ], - # side channel + # same but for the side channel 'np2s': [ nf(LP1, 20, 0, 1, 32), nf(HS1, 800, 9, 1, -4.5), diff --git a/lib/fft.py b/lib/fft.py index c2a7781..a953953 100644 --- a/lib/fft.py +++ b/lib/fft.py @@ -30,11 +30,11 @@ def magnitudes(s, size=8192): for i in range(0, L - 1, int(step)): windowed = s[i:i+win_size]*win power = np.abs(rfft(windowed, size))**2 - # this scraps the nyquist value to get exactly size outputs + # this scraps the nyquist value to get exactly 'size' outputs yield power[0:size] count += 1 - #assert(segs == count) + #assert(segs == count) # this is probably no good in a generator def averfft(s, size=8192): """calculates frequency magnitudes by fft and averages them together.""" diff --git a/lib/planes.py b/lib/planes.py index 8bcd2f4..5f005bf 100644 --- a/lib/planes.py +++ b/lib/planes.py @@ -5,6 +5,8 @@ import sympy as sym def zcgen_py(n, d): zcs = np.zeros(d + 1) + + # expanded from the equation in zcgen_sym zcs[0] = 1 for _ in range(n): for i in range(d, 0, -1): @@ -20,7 +22,7 @@ def zcgen_sym(n, d): coeffs = expr.equals(1) and [1] or expr.as_poly().all_coeffs() return coeffs[::-1] -def s2z_two(b,a,fc,srate,gain=1): +def s2z_two(b, a, fc, srate, gain=1): """ converts s-plane coefficients to z-plane for digital usage. hard-coded for 3 coefficients. diff --git a/lib/plot.py b/lib/plot.py index 813a8f7..23efa67 100644 --- a/lib/plot.py +++ b/lib/plot.py @@ -4,7 +4,6 @@ from matplotlib import ticker def response_setup(ax, ymin=-24, ymax=24, yL=ticker.AutoMinorLocator(3)): ax.set_xlim(20, 20000) ax.set_ylim(ymin, ymax) - #ax.set_yticks(np.arange(ymin, ymax + 1, 6)) ax.set_yticks(tuple(range(ymin, ymax + 1, 6))) ax.yaxis.set_minor_locator(yL) ax.grid(True, 'both') diff --git a/lib/smoothfft.py b/lib/smoothfft.py index 2eec514..a6a031e 100644 --- a/lib/smoothfft.py +++ b/lib/smoothfft.py @@ -1,17 +1,17 @@ -from . import xsp +from . import xsp, lament import numpy as np def smoothfft(xs, ys, bw=1, precision=512): """performs log-lin smoothing on magnitude data, generally from the output of averfft.""" - # TODO: option to extrapolate (pad) fft data + lament("smoothfft(): DEPRECATED; use smoothfft2 instead.") xs2 = xsp(precision) ys2 = np.zeros(precision) log_xs = np.log(xs) for i, x in enumerate(xs2): dist = np.exp(np.abs(log_xs - np.log(x + 1e-35))) window = np.maximum(0, 1 - (dist - bw)) - # at this point you could probably + # at this point we could probably # normalize our *triangular* window to 0-1 # and transform it into *another* windowing function wsum = np.sum(window) @@ -25,7 +25,7 @@ def smoothfft2(xs, ys, bw=1, precision=512, compensate=True): ys2 = np.zeros(precision) log2_xs2 = np.log2(xs2) for i, x in enumerate(xs): - #dist = np.abs(np.log2(xs2/(x + 1e-35)))/bw + # before optimizations: dist = np.abs(np.log2(xs2/(x + 1e-35)))/bw dist = np.abs(log2_xs2 - np.log2(x + 1e-35))/bw #window = np.maximum(0, 1 - dist) # triangle window window = np.exp(-dist**2/(0.5/2)) # gaussian function (non-truncated) @@ -34,27 +34,3 @@ def smoothfft2(xs, ys, bw=1, precision=512, compensate=True): _, temp = smoothfft2(xs, np.ones(len(xs)), bw=bw, precision=precision, compensate=False) ys2 /= temp return xs2, ys2 - -def smoothfft3(xs, ys, bw=1, precision=1024): - # actually this will never work... - # you need to go back to smoothfft2, - # which technically works as-designed, - # and fix the compensation to work with widely-spaced data. - raise Exception("smoothfft3 is broken.") - xs2 = xsp(precision) - ys2 = np.zeros(precision) - step = (xs[1] - xs[0]) - if True: - for i, x in enumerate(xs): - dist = np.abs(xs2 - x) - bw2 = x*bw/2 - window = np.maximum(0, 1 - dist/bw2) - #window = np.minimum(1, np.maximum(0, 1 - (dist - bw))) - ys2 += ys[i]*window - else: - for i, x2 in enumerate(xs2): - dist = np.abs(xs - x2) - window = np.maximum(0, 1 - (dist/step/bw)) - wsum = np.sum(window) - ys2[i] = np.sum(ys*window/wsum) - return xs2, ys2 diff --git a/lib/sweeps.py b/lib/sweeps.py index 4881c85..1e6bbdf 100644 --- a/lib/sweeps.py +++ b/lib/sweeps.py @@ -31,7 +31,7 @@ def tsp(N, m=0.5): # http://www.sound.sie.dendai.ac.jp/dsp/e-21.html if m < 0 or m > 1: - raise Exception("sdfgsdfgsdg") + raise Exception("what are you doinggg") if N < 0: raise Exception("The number of length must be the positive number") diff --git a/lib/wav.py b/lib/wav.py index 4cc7ca1..880c1bb 100644 --- a/lib/wav.py +++ b/lib/wav.py @@ -6,7 +6,7 @@ import scipy.io.wavfile as wav import ewave def wav_smart_read(fn): - lament('DEPRECATED: wav_smart_read; use wav_read instead') + lament('wav_smart_read(): DEPRECATED; use wav_read instead.') srate, s = wav.read(fn) if s.dtype != np.float64: bits = s.dtype.itemsize*8 @@ -14,7 +14,7 @@ def wav_smart_read(fn): return srate, s def wav_smart_write(fn, srate, s): - lament('DEPRECATED: wav_smart_write') + lament('wav_smart_write(): DEPRECATED; use ewave instead.') si = np.zeros_like(s, dtype='int16') bits = si.dtype.itemsize*8 si += np.clip(s*2**(bits - 1), -32768, 32767)