e@0: import pandas as pd e@0: import numpy as np e@0: from numpy.core._internal import _gcd as gcd e@0: e@0: e@0: def zafar(lx, rx, d1, g1, m, fc, G, da=0.007, fs=44100.): e@0: """ Rafii & Pardo Reverberator (2009) controlled by High Level parameters e@0: Inputs: e@0: lx : left channel input e@0: rx : right channel input e@0: d1 : delay of first comb filter in seconds e@0: g1 : gain of first comb filters e@0: da : delay of allpass filter in seconds e@0: G : dry/wet mix gain e@0: fc : lowpass filter cuttoff Hz e@0: m : difference between left and right channel phases e@0: fs : sampling rate e@0: e@0: Outputs: e@0: ly: left channel output e@0: ry: right channel output e@0: """ e@0: e@0: d1 = int(d1 * fs) e@0: m = int(m * fs) e@0: da = int(da * fs) e@0: e@0: def calculate_parameters(d1, g1): e@0: e@0: d2 = int(round((1.5) ** (-1) * d1)) e@0: e@0: while gcd(d2, d1) != 1: e@0: d2 += 1 e@0: e@0: d3 = int(round((1.5) ** (-2) * d1)) e@0: e@0: while gcd(d3, d2) != 1 or gcd(d3, d1) != 1: e@0: d3 += 1 e@0: e@0: d4 = int(round((1.5) ** (-3) * d1)) e@0: e@0: while gcd(d4, d3) != 1 or gcd(d4, d2) != 1 or gcd(d4, d1) != 1: e@0: d4 += 1 e@0: e@0: d5 = int(round((1.5) ** (-4) * d1)) e@0: e@0: while gcd(d5, d4) != 1 or gcd(d5, d3) != 1 or gcd(d5, d2) != 1 or gcd(d5, d1) != 1: e@0: d5 += 1 e@0: e@0: d6 = int(round((1.5) ** (-5) * d1)) e@0: while gcd(d6, d5) != 1 or gcd(d6, d4) != 1 or gcd(d6, d3) != 1 or gcd(d6, d2) != 1 or gcd(d6, d1) != 1: e@0: d6 += 1 e@0: g2 = g1 ** (1.5) ** (-1) * g1 e@0: g3 = g1 ** (1.5) ** (-2) * g1 e@0: g4 = g1 ** (1.5) ** (-3) * g1 e@0: g5 = g1 ** (1.5) ** (-4) * g1 e@0: g6 = g1 ** (1.5) ** (-5) * g1 e@0: e@0: return (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6) e@0: e@0: def comb_array(x, g1, d1): e@0: e@0: (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6) = calculate_parameters(d1, g1) e@0: e@0: c1out = comb(x, g1, d1) e@0: c2out = comb(x, g2, d2) e@0: c3out = comb(x, g3, d3) e@0: c4out = comb(x, g4, d4) e@0: c5out = comb(x, g5, d5) e@0: c6out = comb(x, g6, d6) e@0: e@0: Lc1 = len(c1out) e@0: Lc2 = len(c2out) e@0: Lc3 = len(c3out) e@0: Lc4 = len(c4out) e@0: Lc5 = len(c5out) e@0: Lc6 = len(c6out) e@0: e@0: Lc = max(Lc1, Lc2, Lc3, Lc4, Lc5, Lc6) e@0: e@0: y = np.zeros((Lc,)) e@0: e@0: y[0:Lc1] = c1out e@0: y[0:Lc2] += c2out e@0: y[0:Lc3] += c3out e@0: y[0:Lc4] += c4out e@0: y[0:Lc5] += c5out e@0: y[0:Lc6] += c6out e@0: e@0: return y e@0: e@0: def comb(x, g, d): e@0: LEN = len(x) + d e@0: # print d e@0: y = np.zeros((LEN,)) e@0: for n in range(0, LEN): e@0: if n - d < 0: e@0: y[n] = 0 e@0: else: e@0: y[n] = x[n - d] + g * y[n - d] e@0: e@0: return y e@0: e@0: def allpass(x, g, d): e@0: LENx = len(x) e@0: LENy = LENx + d e@0: y = np.zeros((LENy,)) e@0: for n in range(0, LENy): e@0: if n - d < 0: e@0: y[n] = -g * x[n] e@0: elif n >= LENx: e@0: y[n] = x[n - d] + g * y[n - d] e@0: else: e@0: y[n] = x[n - d] - g * x[n] + g * y[n - d] e@0: e@0: return y e@0: e@0: def lowpass(x, g): e@0: LEN = len(x) e@0: y = np.zeros((LEN,)) e@0: e@0: for n in range(0, LEN): e@0: if n - 1 < 0: e@0: y[n] = (1 - g) * x[n] e@0: else: e@0: y[n] = (1 - g) * x[n] + g * y[n - 1] e@0: e@0: return y e@0: e@0: ga = 1. / np.sqrt(2.) e@0: e@0: cin = 0.5 * lx + 0.5 * rx e@0: cout = comb_array(cin, g1, d1) e@0: e@0: ra = allpass(cout, ga, da + m // 2) e@0: la = allpass(cout, ga, da - m // 2) e@0: e@0: gc = 2 - np.cos(2 * np.pi * fc / fs) - np.sqrt((np.cos(2 * np.pi * fc / fs) - 2) ** 2 - 1) e@0: e@0: ral = lowpass(ra, gc) e@0: lal = lowpass(la, gc) e@0: e@0: ralg = G * ral e@0: lalg = G * lal e@0: e@0: ry = ralg[0:len(rx)] + (1 - G) * rx e@0: ly = lalg[0:len(lx)] + (1 - G) * lx e@0: e@0: return np.vstack([ry, ly]) e@0: e@0: def get_reverb_from_tags(x, tags, fs=44100): e@0: reverb_csv = 'contributions.csv' e@0: df = pd.read_csv(reverb_csv) e@0: df = df.fillna("") e@0: params = [] e@0: for n in range(len(df)): e@0: if all([t in df['agreed'].iloc[n].split(',') for t in tags]): e@0: params.append(df['param'].iloc[n]) e@0: d1, g1, m, fc, G = [float(f) for f in params[0].split(',')] e@0: y = zafar(x, x, d1, g1, m, fc, G, fs=fs) e@0: return y e@0: