heybaeheef commited on
Commit
53b5dcc
ยท
verified ยท
1 Parent(s): 656ae63

Upload effect_chain.py

Browse files
Files changed (1) hide show
  1. effect_chain.py +169 -0
effect_chain.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Effect Chain - Pedalboard ๊ธฐ๋ฐ˜ ์˜ค๋””์˜ค ์ดํŽ™ํŠธ ์ฒ˜๋ฆฌ
3
+ =================================================
4
+ V6: Compressor threshold ๋ฒ”์œ„ ์ˆ˜์ • (0 ~ -5dB)
5
+ """
6
+
7
+ import numpy as np
8
+ import soundfile as sf
9
+ from typing import Dict
10
+ from pedalboard import (
11
+ Pedalboard,
12
+ Compressor,
13
+ Gain,
14
+ HighShelfFilter,
15
+ LowShelfFilter,
16
+ PeakFilter,
17
+ Delay,
18
+ Reverb,
19
+ Limiter
20
+ )
21
+
22
+
23
+ class EffectChain:
24
+ def __init__(self, sample_rate: int = 44100):
25
+ self.sample_rate = sample_rate
26
+
27
+ def _get_param(self, params: Dict[str, float], *keys, default=0.0) -> float:
28
+ for key in keys:
29
+ if key in params:
30
+ return params[key]
31
+ return default
32
+
33
+ def _build_pedalboard(self, params: Dict[str, float]) -> Pedalboard:
34
+ effects = []
35
+
36
+ # Compressor (V6: 0 ~ -5dB ๋ฒ”์œ„)
37
+ comp_threshold = self._get_param(params, "compressor.threshold", default=-3.0)
38
+ comp_ratio = self._get_param(params, "compressor.ratio", default=2.0)
39
+ effects.append(Compressor(
40
+ threshold_db=max(-5.0, min(0.0, comp_threshold)), # V6: 0 ~ -5dB
41
+ ratio=max(1.5, min(4.0, comp_ratio)),
42
+ attack_ms=10.0,
43
+ release_ms=100.0
44
+ ))
45
+
46
+ # EQ Peak 1
47
+ freq1 = self._get_param(params, "eq_peak1.params.freq", default=1000.0)
48
+ gain1 = self._get_param(params, "eq_peak1.params.gain", default=0.0)
49
+ q1 = self._get_param(params, "eq_peak1.params.Q", "eq_peak1.params.q", default=1.0)
50
+ if abs(gain1) > 0.1:
51
+ effects.append(PeakFilter(
52
+ cutoff_frequency_hz=max(20, min(20000, freq1)),
53
+ gain_db=max(-12, min(12, gain1)),
54
+ q=max(0.1, min(10, q1))
55
+ ))
56
+
57
+ # EQ Peak 2
58
+ freq2 = self._get_param(params, "eq_peak2.params.freq", default=4000.0)
59
+ gain2 = self._get_param(params, "eq_peak2.params.gain", default=0.0)
60
+ q2 = self._get_param(params, "eq_peak2.params.Q", "eq_peak2.params.q", default=1.0)
61
+ if abs(gain2) > 0.1:
62
+ effects.append(PeakFilter(
63
+ cutoff_frequency_hz=max(20, min(20000, freq2)),
64
+ gain_db=max(-12, min(12, gain2)),
65
+ q=max(0.1, min(10, q2))
66
+ ))
67
+
68
+ # Low Shelf
69
+ freq_low = self._get_param(params, "eq_lowshelf.params.freq", default=200.0)
70
+ gain_low = self._get_param(params, "eq_lowshelf.params.gain", default=0.0)
71
+ if abs(gain_low) > 0.1:
72
+ effects.append(LowShelfFilter(
73
+ cutoff_frequency_hz=max(20, min(2000, freq_low)),
74
+ gain_db=max(-12, min(12, gain_low)),
75
+ q=0.707
76
+ ))
77
+
78
+ # High Shelf
79
+ freq_high = self._get_param(params, "eq_highshelf.params.freq", default=8000.0)
80
+ gain_high = self._get_param(params, "eq_highshelf.params.gain", default=0.0)
81
+ if abs(gain_high) > 0.1:
82
+ effects.append(HighShelfFilter(
83
+ cutoff_frequency_hz=max(1000, min(20000, freq_high)),
84
+ gain_db=max(-12, min(12, gain_high)),
85
+ q=0.707
86
+ ))
87
+
88
+ # Delay
89
+ delay_time = self._get_param(params, "delay.delay_time", default=0.02)
90
+ delay_feedback = self._get_param(params, "delay.feedback", default=0.15)
91
+ delay_mix = self._get_param(params, "delay.mix", default=0.1)
92
+ if delay_mix > 0.01:
93
+ effects.append(Delay(
94
+ delay_seconds=max(0.01, min(0.3, delay_time)),
95
+ feedback=max(0.0, min(0.25, delay_feedback)),
96
+ mix=max(0.0, min(0.2, delay_mix))
97
+ ))
98
+
99
+ # Reverb
100
+ room_size = self._get_param(params, "reverb.room_size", default=0.3)
101
+ reverb_wet = self._get_param(params, "reverb.wet_level", default=0.0)
102
+ reverb_dry = self._get_param(params, "reverb.dry_level", default=1.0)
103
+ reverb_damping = self._get_param(params, "reverb.damping", default=0.5)
104
+ if reverb_wet > 0.01:
105
+ effects.append(Reverb(
106
+ room_size=max(0.0, min(0.6, room_size)),
107
+ damping=max(0.0, min(1.0, reverb_damping)),
108
+ wet_level=max(0.0, min(0.3, reverb_wet)),
109
+ dry_level=max(0.7, min(1.0, reverb_dry))
110
+ ))
111
+
112
+ # Limiter
113
+ effects.append(Limiter(threshold_db=-6.0))
114
+
115
+ return Pedalboard(effects)
116
+
117
+ def process(self, input_path: str, output_path: str, parameters: Dict[str, float]) -> bool:
118
+ try:
119
+ audio, sr = sf.read(input_path)
120
+
121
+ if len(audio.shape) == 1:
122
+ audio = audio.reshape(-1, 1)
123
+
124
+ audio = audio.astype(np.float32)
125
+
126
+ # ์ž…๋ ฅ ์ •๊ทœํ™”
127
+ input_peak = np.max(np.abs(audio))
128
+ if input_peak > 0.5:
129
+ audio = audio * (0.5 / input_peak)
130
+ print(f"[EffectChain] ์ž…๋ ฅ ๏ฟฝ๏ฟฝ๊ทœํ™”: peak {input_peak:.3f} โ†’ 0.5")
131
+
132
+ board = self._build_pedalboard(parameters)
133
+ processed = board(audio, sr)
134
+
135
+ # Wet/Dry ๋ฏน์Šค
136
+ wet_mix = self._get_param(parameters, "final_wet_mix", default=0.5)
137
+ wet_mix = max(0.3, min(0.7, wet_mix))
138
+
139
+ min_len = min(len(audio), len(processed))
140
+ output = audio[:min_len] * (1 - wet_mix) + processed[:min_len] * wet_mix
141
+
142
+ # ์ถœ๋ ฅ ์ •๊ทœํ™”
143
+ output_peak = np.max(np.abs(output))
144
+ if output_peak > 0.9:
145
+ output = output * (0.9 / output_peak)
146
+ print(f"[EffectChain] ์ถœ๋ ฅ ์ •๊ทœํ™”: peak {output_peak:.3f} โ†’ 0.9")
147
+
148
+ output = np.clip(output, -1.0, 1.0)
149
+ sf.write(output_path, output, sr)
150
+
151
+ print(f"[EffectChain] โœ… ์ฒ˜๋ฆฌ ์™„๋ฃŒ: {output_path}")
152
+ print(f"[EffectChain] ์ ์šฉ๋œ ํŒŒ๋ผ๋ฏธํ„ฐ:")
153
+ print(f" - Compressor: threshold={self._get_param(parameters, 'compressor.threshold', default=-3.0):.1f}dB, ratio={self._get_param(parameters, 'compressor.ratio', default=2.0):.1f}")
154
+ print(f" - EQ Peak1 Gain: {self._get_param(parameters, 'eq_peak1.params.gain'):.2f} dB")
155
+ print(f" - EQ Peak2 Gain: {self._get_param(parameters, 'eq_peak2.params.gain'):.2f} dB")
156
+ print(f" - Low Shelf Gain: {self._get_param(parameters, 'eq_lowshelf.params.gain'):.2f} dB")
157
+ print(f" - High Shelf Gain: {self._get_param(parameters, 'eq_highshelf.params.gain'):.2f} dB")
158
+ print(f" - Distortion: DISABLED")
159
+ print(f" - Delay: time={self._get_param(parameters, 'delay.delay_time', default=0.02):.3f}s, fb={self._get_param(parameters, 'delay.feedback', default=0.15):.2f}, mix={self._get_param(parameters, 'delay.mix', default=0.1):.2f}")
160
+ print(f" - Reverb: room={self._get_param(parameters, 'reverb.room_size', default=0.3):.2f}, wet={self._get_param(parameters, 'reverb.wet_level', default=0.0):.2f}")
161
+ print(f" - Wet Mix: {wet_mix:.2f}")
162
+
163
+ return True
164
+
165
+ except Exception as e:
166
+ print(f"[EffectChain] โŒ ์ฒ˜๋ฆฌ ์‹คํŒจ: {e}")
167
+ import traceback
168
+ traceback.print_exc()
169
+ raise e