Fix output amplitude scaling in iterative Wiener filter (#420) - #447
Open
deekshaNVIDIA wants to merge 1 commit into
Open
deekshaNVIDIA wants to merge 1 commit into
deekshaNVIDIA wants to merge 1 commit into
Conversation
compute_filtered_output divided the frame DFT by sqrt(frame_len) before applying the Wiener gain and returning it to STFT.synthesis, which uses an unnormalized rfft/irfft pair. This scaled the enhanced signal down by sqrt(nfft) (and mutated the caller's stft.X in place). The division is unnecessary: the LPC coefficients derived from the intermediate time-domain frame are scale invariant, so removing it leaves the denoising behaviour unchanged while restoring the correct output amplitude. Add a regression test asserting the output RMS matches the input RMS for a near-passthrough signal across several FFT sizes. Fixes LCAV#420
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #420.
IterativeWiener.compute_filtered_outputdivided the frame DFT bysqrt(frame_len)before applying the Wiener gain and returning the spectrum:The spectrum is then handed to
STFT.synthesis, which uses an unnormalizedrfft/irfftpair (pyroomacoustics/transform/dft.py). So the returned spectrum must be on the same scale asstft.X. The extra1 / sqrt(frame_len)factor therefore scaled the enhanced signal down bysqrt(nfft)(and, as a side effect, mutated the caller'sstft.Xin place).This matches the report: rescaling the output by
sqrt(nfft)recovered the input amplitude fornfft = 512, 1024, 2048.Root cause / why removing the line is correct
The divided
frame_dftwas only used in two places:self.wiener_filt * frame_dft— this is the bug.s_i = irfft(self.wiener_filt * frame_dft), which feedslpc(s_i, ...).LPC coefficients are scale invariant (they depend on the normalized autocorrelation), and the gain
g^2is computed separately fromcurrent_frame(not froms_i). So the Wiener gain values are unchanged whether or not the division is applied — only the output amplitude changes. Removing the division fixes the amplitude and also removes the in-place mutation ofstft.X.Verification
Before (installed 0.10.1), output/input RMS ratio for a near-passthrough harmonic signal:
After the fix the ratio is ~1.0 for all sizes, and the relative denoising behaviour is unchanged.
Changes
frame_dft /= np.sqrt(self.frame_len)scaling incompute_filtered_output.test_iterative_wiener_output_scaling, a regression test asserting output RMS ≈ input RMS across several FFT sizes (fails on the old code with ratio ≈ 0.044, passes now).Test plan
pytest tests/denoise/test_iterative_wiener.pypasses (2 passed).black --checkandisort --check-onlypass on the changed files.