e@0
|
1 import pandas as pd
|
e@0
|
2 import numpy as np
|
e@0
|
3 from numpy.core._internal import _gcd as gcd
|
e@0
|
4
|
e@0
|
5
|
e@0
|
6 def zafar(lx, rx, d1, g1, m, fc, G, da=0.007, fs=44100.):
|
e@0
|
7 """ Rafii & Pardo Reverberator (2009) controlled by High Level parameters
|
e@0
|
8 Inputs:
|
e@0
|
9 lx : left channel input
|
e@0
|
10 rx : right channel input
|
e@0
|
11 d1 : delay of first comb filter in seconds
|
e@0
|
12 g1 : gain of first comb filters
|
e@0
|
13 da : delay of allpass filter in seconds
|
e@0
|
14 G : dry/wet mix gain
|
e@0
|
15 fc : lowpass filter cuttoff Hz
|
e@0
|
16 m : difference between left and right channel phases
|
e@0
|
17 fs : sampling rate
|
e@0
|
18
|
e@0
|
19 Outputs:
|
e@0
|
20 ly: left channel output
|
e@0
|
21 ry: right channel output
|
e@0
|
22 """
|
e@0
|
23
|
e@0
|
24 d1 = int(d1 * fs)
|
e@0
|
25 m = int(m * fs)
|
e@0
|
26 da = int(da * fs)
|
e@0
|
27
|
e@0
|
28 def calculate_parameters(d1, g1):
|
e@0
|
29
|
e@0
|
30 d2 = int(round((1.5) ** (-1) * d1))
|
e@0
|
31
|
e@0
|
32 while gcd(d2, d1) != 1:
|
e@0
|
33 d2 += 1
|
e@0
|
34
|
e@0
|
35 d3 = int(round((1.5) ** (-2) * d1))
|
e@0
|
36
|
e@0
|
37 while gcd(d3, d2) != 1 or gcd(d3, d1) != 1:
|
e@0
|
38 d3 += 1
|
e@0
|
39
|
e@0
|
40 d4 = int(round((1.5) ** (-3) * d1))
|
e@0
|
41
|
e@0
|
42 while gcd(d4, d3) != 1 or gcd(d4, d2) != 1 or gcd(d4, d1) != 1:
|
e@0
|
43 d4 += 1
|
e@0
|
44
|
e@0
|
45 d5 = int(round((1.5) ** (-4) * d1))
|
e@0
|
46
|
e@0
|
47 while gcd(d5, d4) != 1 or gcd(d5, d3) != 1 or gcd(d5, d2) != 1 or gcd(d5, d1) != 1:
|
e@0
|
48 d5 += 1
|
e@0
|
49
|
e@0
|
50 d6 = int(round((1.5) ** (-5) * d1))
|
e@0
|
51 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
|
52 d6 += 1
|
e@0
|
53 g2 = g1 ** (1.5) ** (-1) * g1
|
e@0
|
54 g3 = g1 ** (1.5) ** (-2) * g1
|
e@0
|
55 g4 = g1 ** (1.5) ** (-3) * g1
|
e@0
|
56 g5 = g1 ** (1.5) ** (-4) * g1
|
e@0
|
57 g6 = g1 ** (1.5) ** (-5) * g1
|
e@0
|
58
|
e@0
|
59 return (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6)
|
e@0
|
60
|
e@0
|
61 def comb_array(x, g1, d1):
|
e@0
|
62
|
e@0
|
63 (d1, d2, d3, d4, d5, d6, g1, g2, g3, g4, g5, g6) = calculate_parameters(d1, g1)
|
e@0
|
64
|
e@0
|
65 c1out = comb(x, g1, d1)
|
e@0
|
66 c2out = comb(x, g2, d2)
|
e@0
|
67 c3out = comb(x, g3, d3)
|
e@0
|
68 c4out = comb(x, g4, d4)
|
e@0
|
69 c5out = comb(x, g5, d5)
|
e@0
|
70 c6out = comb(x, g6, d6)
|
e@0
|
71
|
e@0
|
72 Lc1 = len(c1out)
|
e@0
|
73 Lc2 = len(c2out)
|
e@0
|
74 Lc3 = len(c3out)
|
e@0
|
75 Lc4 = len(c4out)
|
e@0
|
76 Lc5 = len(c5out)
|
e@0
|
77 Lc6 = len(c6out)
|
e@0
|
78
|
e@0
|
79 Lc = max(Lc1, Lc2, Lc3, Lc4, Lc5, Lc6)
|
e@0
|
80
|
e@0
|
81 y = np.zeros((Lc,))
|
e@0
|
82
|
e@0
|
83 y[0:Lc1] = c1out
|
e@0
|
84 y[0:Lc2] += c2out
|
e@0
|
85 y[0:Lc3] += c3out
|
e@0
|
86 y[0:Lc4] += c4out
|
e@0
|
87 y[0:Lc5] += c5out
|
e@0
|
88 y[0:Lc6] += c6out
|
e@0
|
89
|
e@0
|
90 return y
|
e@0
|
91
|
e@0
|
92 def comb(x, g, d):
|
e@0
|
93 LEN = len(x) + d
|
e@0
|
94 # print d
|
e@0
|
95 y = np.zeros((LEN,))
|
e@0
|
96 for n in range(0, LEN):
|
e@0
|
97 if n - d < 0:
|
e@0
|
98 y[n] = 0
|
e@0
|
99 else:
|
e@0
|
100 y[n] = x[n - d] + g * y[n - d]
|
e@0
|
101
|
e@0
|
102 return y
|
e@0
|
103
|
e@0
|
104 def allpass(x, g, d):
|
e@0
|
105 LENx = len(x)
|
e@0
|
106 LENy = LENx + d
|
e@0
|
107 y = np.zeros((LENy,))
|
e@0
|
108 for n in range(0, LENy):
|
e@0
|
109 if n - d < 0:
|
e@0
|
110 y[n] = -g * x[n]
|
e@0
|
111 elif n >= LENx:
|
e@0
|
112 y[n] = x[n - d] + g * y[n - d]
|
e@0
|
113 else:
|
e@0
|
114 y[n] = x[n - d] - g * x[n] + g * y[n - d]
|
e@0
|
115
|
e@0
|
116 return y
|
e@0
|
117
|
e@0
|
118 def lowpass(x, g):
|
e@0
|
119 LEN = len(x)
|
e@0
|
120 y = np.zeros((LEN,))
|
e@0
|
121
|
e@0
|
122 for n in range(0, LEN):
|
e@0
|
123 if n - 1 < 0:
|
e@0
|
124 y[n] = (1 - g) * x[n]
|
e@0
|
125 else:
|
e@0
|
126 y[n] = (1 - g) * x[n] + g * y[n - 1]
|
e@0
|
127
|
e@0
|
128 return y
|
e@0
|
129
|
e@0
|
130 ga = 1. / np.sqrt(2.)
|
e@0
|
131
|
e@0
|
132 cin = 0.5 * lx + 0.5 * rx
|
e@0
|
133 cout = comb_array(cin, g1, d1)
|
e@0
|
134
|
e@0
|
135 ra = allpass(cout, ga, da + m // 2)
|
e@0
|
136 la = allpass(cout, ga, da - m // 2)
|
e@0
|
137
|
e@0
|
138 gc = 2 - np.cos(2 * np.pi * fc / fs) - np.sqrt((np.cos(2 * np.pi * fc / fs) - 2) ** 2 - 1)
|
e@0
|
139
|
e@0
|
140 ral = lowpass(ra, gc)
|
e@0
|
141 lal = lowpass(la, gc)
|
e@0
|
142
|
e@0
|
143 ralg = G * ral
|
e@0
|
144 lalg = G * lal
|
e@0
|
145
|
e@0
|
146 ry = ralg[0:len(rx)] + (1 - G) * rx
|
e@0
|
147 ly = lalg[0:len(lx)] + (1 - G) * lx
|
e@0
|
148
|
e@0
|
149 return np.vstack([ry, ly])
|
e@0
|
150
|
e@0
|
151 def get_reverb_from_tags(x, tags, fs=44100):
|
e@0
|
152 reverb_csv = 'contributions.csv'
|
e@0
|
153 df = pd.read_csv(reverb_csv)
|
e@0
|
154 df = df.fillna("")
|
e@0
|
155 params = []
|
e@0
|
156 for n in range(len(df)):
|
e@0
|
157 if all([t in df['agreed'].iloc[n].split(',') for t in tags]):
|
e@0
|
158 params.append(df['param'].iloc[n])
|
e@0
|
159 d1, g1, m, fc, G = [float(f) for f in params[0].split(',')]
|
e@0
|
160 y = zafar(x, x, d1, g1, m, fc, G, fs=fs)
|
e@0
|
161 return y
|
e@0
|
162
|