ongudidan commited on
Commit
c580565
·
1 Parent(s): 3d3121f

feat: add soft noise gate and analog warmth DSP processing to post-processing pipeline

Browse files
Files changed (1) hide show
  1. app.py +41 -8
app.py CHANGED
@@ -135,6 +135,8 @@ def post_process_audio(
135
  low_cut_freq: float,
136
  bass_gain: float,
137
  treble_gain: float,
 
 
138
  ) -> Tensor:
139
  """Apply professional DSP filters to make voice audio crisp and clear."""
140
  # 1. High-pass filter (Low-cut) to cut sub-bass rumble and AC hums
@@ -149,7 +151,25 @@ def post_process_audio(
149
  if treble_gain != 0:
150
  waveform = F_audio.equalizer_biquad(waveform, sample_rate=sr, center_freq=6000.0, gain=treble_gain, Q=0.707)
151
 
152
- # 4. Normalize peak to -1.0 dBFS (0.9 max amplitude) to maximize volume without clipping
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  max_val = waveform.abs().max()
154
  if max_val > 0:
155
  waveform = waveform * (0.9 / max_val)
@@ -168,13 +188,15 @@ def demo_fn(
168
  low_cut_freq: float,
169
  bass_gain: float,
170
  treble_gain: float,
 
 
171
  mic_input: Optional[str] = None,
172
  ):
173
  if input_type == "mic":
174
  speech_upl = mic_input
175
 
176
  sr = config("sr", 48000, int, section="df")
177
- logger.info(f"Got parameters input_type: {input_type}, speech_upl: {speech_upl}, noise: {noise_type}, snr: {snr}, atten_lim_db: {atten_lim_db}, wet_dry_mix: {wet_dry_mix}, post_process: {post_process}, low_cut: {low_cut_freq}, bass: {bass_gain}, treble: {treble_gain}")
178
  snr = int(snr)
179
  noise_fn = NOISES[noise_type]
180
  meta = AudioMetaData(-1, -1, -1, -1, "")
@@ -220,9 +242,9 @@ def demo_fn(
220
  alpha = wet_dry_mix / 100.0
221
  enhanced = alpha * enhanced + (1 - alpha) * sample
222
 
223
- # Apply professional post-processing (Low-cut filter + bass EQ + treble EQ)
224
  if post_process:
225
- enhanced = post_process_audio(enhanced, sr, low_cut_freq, bass_gain, treble_gain)
226
 
227
  lim = torch.linspace(0.0, 1.0, int(sr * 0.15)).unsqueeze(0)
228
  lim = torch.cat((lim, torch.ones(1, enhanced.shape[-1] - lim.shape[1])), dim=1)
@@ -441,6 +463,17 @@ with gr.Blocks() as demo:
441
  value=3,
442
  label="Voice Treble EQ Boost (dB) at 6kHz - adds crispness/air",
443
  ),
 
 
 
 
 
 
 
 
 
 
 
444
  mic_input,
445
  ]
446
  btn = gr.Button("Generate")
@@ -457,10 +490,10 @@ with gr.Blocks() as demo:
457
  radio.change(toggle, radio, [mic_input, audio_file])
458
  gr.Examples(
459
  [
460
- ["file", "./samples/p232_013_clean.wav", "Kitchen", "10", 15, 90, True, 80, 0, 3, None],
461
- ["file", "./samples/p232_013_clean.wav", "Cafe", "10", 15, 90, True, 80, 0, 3, None],
462
- ["file", "./samples/p232_019_clean.wav", "Cafe", "10", 15, 90, True, 80, 0, 3, None],
463
- ["file", "./samples/p232_019_clean.wav", "River", "10", 15, 90, True, 80, 0, 3, None],
464
  ],
465
  fn=demo_fn,
466
  inputs=inputs,
 
135
  low_cut_freq: float,
136
  bass_gain: float,
137
  treble_gain: float,
138
+ gate_threshold: float,
139
+ enable_warmth: bool,
140
  ) -> Tensor:
141
  """Apply professional DSP filters to make voice audio crisp and clear."""
142
  # 1. High-pass filter (Low-cut) to cut sub-bass rumble and AC hums
 
151
  if treble_gain != 0:
152
  waveform = F_audio.equalizer_biquad(waveform, sample_rate=sr, center_freq=6000.0, gain=treble_gain, Q=0.707)
153
 
154
+ # 4. Soft Noise Gate to remove background gating/watery artifacts during silence
155
+ if gate_threshold > -60.0:
156
+ threshold = 10 ** (gate_threshold / 20.0)
157
+ envelope = waveform.abs()
158
+ # Smooth envelope using 50ms average pooling
159
+ win_size = int(sr * 0.05)
160
+ if win_size % 2 == 0:
161
+ win_size += 1
162
+ env_padded = torch.nn.functional.pad(envelope, (win_size//2, win_size//2), mode='reflect')
163
+ env_smooth = torch.nn.functional.avg_pool1d(env_padded.unsqueeze(0), kernel_size=win_size, stride=1).squeeze(0)
164
+ # Soft sigmoid gating to prevent clicking
165
+ gain = torch.sigmoid((env_smooth - threshold) / (threshold * 0.25))
166
+ waveform = waveform * gain
167
+
168
+ # 5. Analog Warmth (Soft Saturation / Tube Limiting)
169
+ if enable_warmth:
170
+ waveform = torch.tanh(waveform * 1.05) / 1.05
171
+
172
+ # 6. Normalize peak to -1.0 dBFS (0.9 max amplitude) to maximize volume without clipping
173
  max_val = waveform.abs().max()
174
  if max_val > 0:
175
  waveform = waveform * (0.9 / max_val)
 
188
  low_cut_freq: float,
189
  bass_gain: float,
190
  treble_gain: float,
191
+ gate_threshold: float,
192
+ enable_warmth: bool,
193
  mic_input: Optional[str] = None,
194
  ):
195
  if input_type == "mic":
196
  speech_upl = mic_input
197
 
198
  sr = config("sr", 48000, int, section="df")
199
+ logger.info(f"Got parameters input_type: {input_type}, speech_upl: {speech_upl}, noise: {noise_type}, snr: {snr}, atten_lim_db: {atten_lim_db}, wet_dry_mix: {wet_dry_mix}, post_process: {post_process}, low_cut: {low_cut_freq}, bass: {bass_gain}, treble: {treble_gain}, gate: {gate_threshold}, warmth: {enable_warmth}")
200
  snr = int(snr)
201
  noise_fn = NOISES[noise_type]
202
  meta = AudioMetaData(-1, -1, -1, -1, "")
 
242
  alpha = wet_dry_mix / 100.0
243
  enhanced = alpha * enhanced + (1 - alpha) * sample
244
 
245
+ # Apply professional post-processing (Low-cut filter + bass EQ + treble EQ + gate + warmth)
246
  if post_process:
247
+ enhanced = post_process_audio(enhanced, sr, low_cut_freq, bass_gain, treble_gain, gate_threshold, enable_warmth)
248
 
249
  lim = torch.linspace(0.0, 1.0, int(sr * 0.15)).unsqueeze(0)
250
  lim = torch.cat((lim, torch.ones(1, enhanced.shape[-1] - lim.shape[1])), dim=1)
 
463
  value=3,
464
  label="Voice Treble EQ Boost (dB) at 6kHz - adds crispness/air",
465
  ),
466
+ gr.Slider(
467
+ minimum=-60,
468
+ maximum=-30,
469
+ step=5,
470
+ value=-45,
471
+ label="Noise Gate Threshold (dB) - lower keeps quiet sound, higher silences gaps",
472
+ ),
473
+ gr.Checkbox(
474
+ label="Enable Analog Warmth (Soft Saturation)",
475
+ value=True,
476
+ ),
477
  mic_input,
478
  ]
479
  btn = gr.Button("Generate")
 
490
  radio.change(toggle, radio, [mic_input, audio_file])
491
  gr.Examples(
492
  [
493
+ ["file", "./samples/p232_013_clean.wav", "Kitchen", "10", 15, 90, True, 80, 0, 3, -45, True, None],
494
+ ["file", "./samples/p232_013_clean.wav", "Cafe", "10", 15, 90, True, 80, 0, 3, -45, True, None],
495
+ ["file", "./samples/p232_019_clean.wav", "Cafe", "10", 15, 90, True, 80, 0, 3, -45, True, None],
496
+ ["file", "./samples/p232_019_clean.wav", "River", "10", 15, 90, True, 80, 0, 3, -45, True, None],
497
  ],
498
  fn=demo_fn,
499
  inputs=inputs,