diff --git a/lib/__init__.py b/lib/__init__.py index 114d04e..c835149 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,7 +1,3 @@ -import numpy as np -#from IPython.display import display -from matplotlib.pylab import show - from .util import * from .bq import * from .data import * @@ -14,6 +10,9 @@ from .planes import * from .fft import * from .bs import * +import numpy as np +from matplotlib.pylab import show + def analog(b, a): import sympy as sym w,s = sym.symbols('w s') @@ -35,27 +34,18 @@ def test_filter_raw(ba, fc=1000, gain=0, precision=4096): fig, ax = new_response(ymin=-24, ymax=24) xs = xsp(precision) ax.semilogx(xs, makemag(fc, ba, gain)(xs)) - show(fig) def test_filter(ff, A=toA(12), Q=toQ(1), **kwargs): test_filter_raw(ff(A, Q), **kwargs) -npc = [makemag(*f) for f in cascades['raw']] def neonpink(xs): lament("neonpink(): DEPRECATED; use tilter2(xs, 'raw') instead.") - combined = np.zeros(len(xs)) - for f in npc: - combined += f(xs) - return combined + return tilter2(xs, 'raw') def c_render(cascade, precision=4096): # TODO: deprecate in favor of tilter2 (which also needs to be renamed) xs = xsp(precision) - ys = np.zeros_like(xs) - c = [makemag(*f) for f in cascade] - for f in c: - ys += f(xs) - return xs, ys + return xs, tilter2(xs, cascade) def c_render2(xs, cascade, phase=False): """c_render optimized and specifically for first/second-order filters""" @@ -87,10 +77,10 @@ def c_render2(xs, cascade, phase=False): ys = degrees_clamped(ys) return ys -def firize(xs, ys, n=4096, srate=44100, plot=None): +def firize(xs, ys, n=4096, srate=44100, ax=None): import scipy.signal as sig - if plot: - plot.semilogx(xs, ys, label='desired') + if ax: + ax.semilogx(xs, ys, label='desired') xf = xs/srate*2 yg = 10**(ys/20) @@ -99,40 +89,29 @@ def firize(xs, ys, n=4096, srate=44100, plot=None): b = sig.firwin2(n, xf, yg, antisymmetric=True) - if plot: + if ax: _, ys = sig.freqz(b, worN=xs/srate*tau) ys = 20*np.log10(np.abs(ys)) - plot.semilogx(xs, ys, label='FIR ({} taps)'.format(n)) - plot.legend(loc=8) + ax.semilogx(xs, ys, label='FIR ({} taps)'.format(n)) + ax.legend(loc=8) return b def tilter(xs, ys, tilt): """tilts a magnitude plot by some decibels, or by equalizer curve.""" lament("tilter(): DEPRECATED; use ys -= tilter2(xs, tilt) instead.") - if tilt == 'neon': - noise = neonpink(xs) - elif type(tilt) is str: - noise = np.zeros(len(xs)) - c = [makemag(*f) for f in cascades[tilt]] - for f in c: - noise += f(xs) - elif isinstance(tilt, int) or isinstance(tilt, float): - noise = tilt*(np.log2(1000) - np.log2(xs)) - else: - noise = np.zeros(xs.shape) - return xs, ys - noise + return xs, ys - tilter2(xs, tilt) def tilter2(xs, tilt): - if type(tilt) is str: - noise = np.zeros(len(xs)) - c = [makemag(*f) for f in cascades[tilt]] + noise = np.zeros(xs.shape) + if isinstance(tilt, str) and tilt in cascades: + tilt = cascades[tilt] + if isinstance(tilt, list): + c = [makemag(*f) for f in tilt] for f in c: noise += f(xs) elif isinstance(tilt, int) or isinstance(tilt, float): noise = tilt*(np.log2(1000) - np.log2(xs + 1e-35)) - else: - noise = np.zeros(xs.shape) return noise from .plotwav import * diff --git a/lib/bq.py b/lib/bq.py index b2610ec..d9198bc 100644 --- a/lib/bq.py +++ b/lib/bq.py @@ -2,6 +2,7 @@ import numpy as np import scipy.signal as sig from .util import * +from .planes import s2z bq_run = lambda bq, xs: sig.lfilter(*bq, x=xs, axis=0) diff --git a/lib/bs.py b/lib/bs.py index d8bf299..1490a41 100644 --- a/lib/bs.py +++ b/lib/bs.py @@ -55,7 +55,6 @@ def BS_plot(ys, g10=None, g70=None, threshold=None, fig=None, ax=None): ax.xlabel('loudness (LKFS)') ax.ylabel('probability') fig.set_size_inches(10,4) - show() xs = np.arange(len(ys)) #ax.plot(xs, ys, color='#066ACF', linestyle=':', marker='d', markersize=2) diff --git a/lib/plotwav.py b/lib/plotwav.py index 90df7e2..23b2b57 100644 --- a/lib/plotwav.py +++ b/lib/plotwav.py @@ -1,45 +1,11 @@ # this is a bunch of crap that should really be reduced to one or two functions from . import wav_read, normalize, averfft, tilter2, smoothfft2, firize -from . import new_response, show, convolve_each, monoize, count_channels +from . import new_response, convolve_each, monoize, count_channels import numpy as np -def plotwavsmooth(fn, ax, tilt=None, bw=1, size=8192, raw=False, fix=False, smoother=smoothfft2, **kwargs): - s, srate = wav_read(fn) - - s, rms = normalize(s, srate) - sm = monoize(s) - ss = monoize(s*np.array((1, -1))) - - xs_raw = np.arange(0, srate/2, srate/2/size) - ys_raw = averfft(sm, size=size) - - # tilting beforehand is negligible besides lowest frequencies, but eh - if tilt is not None: - ys_raw -= tilter2(xs_raw, tilt) - - xs, ys = smoother(xs_raw, ys_raw, bw=bw) - - if not 'label' in kwargs: - kwargs['label'] = fn - - if raw: - ax.semilogx(xs_raw, ys_raw, **kwargs) - ax.semilogx(xs, ys, **kwargs) - - if not fix: return - - fno = fn[:-4]+"-proc.wav" - fir = firize(xs, -ys, srate=srate) - sf = convolve_each(s/8, fir, mode='same') - - import ewave - with ewave.open(fno, 'w', sampling_rate=srate, nchannels=count_channels(sf)) as f: - f.write(sf) - print('wrote '+fno) - -def plotfftsmooth(s, srate, ax, bw=1, tilt=None, size=8192, window=0, raw=False, **kwargs): +def plotfftsmooth(s, srate, ax=None, bw=1, tilt=None, size=8192, window=0, raw=False, **kwargs): sm = monoize(s) xs_raw = np.arange(0, srate/2, srate/2/size) @@ -49,78 +15,69 @@ def plotfftsmooth(s, srate, ax, bw=1, tilt=None, size=8192, window=0, raw=False, xs, ys = smoothfft(xs_raw, ys_raw, bw=bw) - if raw: ax.semilogx(xs_raw, ys_raw, **kwargs) - ax.semilogx(xs, ys, **kwargs) + if ax: + if raw: ax.semilogx(xs_raw, ys_raw, **kwargs) + ax.semilogx(xs, ys, **kwargs) return xs, ys -def plotwav2(fn, ax, bw=1, size=8192, raw=False, fix=False, - smoother=smoothfft2, side_compensate=9, **kwargs): +def plotwavinternal(sm, ss, srate, bw=1, size=8192, smoother=smoothfft2): + xs_raw = np.arange(0, srate/2, srate/2/size) + ys_raw_m = averfft(sm, size=size) + ys_raw_s = averfft(ss, size=size) + + # tilting beforehand is negligible besides lowest frequencies, but eh + ys_raw_m -= tilter2(xs_raw, 'np2') + ys_raw_s -= tilter2(xs_raw, 'np2s') + + if bw <= 0: + return xs_raw, xs_raw_m, xs_raw_s + + xs, ys_m = smoother(xs_raw, ys_raw_m, bw=bw) + xs, ys_s = smoother(xs_raw, ys_raw_s, bw=bw) + + return xs, ys_m, ys_s + +def plotwav2(fn, bw=1, size=8192, fix=False, + smoother=smoothfft2, **kwargs): s, srate = wav_read(fn) s, rms = normalize(s, srate) sm = monoize(s) - ss = monoize(s*np.array((1, -1))) + if s.shape[1] == 2: + ss = monoize(s*np.array((1, -1))) + else: + ss = np.zeros(len(s)) - xs_raw = np.arange(0, srate/2, srate/2/size) - ys_raw = averfft(sm, size=size) - ys_raw_side = averfft(ss, size=size) + xs, ys_m, ys_s = plotwavinternal(sm, ss, srate, bw, size, smoother) - # tilting beforehand is negligible besides lowest frequencies, but eh - ys_raw -= tilter2(xs_raw, 'np2') - ys_raw_side -= tilter2(xs_raw, 'np2s') + side_gain = np.average(ys_s) - np.average(ys_m) - xs, ys = smoother(xs_raw, ys_raw, bw=bw) - xs, ys_side = smoother(xs_raw, ys_raw_side, bw=bw) + if fix: + fno = fn[:-4]+"-proc.wav" - if not 'label' in kwargs: - kwargs['label'] = fn + fir_m = firize(xs, -ys_m, srate=srate) + fir_s = firize(xs, -ys_s, srate=srate) + smf = convolve_each(sm/8, fir_m, mode='same') + ssf = convolve_each(ss/8, fir_s, mode='same') + ssf *= 10**(side_gain/20) + sf = np.array((smf + ssf, smf - ssf)).T - if raw: - ax.semilogx(xs_raw, ys_raw, **kwargs) - ax.semilogx(xs_raw, ys_raw_side + side_compensate, **kwargs) - ax.semilogx(xs, ys, **kwargs) - ax.semilogx(xs, ys_side + side_compensate, **kwargs) + import ewave + with ewave.open(fno, 'w', sampling_rate=srate, nchannels=count_channels(sf)) as f: + f.write(sf) + print('wrote '+fno) - side_gain = np.average(ys_raw_side) - np.average(ys_raw) - print("side gain:", side_gain) + return xs, ys_m, ys_s - if not fix: return +def pw2(fn, label=None, bw=1/6, **kwargs): fno = fn[:-4]+"-proc.wav" + xs, ys_m, ys_s = plotwav2(fn, fix=True, bw=bw, **kwargs) + xs, ys_m, ys_s = plotwav2(fno, fix=False, bw=bw, **kwargs) - fir = firize(xs, -ys, srate=srate) - smf = convolve_each(sm/8, fir, mode='same') - fir = firize(xs, -ys_side, srate=srate) - ssf = convolve_each(ss/8, fir, mode='same') - ssf *= 10**(side_gain/20) - sf = np.array((smf + ssf, smf - ssf)).T - - import ewave - with ewave.open(fno, 'w', sampling_rate=srate, nchannels=count_channels(sf)) as f: - f.write(sf) - print('wrote '+fno) - -def pw(fn, ax, **kwargs): - plotwavsmooth(fn, ax, tilt='np2', bw=1/6, **kwargs) - -def pwc(fn, **kwargs): fig, ax = new_response(-18, 18) ax.set_title('averaged magnitudes of normalized songs with tilt and smoothing') - - pw(fn, ax, fix=True, **kwargs) - fno = fn[:-4]+"-proc.wav" - pw(fno, ax, fix=False, **kwargs) - + label = label or fn + ax.semilogx(xs, ys_m + 0, label=label+' (mid)') + ax.semilogx(xs, ys_s + 9, label=label+' (side)') ax.legend(loc=8) - show(fig) - -def pw2(fn, **kwargs): - fig, ax = new_response(-18, 18) - ax.set_title('averaged magnitudes of normalized songs with tilt and smoothing') - - plotwav2(fn, ax, fix=True, bw=1/6, **kwargs) - fno = fn[:-4]+"-proc.wav" - plotwav2(fno, ax, fix=False, bw=1/6, **kwargs) - - ax.legend(loc=8) - show(fig)