ongudidan commited on
Commit
56fb286
·
1 Parent(s): d527034

feat: add optional DSP post-processing for audio clarification and normalization

Browse files
Files changed (1) hide show
  1. app.py +33 -6
app.py CHANGED
@@ -120,19 +120,38 @@ def ensure_wav(filepath: str) -> str:
120
  return filepath
121
 
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  def demo_fn(
124
  speech_upl: str,
125
  noise_type: str,
126
  snr: int,
127
  atten_lim_db: float,
128
  wet_dry_mix: float,
 
129
  mic_input: Optional[str] = None,
130
  ):
131
  if mic_input:
132
  speech_upl = mic_input
133
 
134
  sr = config("sr", 48000, int, section="df")
135
- logger.info(f"Got parameters speech_upl: {speech_upl}, noise: {noise_type}, snr: {snr}, atten_lim_db: {atten_lim_db}, wet_dry_mix: {wet_dry_mix}")
136
  snr = int(snr)
137
  noise_fn = NOISES[noise_type]
138
  meta = AudioMetaData(-1, -1, -1, -1, "")
@@ -177,8 +196,12 @@ def demo_fn(
177
  alpha = wet_dry_mix / 100.0
178
  enhanced = alpha * enhanced + (1 - alpha) * sample
179
 
 
 
 
 
180
  lim = torch.linspace(0.0, 1.0, int(sr * 0.15)).unsqueeze(0)
181
- lim = torch.cat((lim, torch.ones(1, enhanced.shape[1] - lim.shape[1])), dim=1)
182
  enhanced = enhanced * lim
183
 
184
  if meta.sample_rate != sr:
@@ -368,6 +391,10 @@ with gr.Blocks() as demo:
368
  value=90,
369
  label="Voice Naturalness Mix (%) - 100% is fully denoised, 90% blends back some original voice",
370
  ),
 
 
 
 
371
  mic_input,
372
  ]
373
  btn = gr.Button("Generate")
@@ -384,10 +411,10 @@ with gr.Blocks() as demo:
384
  radio.change(toggle, radio, [mic_input, audio_file])
385
  gr.Examples(
386
  [
387
- ["./samples/p232_013_clean.wav", "Kitchen", "10", 15, 90, None],
388
- ["./samples/p232_013_clean.wav", "Cafe", "10", 15, 90, None],
389
- ["./samples/p232_019_clean.wav", "Cafe", "10", 15, 90, None],
390
- ["./samples/p232_019_clean.wav", "River", "10", 15, 90, None],
391
  ],
392
  fn=demo_fn,
393
  inputs=inputs,
 
120
  return filepath
121
 
122
 
123
+ import torchaudio.functional as F_audio
124
+
125
+ def post_process_audio(waveform: Tensor, sr: int) -> Tensor:
126
+ """Apply professional DSP filters to make voice audio crisp and clear."""
127
+ # 1. High-pass filter at 80 Hz to cut muddy sub-bass rumble and AC hums
128
+ waveform = F_audio.highpass_biquad(waveform, sample_rate=sr, cutoff_freq=80.0)
129
+
130
+ # 2. Treble peaking equalizer at 6000 Hz (+3.0 dB) to add air, presence, and vocal crispness
131
+ waveform = F_audio.equalizer_biquad(waveform, sample_rate=sr, center_freq=6000.0, gain=3.0, Q=0.707)
132
+
133
+ # 3. Normalize peak to -1.0 dBFS (0.9 max amplitude) to maximize volume without clipping
134
+ max_val = waveform.abs().max()
135
+ if max_val > 0:
136
+ waveform = waveform * (0.9 / max_val)
137
+
138
+ return waveform
139
+
140
+
141
  def demo_fn(
142
  speech_upl: str,
143
  noise_type: str,
144
  snr: int,
145
  atten_lim_db: float,
146
  wet_dry_mix: float,
147
+ post_process: bool,
148
  mic_input: Optional[str] = None,
149
  ):
150
  if mic_input:
151
  speech_upl = mic_input
152
 
153
  sr = config("sr", 48000, int, section="df")
154
+ logger.info(f"Got parameters 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}")
155
  snr = int(snr)
156
  noise_fn = NOISES[noise_type]
157
  meta = AudioMetaData(-1, -1, -1, -1, "")
 
196
  alpha = wet_dry_mix / 100.0
197
  enhanced = alpha * enhanced + (1 - alpha) * sample
198
 
199
+ # Apply professional post-processing (Low-cut filter + presence boost EQ)
200
+ if post_process:
201
+ enhanced = post_process_audio(enhanced, sr)
202
+
203
  lim = torch.linspace(0.0, 1.0, int(sr * 0.15)).unsqueeze(0)
204
+ lim = torch.cat((lim, torch.ones(1, enhanced.shape[-1] - lim.shape[1])), dim=1)
205
  enhanced = enhanced * lim
206
 
207
  if meta.sample_rate != sr:
 
391
  value=90,
392
  label="Voice Naturalness Mix (%) - 100% is fully denoised, 90% blends back some original voice",
393
  ),
394
+ gr.Checkbox(
395
+ label="Post-Process (80Hz Low-Cut & Presence Boost)",
396
+ value=True,
397
+ ),
398
  mic_input,
399
  ]
400
  btn = gr.Button("Generate")
 
411
  radio.change(toggle, radio, [mic_input, audio_file])
412
  gr.Examples(
413
  [
414
+ ["./samples/p232_013_clean.wav", "Kitchen", "10", 15, 90, True, None],
415
+ ["./samples/p232_013_clean.wav", "Cafe", "10", 15, 90, True, None],
416
+ ["./samples/p232_019_clean.wav", "Cafe", "10", 15, 90, True, None],
417
+ ["./samples/p232_019_clean.wav", "River", "10", 15, 90, True, None],
418
  ],
419
  fn=demo_fn,
420
  inputs=inputs,