Unverified Commit 0fcb0c07 authored by Ryuichi Yamamoto's avatar Ryuichi Yamamoto Committed by GitHub
Browse files

lfilter: add an optional arg `clamp` (#600)



* lfilter: add an optional arg `clamp`

to give users control on the clamping behavior within the range [-1, 1],
which was hardcoded before.

Fixes #596

* doc string formatting

* lint

* doc string again
Co-authored-by: default avatarVincent QB <vincentqb@users.noreply.github.com>
parent fe30f30f
...@@ -28,6 +28,15 @@ class _LfilterMixin: ...@@ -28,6 +28,15 @@ class _LfilterMixin:
torch.testing.assert_allclose(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5) torch.testing.assert_allclose(output_waveform[:, 3:], waveform[:, 0:-3], atol=1e-5, rtol=1e-5)
def test_clamp(self):
input_signal = torch.ones(1, 44100 * 1, dtype=self.dtype, device=self.device)
b_coeffs = torch.tensor([1, 0], dtype=self.dtype, device=self.device)
a_coeffs = torch.tensor([1, -0.95], dtype=self.dtype, device=self.device)
output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=True)
self.assertTrue(output_signal.max() <= 1)
output_signal = F.lfilter(input_signal, a_coeffs, b_coeffs, clamp=False)
self.assertTrue(output_signal.max() > 1)
class TestLfilterFloat32CPU(_LfilterMixin, unittest.TestCase): class TestLfilterFloat32CPU(_LfilterMixin, unittest.TestCase):
device = torch.device('cpu') device = torch.device('cpu')
......
...@@ -673,21 +673,23 @@ def phase_vocoder( ...@@ -673,21 +673,23 @@ def phase_vocoder(
def lfilter( def lfilter(
waveform: Tensor, waveform: Tensor,
a_coeffs: Tensor, a_coeffs: Tensor,
b_coeffs: Tensor b_coeffs: Tensor,
clamp: bool = True,
) -> Tensor: ) -> Tensor:
r"""Perform an IIR filter by evaluating difference equation. r"""Perform an IIR filter by evaluating difference equation.
Args: Args:
waveform (Tensor): audio waveform of dimension of `(..., time)`. Must be normalized to -1 to 1. waveform (Tensor): audio waveform of dimension of ``(..., time)``. Must be normalized to -1 to 1.
a_coeffs (Tensor): denominator coefficients of difference equation of dimension of `(n_order + 1)`. a_coeffs (Tensor): denominator coefficients of difference equation of dimension of ``(n_order + 1)``.
Lower delays coefficients are first, e.g. `[a0, a1, a2, ...]`. Lower delays coefficients are first, e.g. ``[a0, a1, a2, ...]``.
Must be same size as b_coeffs (pad with 0's as necessary). Must be same size as b_coeffs (pad with 0's as necessary).
b_coeffs (Tensor): numerator coefficients of difference equation of dimension of `(n_order + 1)`. b_coeffs (Tensor): numerator coefficients of difference equation of dimension of ``(n_order + 1)``.
Lower delays coefficients are first, e.g. `[b0, b1, b2, ...]`. Lower delays coefficients are first, e.g. ``[b0, b1, b2, ...]``.
Must be same size as a_coeffs (pad with 0's as necessary). Must be same size as a_coeffs (pad with 0's as necessary).
clamp (bool, optional): If ``True``, clamp the output signal to be in the range [-1, 1] (Default: ``True``)
Returns: Returns:
Tensor: Waveform with dimension of `(..., time)`. Output will be clipped to -1 to 1. Tensor: Waveform with dimension of ``(..., time)``.
""" """
# pack batch # pack batch
shape = waveform.size() shape = waveform.size()
...@@ -731,7 +733,10 @@ def lfilter( ...@@ -731,7 +733,10 @@ def lfilter(
o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1) o0.addmv_(windowed_output_signal, a_coeffs_flipped, alpha=-1)
padded_output_waveform[:, i_sample + n_order - 1] = o0 padded_output_waveform[:, i_sample + n_order - 1] = o0
output = torch.clamp(padded_output_waveform[:, (n_order - 1):], min=-1., max=1.) output = padded_output_waveform[:, (n_order - 1):]
if clamp:
output = torch.clamp(output, min=-1., max=1.)
# unpack batch # unpack batch
output = output.reshape(shape[:-1] + output.shape[-1:]) output = output.reshape(shape[:-1] + output.shape[-1:])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment