perf: reuse GCC-PHAT TDOA; skip 16 kHz AudioNormalizer
Delay-and-Sum still uses the tutorial STFT/cov/GCC-PHAT/DelaySum/ISTFT path. TDOA is refreshed every BEAMFORM_TDOA_EVERY hops (default 5).
This commit is contained in:
+35
-6
@@ -64,7 +64,8 @@ class AudioCleaner:
|
||||
chunk_s: float = 1.0,
|
||||
hop_s: float = 0.2,
|
||||
beamform: str = "auto",
|
||||
torch_num_threads: int = 1):
|
||||
torch_num_threads: int = 1,
|
||||
tdoa_every: int = 5):
|
||||
self.mode = mode
|
||||
self.beamform_mode = beamform
|
||||
self.sample_rate = sample_rate
|
||||
@@ -78,6 +79,14 @@ class AudioCleaner:
|
||||
self.backend = "off"
|
||||
self.last_dt_ms = -1.0
|
||||
self.torch_num_threads = max(1, int(torch_num_threads))
|
||||
self.tdoa_every = max(1, int(tdoa_every))
|
||||
self._stft = None
|
||||
self._cov = None
|
||||
self._gccphat = None
|
||||
self._delaysum = None
|
||||
self._istft = None
|
||||
self._last_tdoas = None
|
||||
self._tdoa_age = 0
|
||||
|
||||
self._load_torch()
|
||||
if beamform == "force":
|
||||
@@ -130,12 +139,23 @@ class AudioCleaner:
|
||||
return
|
||||
try:
|
||||
log.info("loading speechbrain DelaySum_Beamformer (GCC-PHAT)")
|
||||
self._normalizer = AudioNormalizer(
|
||||
sample_rate=self.sample_rate, mix="keep")
|
||||
# Native 16 kHz C920s: AudioNormalizer would resample 16k->16k.
|
||||
if self.sample_rate != SAMPLE_RATE:
|
||||
self._normalizer = AudioNormalizer(
|
||||
sample_rate=self.sample_rate, mix="keep")
|
||||
else:
|
||||
self._normalizer = None
|
||||
bf = DelaySum_Beamformer(sampling_rate=self.sample_rate)
|
||||
bf.eval()
|
||||
self._beamformer = bf
|
||||
log.info("DelaySum beamformer ready (stereo in, mono out)")
|
||||
self._stft = bf.stft
|
||||
self._cov = bf.cov
|
||||
self._gccphat = bf.gccphat
|
||||
self._delaysum = bf.delaysum
|
||||
self._istft = bf.istft
|
||||
log.info(
|
||||
"DelaySum beamformer ready (stereo in, mono out, tdoa_every=%d)",
|
||||
self.tdoa_every)
|
||||
except Exception as e: # noqa: BLE001
|
||||
log.warning("failed to load DelaySum_Beamformer: %s", e)
|
||||
self._beamformer = None
|
||||
@@ -216,9 +236,18 @@ class AudioCleaner:
|
||||
wav = torch.from_numpy(np.ascontiguousarray(stereo, dtype=np.float32))
|
||||
if self._normalizer is not None:
|
||||
wav = self._normalizer(wav, self.sample_rate)
|
||||
# DelaySum_Beamformer expects [batch, time, channels]
|
||||
# DelaySum expects [batch, time, channels]
|
||||
xs = wav.unsqueeze(0)
|
||||
with torch.no_grad():
|
||||
y = self._beamformer(wav.unsqueeze(0))
|
||||
Xs = self._stft(xs)
|
||||
if (self._last_tdoas is None
|
||||
or self._tdoa_age >= self.tdoa_every):
|
||||
XXs = self._cov(Xs)
|
||||
self._last_tdoas = self._gccphat(XXs)
|
||||
self._tdoa_age = 0
|
||||
self._tdoa_age += 1
|
||||
Ys = self._delaysum(Xs, self._last_tdoas)
|
||||
y = self._istft(Ys)
|
||||
out = y.squeeze().detach().cpu().numpy().astype(np.float32, copy=False)
|
||||
if out.ndim > 1:
|
||||
out = np.reshape(out, -1)
|
||||
|
||||
Reference in New Issue
Block a user