ongudidan commited on
Commit
6d7d479
·
1 Parent(s): 42eb2c0

refactor: replace abstract denoising strength slider with granular controls for post-processing and noise gate parameters

Browse files
Files changed (1) hide show
  1. app.py +62 -39
app.py CHANGED
@@ -151,21 +151,18 @@ def post_process_audio(
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 with a floor to keep background noise natural and not too dry
155
  if gate_threshold > -60.0:
156
  threshold = 10 ** (gate_threshold / 20.0)
157
  envelope = waveform.abs()
158
- # Fast 15ms window to open instantly at the start of words (avoids muddy onset delay)
159
- win_size = int(sr * 0.015)
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
- raw_gain = torch.sigmoid((env_smooth - threshold) / (threshold * 0.25))
166
- # Keep a floor of 35% gain (approx -9dB) so background noise remains continuous & controllable
167
- gate_floor = 0.35
168
- gain = gate_floor + (1.0 - gate_floor) * raw_gain
169
  waveform = waveform * gain
170
 
171
  # 5. Analog Warmth (Soft Saturation / Tube Limiting)
@@ -185,29 +182,25 @@ def demo_fn(
185
  speech_upl: str,
186
  noise_type: str,
187
  snr: int,
188
- denoising_strength: float,
189
- vocal_polish: bool,
 
 
 
 
 
 
190
  mic_input: Optional[str] = None,
191
  ):
192
  if input_type == "mic":
193
  speech_upl = mic_input
194
 
195
  sr = config("sr", 48000, int, section="df")
196
- logger.info(f"Got parameters input_type: {input_type}, speech_upl: {speech_upl}, noise: {noise_type}, snr: {snr}, strength: {denoising_strength}, polish: {vocal_polish}")
197
  snr = int(snr)
198
  noise_fn = NOISES[noise_type]
199
  meta = AudioMetaData(-1, -1, -1, -1, "")
200
 
201
- # Map the simple 0-100% denoising strength to advanced model parameters
202
- if denoising_strength == 0:
203
- atten_lim_db = 0.0
204
- wet_dry_mix = 0.0
205
- else:
206
- # Interpolate maximum attenuation between 6dB and 30dB
207
- atten_lim_db = 6.0 + (denoising_strength / 100.0) * 24.0
208
- # Interpolate dry/wet mix between 50% and 100%
209
- wet_dry_mix = 50.0 + (denoising_strength / 100.0) * 50.0
210
-
211
  max_s = 3600 # allow up to 1 hour (3600 seconds)
212
 
213
  if speech_upl is not None:
@@ -249,18 +242,9 @@ def demo_fn(
249
  alpha = wet_dry_mix / 100.0
250
  enhanced = alpha * enhanced + (1 - alpha) * sample
251
 
252
- # Apply professional post-processing (Low-cut filter + bass EQ + treble EQ + gate + warmth) using optimized studio defaults
253
- if vocal_polish:
254
- # We set low_cut_freq=110.0 to cut muddy frequency spikes at the start of words
255
- enhanced = post_process_audio(
256
- enhanced,
257
- sr,
258
- low_cut_freq=110.0,
259
- bass_gain=0.0,
260
- treble_gain=3.0,
261
- gate_threshold=-45.0,
262
- enable_warmth=True
263
- )
264
 
265
  lim = torch.linspace(0.0, 1.0, int(sr * 0.15)).unsqueeze(0)
266
  lim = torch.cat((lim, torch.ones(1, enhanced.shape[-1] - lim.shape[1])), dim=1)
@@ -441,14 +425,53 @@ with gr.Blocks() as demo:
441
  value="10",
442
  ),
443
  gr.Slider(
444
- minimum=0,
 
 
 
 
 
 
 
445
  maximum=100,
446
  step=5,
 
 
 
 
 
 
 
 
 
 
 
447
  value=80,
448
- label="Denoising Strength (%) - higher removes more noise, lower is more natural",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  ),
450
  gr.Checkbox(
451
- label="Vocal Polish (80Hz Low-Cut, Treble EQ & Analog Warmth)",
452
  value=True,
453
  ),
454
  mic_input,
@@ -467,10 +490,10 @@ with gr.Blocks() as demo:
467
  radio.change(toggle, radio, [mic_input, audio_file])
468
  gr.Examples(
469
  [
470
- ["file", "./samples/p232_013_clean.wav", "Kitchen", "10", 80, True, None],
471
- ["file", "./samples/p232_013_clean.wav", "Cafe", "10", 80, True, None],
472
- ["file", "./samples/p232_019_clean.wav", "Cafe", "10", 80, True, None],
473
- ["file", "./samples/p232_019_clean.wav", "River", "10", 80, True, None],
474
  ],
475
  fn=demo_fn,
476
  inputs=inputs,
 
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)
 
182
  speech_upl: str,
183
  noise_type: str,
184
  snr: int,
185
+ atten_lim_db: float,
186
+ wet_dry_mix: float,
187
+ post_process: bool,
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, "")
203
 
 
 
 
 
 
 
 
 
 
 
204
  max_s = 3600 # allow up to 1 hour (3600 seconds)
205
 
206
  if speech_upl is not None:
 
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)
 
425
  value="10",
426
  ),
427
  gr.Slider(
428
+ minimum=6,
429
+ maximum=35,
430
+ step=1,
431
+ value=15,
432
+ label="Max Attenuation (dB) - lower is more natural/clear, higher reduces more noise",
433
+ ),
434
+ gr.Slider(
435
+ minimum=50,
436
  maximum=100,
437
  step=5,
438
+ value=90,
439
+ label="Voice Naturalness Mix (%) - 100% is fully denoised, 90% blends back some original voice",
440
+ ),
441
+ gr.Checkbox(
442
+ label="Enable Post-Processing EQ & Filters",
443
+ value=True,
444
+ ),
445
+ gr.Slider(
446
+ minimum=20,
447
+ maximum=200,
448
+ step=10,
449
  value=80,
450
+ label="Low-Cut Filter Cutoff (Hz) - cuts muddy AC rumble/handling noise",
451
+ ),
452
+ gr.Slider(
453
+ minimum=-10,
454
+ maximum=10,
455
+ step=1,
456
+ value=0,
457
+ label="Voice Bass EQ Boost (dB) at 150Hz - adds warmth",
458
+ ),
459
+ gr.Slider(
460
+ minimum=-10,
461
+ maximum=10,
462
+ step=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,
 
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,