From 074a7abd1a6c691804b8c8df2b7119c9815be0bd Mon Sep 17 00:00:00 2001 From: takenori-y Date: Thu, 13 Apr 2023 17:43:43 +0900 Subject: [PATCH 01/12] fix test --- tests/test_yingram.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_yingram.py b/tests/test_yingram.py index c97987e..7c0f462 100644 --- a/tests/test_yingram.py +++ b/tests/test_yingram.py @@ -27,6 +27,8 @@ def test_compatibility( ): if device == "cuda" and not torch.cuda.is_available(): return + if torch.get_default_dtype() != torch.float64: + return frame = diffsptk.Frame(fl, fp, center=False).to(device) yingram = diffsptk.Yingram(fl, sr, lag_min, lag_max, n_bin).to(device) From eb34fb25f3e185b40f6fb66d9293bc66bf606bbc Mon Sep 17 00:00:00 2001 From: takenori-y Date: Thu, 13 Apr 2023 17:46:25 +0900 Subject: [PATCH 02/12] support filtering in freq domain --- README.md | 2 +- diffsptk/core/imglsadf.py | 38 ++++++++---- diffsptk/core/mgc2sp.py | 4 +- diffsptk/core/mglsadf.py | 126 ++++++++++++++++++++++++++++++++------ diffsptk/core/zerodf.py | 2 +- tests/test_imglsadf.py | 78 +++++++++++------------ tests/test_istft.py | 2 +- tests/test_mglsadf.py | 53 ++++++++++------ tests/test_zerodf.py | 2 +- 9 files changed, 209 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index 0eb76a7..8821dec 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ mcep = diffsptk.MelCepstralAnalysis(cep_order=M, fft_length=n_fft, alpha=alpha, mc = mcep(X) # Reconstruct x. -mlsa = diffsptk.MLSA(filter_order=M, alpha=alpha, frame_period=fp, taylor_order=30) +mlsa = diffsptk.MLSA(filter_order=M, frame_period=fp, alpha=alpha, taylor_order=30) x_hat = mlsa(mlsa(x, -mc), mc) # Write reconstructed waveform. diff --git a/diffsptk/core/imglsadf.py b/diffsptk/core/imglsadf.py index 145d63b..23e1853 100644 --- a/diffsptk/core/imglsadf.py +++ b/diffsptk/core/imglsadf.py @@ -28,6 +28,9 @@ class PseudoInverseMGLSADigitalFilter(nn.Module): filter_order : int >= 0 [scalar] Order of filter coefficients, :math:`M`. + frame_period : int >= 1 [scalar] + Frame period, :math:`P`. + alpha : float [-1 < alpha < 1] Frequency warping factor, :math:`\\alpha`. @@ -37,36 +40,47 @@ class PseudoInverseMGLSADigitalFilter(nn.Module): c : int >= 1 [scalar] Number of stages. - frame_period : int >= 1 [scalar] - Frame period, :math:`P`. - ignore_gain : bool [scalar] If True, perform filtering without gain. phase : ['minimum', 'maximum', 'zero'] Filter type. - cascade : bool [scalar] - If True, use multi-stage FIR filter. + mode : ['multi-stage', 'single-stage', 'freq-domain'] + 'multi-stage' approximates the MLSA filter by cascading FIR filters based on the + Taylor series expansion. 'single-stage' uses a FIR filter whose coefficients are + the impulse response converted from mel-cepstral coefficients. 'freq-domain' + performs filtering in the frequency domain rather than time one. taylor_order : int >= 0 [scalar] - Order of Taylor series expansion (valid only if **cascade** is True). + Order of Taylor series expansion (valid only if **mode** is 'multi-stage'). + + cep_order : int >= 0 [scalar] + Order of linear cepstrum (valid only if **mode** is 'multi-stage'). ir_length : int >= 1 [scalar] - Length of impulse response (valid only if **cascade** is False). + Length of impulse response (valid only if **mode** is 'single-stage'). n_fft : int >= 1 [scalar] - Number of FFT bins for conversion (valid only if **cascade** is False). + Number of FFT bins for conversion (valid only if **mode** is 'single-stage'). - cep_order : int >= 0 [scalar] - Order of linear cepstrum (used to convert input to cepstrum). + **stft_kwargs : additional keyword arguments + See ShortTermFourierTransform (valid only if **mode** is 'freq-domain'). """ - def __init__(self, filter_order, **kwargs): + def __init__(self, filter_order, frame_period, **kwargs): super(PseudoInverseMGLSADigitalFilter, self).__init__() - self.mglsadf = PseudoMGLSADigitalFilter(filter_order, **kwargs) + # Change the default value of the order of Taylor series. + # This is because inverse filtering requires the large value. + if ( + kwargs.get("mode", "multi-stage") == "multi-stage" + and "taylor_order" not in kwargs + ): + kwargs["taylor_order"] = 40 + + self.mglsadf = PseudoMGLSADigitalFilter(filter_order, frame_period, **kwargs) def forward(self, y, mc): """Apply an inverse MGLSA digital filter. diff --git a/diffsptk/core/mgc2sp.py b/diffsptk/core/mgc2sp.py index 0e89a12..7aad934 100644 --- a/diffsptk/core/mgc2sp.py +++ b/diffsptk/core/mgc2sp.py @@ -47,7 +47,7 @@ class MelGeneralizedCepstrumToSpectrum(nn.Module): If True, assume gamma-multiplied cepstrum. out_format : ['db', 'log-magnitude', 'magnitude', 'power', \ - 'cycle', 'radian', 'degree'] + 'cycle', 'radian', 'degree', 'complex'] Output format. n_fft : int >> :math:`L` [scalar] @@ -88,6 +88,8 @@ def __init__( elif out_format == 6 or out_format == "degree": c = 180 / math.pi self.convert = lambda x: x.imag * c + elif out_format == "complex": + self.convert = lambda x: torch.polar(torch.exp(x.real), x.imag) else: raise ValueError(f"out_format {out_format} is not supported") diff --git a/diffsptk/core/mglsadf.py b/diffsptk/core/mglsadf.py index 483a01e..4ddec59 100644 --- a/diffsptk/core/mglsadf.py +++ b/diffsptk/core/mglsadf.py @@ -20,8 +20,14 @@ from ..misc.utils import Lambda from ..misc.utils import check_size from ..misc.utils import get_gamma +from .b2mc import MLSADigitalFilterCoefficientsToMelCepstrum +from .gnorm import GeneralizedCepstrumGainNormalization +from .istft import InverseShortTermFourierTransform from .linear_intpl import LinearInterpolation +from .mc2b import MelCepstrumToMLSADigitalFilterCoefficients from .mgc2mgc import MelGeneralizedCepstrumToMelGeneralizedCepstrum +from .mgc2sp import MelGeneralizedCepstrumToSpectrum +from .stft import ShortTermFourierTransform def mirror(x, half=False): @@ -41,6 +47,9 @@ class PseudoMGLSADigitalFilter(nn.Module): filter_order : int >= 0 [scalar] Order of filter coefficients, :math:`M`. + frame_period : int >= 1 [scalar] + Frame period, :math:`P`. + alpha : float [-1 < alpha < 1] Frequency warping factor, :math:`\\alpha`. @@ -50,29 +59,32 @@ class PseudoMGLSADigitalFilter(nn.Module): c : int >= 1 [scalar] Number of stages. - frame_period : int >= 1 [scalar] - Frame period, :math:`P`. - ignore_gain : bool [scalar] If True, perform filtering without gain. phase : ['minimum', 'maximum', 'zero'] Filter type. - cascade : bool [scalar] - If True, use multi-stage FIR filter. + mode : ['multi-stage', 'single-stage', 'freq-domain'] + 'multi-stage' approximates the MLSA filter by cascading FIR filters based on the + Taylor series expansion. 'single-stage' uses a FIR filter whose coefficients are + the impulse response converted from mel-cepstral coefficients. 'freq-domain' + performs filtering in the frequency domain rather than the time one. taylor_order : int >= 0 [scalar] - Order of Taylor series expansion (valid only if **cascade** is True). + Order of Taylor series expansion (valid only if **mode** is 'multi-stage'). + + cep_order : int >= 0 [scalar] + Order of linear cepstrum (valid only if **mode** is 'multi-stage'). ir_length : int >= 1 [scalar] - Length of impulse response (valid only if **cascade** is False). + Length of impulse response (valid only if **mode** is 'single-stage'). n_fft : int >= 1 [scalar] - Number of FFT bins for conversion (valid only if **cascade** is False). + Number of FFT bins for conversion (valid only if **mode** is 'single-stage'). - cep_order : int >= 0 [scalar] - Order of linear cepstrum (used to convert input to cepstrum). + **stft_kwargs : additional keyword arguments + See ShortTermFourierTransform (valid only if **mode** is 'freq-domain'). References ---------- @@ -84,13 +96,14 @@ class PseudoMGLSADigitalFilter(nn.Module): def __init__( self, filter_order, + frame_period, + *, alpha=0, gamma=0, c=None, - frame_period=1, ignore_gain=False, phase="minimum", - cascade=True, + mode="multi-stage", **kwargs, ): super(PseudoMGLSADigitalFilter, self).__init__() @@ -100,26 +113,38 @@ def __init__( gamma = get_gamma(gamma, c) - if cascade: + if mode == "multi-stage": self.mglsadf = MultiStageFIRFilter( filter_order, + frame_period, alpha=alpha, gamma=gamma, - frame_period=frame_period, ignore_gain=ignore_gain, phase=phase, **kwargs, ) - else: + elif mode == "single-stage": self.mglsadf = SingleStageFIRFilter( filter_order, + frame_period, + alpha=alpha, + gamma=gamma, + ignore_gain=ignore_gain, + phase=phase, + **kwargs, + ) + elif mode == "freq-domain": + self.mglsadf = FrequencyDomainFIRFilter( + filter_order, + frame_period, alpha=alpha, gamma=gamma, - frame_period=frame_period, ignore_gain=ignore_gain, phase=phase, **kwargs, ) + else: + raise ValueError(f"mode {mode} is not supported") def forward(self, x, mc): """Apply an MGLSA digital filter. @@ -162,9 +187,10 @@ class MultiStageFIRFilter(nn.Module): def __init__( self, filter_order, + frame_period, + *, alpha=0, gamma=0, - frame_period=1, ignore_gain=False, phase="minimum", taylor_order=20, @@ -224,14 +250,14 @@ class SingleStageFIRFilter(nn.Module): def __init__( self, filter_order, + frame_period, + *, alpha=0, gamma=0, - frame_period=1, ignore_gain=False, phase="minimum", ir_length=2000, n_fft=4096, - cep_order=199, ): super(SingleStageFIRFilter, self).__init__() @@ -261,9 +287,10 @@ def __init__( else: self.mgc2c = MelGeneralizedCepstrumToMelGeneralizedCepstrum( filter_order, - cep_order, + ir_length - 1, in_alpha=alpha, in_gamma=gamma, + n_fft=n_fft, ) self.c2ir = nn.Sequential( Lambda(lambda x: torch.fft.hfft(x, n=n_fft)), @@ -297,8 +324,67 @@ def forward(self, x, mc): h = h / h[..., -1:] elif self.phase == "maximum": h = h / h[..., :1] + elif self.phase == "zero": + pass + else: + raise RuntimeError x = self.pad(x) x = x.unfold(-1, h.size(-1), 1) y = (x * h).sum(-1) return y + + +class FrequencyDomainFIRFilter(nn.Module): + def __init__( + self, + filter_order, + frame_period, + *, + alpha=0, + gamma=0, + ignore_gain=False, + phase="minimum", + frame_length=400, + fft_length=512, + **kwargs, + ): + super(FrequencyDomainFIRFilter, self).__init__() + + self.ignore_gain = ignore_gain + + if self.ignore_gain: + self.gnorm = GeneralizedCepstrumGainNormalization(filter_order, gamma=gamma) + self.mc2b = MelCepstrumToMLSADigitalFilterCoefficients( + filter_order, alpha=alpha + ) + self.b2mc = MLSADigitalFilterCoefficientsToMelCepstrum( + filter_order, alpha=alpha + ) + + self.stft = ShortTermFourierTransform( + frame_length, frame_period, fft_length, out_format="complex", **kwargs + ) + self.istft = InverseShortTermFourierTransform( + frame_length, frame_period, fft_length, **kwargs + ) + self.mgc2sp = MelGeneralizedCepstrumToSpectrum( + filter_order, + fft_length, + alpha=alpha, + gamma=gamma, + out_format="magnitude" if phase == "zero" else "complex", + ) + + def forward(self, x, mc): + if self.ignore_gain: + b = self.mc2b(mc) + b = self.gnorm(b) + b[..., 0] = 0 + mc = self.b2mc(b) + + H = self.mgc2sp(mc) + X = self.stft(x) + Y = H * X + y = self.istft(Y, out_length=x.size(-1)) + return y diff --git a/diffsptk/core/zerodf.py b/diffsptk/core/zerodf.py index 849eaa0..7266527 100644 --- a/diffsptk/core/zerodf.py +++ b/diffsptk/core/zerodf.py @@ -37,7 +37,7 @@ class AllZeroDigitalFilter(nn.Module): """ - def __init__(self, filter_order, frame_period=1, ignore_gain=False): + def __init__(self, filter_order, frame_period, ignore_gain=False): super(AllZeroDigitalFilter, self).__init__() self.filter_order = filter_order diff --git a/tests/test_imglsadf.py b/tests/test_imglsadf.py index 1c7a61e..eeee61f 100644 --- a/tests/test_imglsadf.py +++ b/tests/test_imglsadf.py @@ -14,8 +14,8 @@ # limitations under the License. # # ------------------------------------------------------------------------ # +import numpy as np import pytest -import torch import diffsptk import tests.utils as U @@ -23,53 +23,47 @@ @pytest.mark.parametrize("device", ["cpu", "cuda"]) @pytest.mark.parametrize("ignore_gain", [False, True]) -@pytest.mark.parametrize("cascade", [False, True]) -def test_compatibility(device, ignore_gain, cascade, c=0, alpha=0.42, M=24, P=80): - if device == "cuda" and not torch.cuda.is_available(): - return +@pytest.mark.parametrize("mode", ["multi-stage", "single-stage", "freq-domain"]) +def test_compatibility( + device, ignore_gain, mode, c=0, alpha=0.42, M=24, P=80, L=400, fft_length=512 +): + if mode == "multi-stage": + params = {"cep_order": 100} + elif mode == "single-stage": + params = {"ir_length": 400, "n_fft": 1024} + elif mode == "freq-domain": + params = {"frame_length": L, "fft_length": fft_length} - # FIXME: numerical error problem. - if cascade and torch.get_default_dtype() != torch.float64: # pragma: no cover - return - - # Prepare data for C++. - tmp1 = "mglsadf.tmp1" - tmp2 = "mglsadf.tmp2" - U.call(f"x2x +sd tools/SPTK/asset/data.short > {tmp1}", get=False) - cmd = ( - f"x2x +sd tools/SPTK/asset/data.short | " - f"frame -p {P} -l 400 | " - f"window -w 1 -n 1 -l 400 -L 512 | " - f"mgcep -c {c} -a {alpha} -m {M} -l 512 > {tmp2}" - ) - U.call(f"{cmd}", get=False) - - # Prepare data for Python. - y = torch.from_numpy(U.call(f"cat {tmp1}")).to(device) - mc = torch.from_numpy(U.call(f"cat {tmp2}").reshape(-1, M + 1)).to(device) - U.call(f"rm {tmp1} {tmp2}", get=False) - - if cascade: - params = {"cep_order": 100, "taylor_order": 40} - else: - params = {"ir_length": 500, "n_fft": 1024} - - # Get residual signal. imglsadf = diffsptk.IMLSA( M, - frame_period=P, + P, alpha=alpha, c=c, ignore_gain=ignore_gain, - cascade=cascade, phase="minimum", + mode=mode, **params, - ).to(device) - x = imglsadf(y, mc) - - # Get reconstructed signal. - y_hat = imglsadf(x, -mc) + ) - # Compute correlation between two signals. - r = torch.corrcoef(torch.stack([y, y_hat]))[0, 1] - assert torch.gt(r, 0.99) + tmp1 = "mglsadf.tmp1" + tmp2 = "mglsadf.tmp2" + # Note that using waveform [-1, 1] is numerically stable. + cmd1 = f"x2x +sd tools/SPTK/asset/data.short | sopr -d 32768 > {tmp1}" + cmd2 = ( + f"x2x +sd tools/SPTK/asset/data.short | " + "sopr -d 32768 | " + f"frame -p {P} -l {L} | " + f"window -w 1 -n 1 -l {L} -L {fft_length} | " + f"mgcep -c {c} -a {alpha} -m {M} -l {fft_length} > {tmp2}" + ) + opt = "-k" if ignore_gain else "" + U.check_compatibility( + device, + imglsadf, + [cmd1, cmd2], + [f"cat {tmp1}", f"cat {tmp2}"], + f"imglsadf {tmp2} < {tmp1} -c {c} -a {alpha} -m {M} -p {P} {opt}", + [f"rm {tmp1} {tmp2}"], + dx=[None, M + 1], + eq=lambda a, b: np.corrcoef(a, b)[0, 1] > 0.99, + ) diff --git a/tests/test_istft.py b/tests/test_istft.py index 3665b9b..180f67d 100644 --- a/tests/test_istft.py +++ b/tests/test_istft.py @@ -37,5 +37,5 @@ def test_compatibility(device): istft = diffsptk.ISTFT(**stft_params).to(device) x = torch.from_numpy(U.call("x2x +sd tools/SPTK/asset/data.short")).to(device) - y = istft(stft(x), out_length=x.size(0)) + y = istft(stft(x), out_length=x.size(0)).round() assert torch.allclose(x, y) diff --git a/tests/test_mglsadf.py b/tests/test_mglsadf.py index b4c8eec..349a2b7 100644 --- a/tests/test_mglsadf.py +++ b/tests/test_mglsadf.py @@ -25,51 +25,66 @@ @pytest.mark.parametrize("device", ["cpu", "cuda"]) @pytest.mark.parametrize("ignore_gain", [False, True]) -@pytest.mark.parametrize("cascade", [False, True]) +@pytest.mark.parametrize("mode", ["multi-stage", "single-stage", "freq-domain"]) @pytest.mark.parametrize("c", [0, 10]) -def test_compatibility(device, ignore_gain, cascade, c, alpha=0.42, M=24, P=80): - if cascade: - params = {"cep_order": 100, "taylor_order": 20} - else: +def test_compatibility( + device, ignore_gain, mode, c, alpha=0.42, M=24, P=80, L=400, fft_length=512 +): + if mode == "multi-stage": + params = {"cep_order": 100} + elif mode == "single-stage": params = {"ir_length": 200, "n_fft": 512} + elif mode == "freq-domain": + params = {"frame_length": L, "fft_length": fft_length} mglsadf = diffsptk.MLSA( M, - frame_period=P, + P, alpha=alpha, c=c, ignore_gain=ignore_gain, - cascade=cascade, phase="minimum", + mode=mode, **params, ) tmp1 = "mglsadf.tmp1" tmp2 = "mglsadf.tmp2" - opt = "-k" if ignore_gain else "" - cmd = ( + T = os.path.getsize("tools/SPTK/asset/data.short") // 2 + cmd1 = f"nrand -l {T} > {tmp1}" + cmd2 = ( f"x2x +sd tools/SPTK/asset/data.short | " - f"frame -p {P} -l 400 | " - f"window -w 1 -n 1 -l 400 -L 512 | " - f"mgcep -c {c} -a {alpha} -m {M} -l 512 -E -60 > {tmp2}" + f"frame -p {P} -l {L} | " + f"window -w 1 -n 1 -l {L} -L {fft_length} | " + f"mgcep -c {c} -a {alpha} -m {M} -l {fft_length} -E -60 > {tmp2}" ) - T = os.path.getsize("tools/SPTK/asset/data.short") // 2 + opt = "-k" if ignore_gain else "" + threshold = 0.98 if mode == "freq-domain" and ignore_gain else 0.99 U.check_compatibility( device, mglsadf, - [f"nrand -l {T} > {tmp1}", cmd], + [cmd1, cmd2], [f"cat {tmp1}", f"cat {tmp2}"], - f"mglsadf {tmp2} < {tmp1} -i 1 -m {M} -p {P} -c {c} -a {alpha} {opt}", + f"mglsadf {tmp2} < {tmp1} -m {M} -p {P} -c {c} -a {alpha} {opt}", [f"rm {tmp1} {tmp2}"], dx=[None, M + 1], - eq=lambda a, b: np.corrcoef(a, b)[0, 1] > 0.99, + eq=lambda a, b: np.corrcoef(a, b)[0, 1] > threshold, ) @pytest.mark.parametrize("device", ["cpu", "cuda"]) @pytest.mark.parametrize("ignore_gain", [False, True]) -@pytest.mark.parametrize("cascade", [False, True]) @pytest.mark.parametrize("phase", ["minimum", "maximum", "zero"]) -def test_differentiable(device, ignore_gain, cascade, phase, B=4, T=20, M=4): - mglsadf = diffsptk.MLSA(M, ignore_gain=ignore_gain, cascade=cascade, phase=phase) +@pytest.mark.parametrize("mode", ["multi-stage", "single-stage", "freq-domain"]) +def test_differentiable(device, ignore_gain, phase, mode, B=4, T=20, M=4): + if mode == "multi-stage": + params = {"cep_order": 100} + elif mode == "single-stage": + params = {"ir_length": 200, "n_fft": 512} + elif mode == "freq-domain": + params = {"frame_length": 4, "fft_length": 16} + + mglsadf = diffsptk.MLSA( + M, 1, ignore_gain=ignore_gain, phase=phase, mode=mode, **params + ) U.check_differentiable(device, mglsadf, [(B, T), (B, T, M + 1)]) diff --git a/tests/test_zerodf.py b/tests/test_zerodf.py index facbef9..9c3328a 100644 --- a/tests/test_zerodf.py +++ b/tests/test_zerodf.py @@ -33,7 +33,7 @@ def test_compatibility(device, ignore_gain, M=3, T=100, P=10): zerodf, [f"nrand -l {T} > {tmp1}", f"nrand -l {T//P*(M+1)} > {tmp2}"], [f"cat {tmp1}", f"cat {tmp2}"], - f"zerodf {tmp2} < {tmp1} -i 1 -m {M} -p {P} {opt}", + f"zerodf {tmp2} < {tmp1} -m {M} -p {P} {opt}", [f"rm {tmp1} {tmp2}"], dx=[None, M + 1], ) From 11b94b594c2816d6bd1d0bde326868d49af17712 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Thu, 13 Apr 2023 20:28:12 +0900 Subject: [PATCH 03/12] fix test --- tests/test_mglsadf.py | 4 ++-- tests/test_yingram.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_mglsadf.py b/tests/test_mglsadf.py index 349a2b7..84c240f 100644 --- a/tests/test_mglsadf.py +++ b/tests/test_mglsadf.py @@ -78,9 +78,9 @@ def test_compatibility( @pytest.mark.parametrize("mode", ["multi-stage", "single-stage", "freq-domain"]) def test_differentiable(device, ignore_gain, phase, mode, B=4, T=20, M=4): if mode == "multi-stage": - params = {"cep_order": 100} + params = {"cep_order": 10} elif mode == "single-stage": - params = {"ir_length": 200, "n_fft": 512} + params = {"ir_length": 20, "n_fft": 32} elif mode == "freq-domain": params = {"frame_length": 4, "fft_length": 16} diff --git a/tests/test_yingram.py b/tests/test_yingram.py index 7c0f462..ecb7d0a 100644 --- a/tests/test_yingram.py +++ b/tests/test_yingram.py @@ -27,7 +27,7 @@ def test_compatibility( ): if device == "cuda" and not torch.cuda.is_available(): return - if torch.get_default_dtype() != torch.float64: + if torch.get_default_dtype() != torch.float64: # pragma: no cover return frame = diffsptk.Frame(fl, fp, center=False).to(device) From 54416759ec0e9caee1fb7f36fff78e019b8407ee Mon Sep 17 00:00:00 2001 From: takenori-y Date: Thu, 13 Apr 2023 21:31:48 +0900 Subject: [PATCH 04/12] fix doc --- diffsptk/core/imglsadf.py | 49 +-------------------------------------- diffsptk/core/istft.py | 2 +- diffsptk/core/mglsadf.py | 7 +++--- diffsptk/core/msvq.py | 4 ++-- diffsptk/core/unframe.py | 2 +- diffsptk/core/vq.py | 4 ++-- diffsptk/core/yingram.py | 8 +++++-- 7 files changed, 17 insertions(+), 59 deletions(-) diff --git a/diffsptk/core/imglsadf.py b/diffsptk/core/imglsadf.py index 23e1853..2455a72 100644 --- a/diffsptk/core/imglsadf.py +++ b/diffsptk/core/imglsadf.py @@ -20,54 +20,7 @@ class PseudoInverseMGLSADigitalFilter(nn.Module): - """See `this page `_ - for details. - - Parameters - ---------- - filter_order : int >= 0 [scalar] - Order of filter coefficients, :math:`M`. - - frame_period : int >= 1 [scalar] - Frame period, :math:`P`. - - alpha : float [-1 < alpha < 1] - Frequency warping factor, :math:`\\alpha`. - - gamma : float [-1 <= gamma <= 1] - Gamma, :math:`\\gamma`. - - c : int >= 1 [scalar] - Number of stages. - - ignore_gain : bool [scalar] - If True, perform filtering without gain. - - phase : ['minimum', 'maximum', 'zero'] - Filter type. - - mode : ['multi-stage', 'single-stage', 'freq-domain'] - 'multi-stage' approximates the MLSA filter by cascading FIR filters based on the - Taylor series expansion. 'single-stage' uses a FIR filter whose coefficients are - the impulse response converted from mel-cepstral coefficients. 'freq-domain' - performs filtering in the frequency domain rather than time one. - - taylor_order : int >= 0 [scalar] - Order of Taylor series expansion (valid only if **mode** is 'multi-stage'). - - cep_order : int >= 0 [scalar] - Order of linear cepstrum (valid only if **mode** is 'multi-stage'). - - ir_length : int >= 1 [scalar] - Length of impulse response (valid only if **mode** is 'single-stage'). - - n_fft : int >= 1 [scalar] - Number of FFT bins for conversion (valid only if **mode** is 'single-stage'). - - **stft_kwargs : additional keyword arguments - See ShortTermFourierTransform (valid only if **mode** is 'freq-domain'). - - """ + """See :func:`~diffsptk.PseudoMGLSADigitalFilter` for details.""" def __init__(self, filter_order, frame_period, **kwargs): super(PseudoInverseMGLSADigitalFilter, self).__init__() diff --git a/diffsptk/core/istft.py b/diffsptk/core/istft.py index 8e202bf..83acb57 100644 --- a/diffsptk/core/istft.py +++ b/diffsptk/core/istft.py @@ -22,7 +22,7 @@ class InverseShortTermFourierTransform(nn.Module): - """This is the opposite module to ShortTermFourierTransform. + """This is the opposite module to :func:`~diffsptk.ShortTermFourierTransform` Parameters ---------- diff --git a/diffsptk/core/mglsadf.py b/diffsptk/core/mglsadf.py index 4ddec59..ff5fa04 100644 --- a/diffsptk/core/mglsadf.py +++ b/diffsptk/core/mglsadf.py @@ -68,8 +68,8 @@ class PseudoMGLSADigitalFilter(nn.Module): mode : ['multi-stage', 'single-stage', 'freq-domain'] 'multi-stage' approximates the MLSA filter by cascading FIR filters based on the Taylor series expansion. 'single-stage' uses a FIR filter whose coefficients are - the impulse response converted from mel-cepstral coefficients. 'freq-domain' - performs filtering in the frequency domain rather than the time one. + the impulse response converted from input mel-cepstral coefficients using FFT. + 'freq-domain' performs filtering in the frequency domain rather than time one. taylor_order : int >= 0 [scalar] Order of Taylor series expansion (valid only if **mode** is 'multi-stage'). @@ -84,7 +84,8 @@ class PseudoMGLSADigitalFilter(nn.Module): Number of FFT bins for conversion (valid only if **mode** is 'single-stage'). **stft_kwargs : additional keyword arguments - See ShortTermFourierTransform (valid only if **mode** is 'freq-domain'). + See :func:`~diffsptk.ShortTermFourierTransform` (valid only if **mode** is + 'freq-domain'). References ---------- diff --git a/diffsptk/core/msvq.py b/diffsptk/core/msvq.py index 03c7438..62d7a50 100644 --- a/diffsptk/core/msvq.py +++ b/diffsptk/core/msvq.py @@ -38,7 +38,7 @@ class MultiStageVectorQuantization(nn.Module): Number of stages (quantizers), :math:`Q`. **kwargs : additional keyword arguments - See vector-quantize-pytorch repository for details. + See `this page`_ for details. """ @@ -69,7 +69,7 @@ def forward(self, x, codebooks=None, **kwargs): External codebooks. If None, use internal codebooks. **kwargs : additional keyword arguments - See vector-quantize-pytorch repository for details. + See `this page`_ for details. Returns ------- diff --git a/diffsptk/core/unframe.py b/diffsptk/core/unframe.py index 0b9f1d0..fd15f32 100644 --- a/diffsptk/core/unframe.py +++ b/diffsptk/core/unframe.py @@ -21,7 +21,7 @@ class Unframe(nn.Module): - """This is the opposite module to Frame. + """This is the opposite module to :func:`~diffsptk.Frame`. Parameters ---------- diff --git a/diffsptk/core/vq.py b/diffsptk/core/vq.py index 28eef54..46a64b3 100644 --- a/diffsptk/core/vq.py +++ b/diffsptk/core/vq.py @@ -35,7 +35,7 @@ class VectorQuantization(nn.Module): Codebook size, :math:`K`. **kwargs : additional keyword arguments - See vector-quantize-pytorch repository for details. + See `this page`_ for details. """ @@ -65,7 +65,7 @@ def forward(self, x, codebook=None, **kwargs): External codebook. If None, use internal codebook. **kwargs : additional keyword arguments - See vector-quantize-pytorch repository for details. + See `this page`_ for details. Returns ------- diff --git a/diffsptk/core/yingram.py b/diffsptk/core/yingram.py index 3f86575..7dac9d1 100644 --- a/diffsptk/core/yingram.py +++ b/diffsptk/core/yingram.py @@ -52,8 +52,12 @@ class Yingram(nn.Module): References ---------- - .. [1] H. Choi et al., "Neural analysis and synthesis: Reconstructing speech from - self-supervised representations,", *arXiv:2110.14513*, 2021. + .. [1] A. Cheveigne and H. Kawahara, "YIN, a fundamental frequency estimator for + speech and music," *The Journal of the Acoustical Society of America*, + vol. 111, 2002. + + .. [2] H. Choi et al., "Neural analysis and synthesis: Reconstructing speech from + self-supervised representations," *arXiv:2110.14513*, 2021. """ From a376d56a39465999773d6181baf13fdef8a52f20 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Mon, 17 Apr 2023 11:18:39 +0900 Subject: [PATCH 05/12] add docs --- diffsptk/core/dct.py | 13 +++++++++++++ diffsptk/core/delta.py | 17 +++++++++++++++++ diffsptk/core/fbank.py | 3 +-- diffsptk/core/freqt2.py | 22 +++++++++++++++++++++- diffsptk/core/mgc2mgc.py | 35 ++++++++++++++++++++++++++++++++++- diffsptk/core/mglsadf.py | 20 ++++++++++++++++++-- diffsptk/core/pqmf.py | 40 +++++++++++++++++++++++++++++++++++++++- 7 files changed, 143 insertions(+), 7 deletions(-) diff --git a/diffsptk/core/dct.py b/diffsptk/core/dct.py index b75beda..9424e6d 100644 --- a/diffsptk/core/dct.py +++ b/diffsptk/core/dct.py @@ -22,6 +22,19 @@ def make_dct_matrix(L): + """Make DCT matrix. + + Parameters + ---------- + L : int >= 1 [scalar] + DCT length, :math:`L`. + + Returns + ------- + W : ndarray [shape=(L, L)] + DCT matrix. + + """ W = np.empty((L, L)) n = (np.arange(L) + 0.5) * (np.pi / L) c = np.sqrt(2 / L) diff --git a/diffsptk/core/delta.py b/diffsptk/core/delta.py index 70bbc8e..046ec34 100644 --- a/diffsptk/core/delta.py +++ b/diffsptk/core/delta.py @@ -22,6 +22,23 @@ def make_window(seed, static_out=True): + """Make window for delta computation. + + Parameters + ---------- + seed : list[list[float]] or list[int] + Delta coefficients or width(s) of 1st (and 2nd) regression coefficients. + + static_out : bool [scalar] + If True, make window for static component. + + Returns + ------- + window : ndarray [shape=(D+1, W)] + Window for delta computation, where D is the number of dynamic components and + W is the width of window. + + """ if not isinstance(seed, (tuple, list)): raise ValueError("seed must be tuple or list") diff --git a/diffsptk/core/fbank.py b/diffsptk/core/fbank.py index 2695918..fe3bb00 100644 --- a/diffsptk/core/fbank.py +++ b/diffsptk/core/fbank.py @@ -26,8 +26,7 @@ def hz_to_mel(x): def sample_mel(n, fft_length, sample_rate): - hz = sample_rate * n / fft_length - return hz_to_mel(hz) + return hz_to_mel(sample_rate * n / fft_length) class MelFilterBankAnalysis(nn.Module): diff --git a/diffsptk/core/freqt2.py b/diffsptk/core/freqt2.py index d7af547..4f3a338 100644 --- a/diffsptk/core/freqt2.py +++ b/diffsptk/core/freqt2.py @@ -22,13 +22,33 @@ def warp(omega, alpha, theta): + """Warp frequency. + + Parameters + ---------- + omega : float [0 <= omega <= 2pi] + Frequency. + + alpha : float [-1 < alpha < 1] + Frequency warping factor, :math:`\\alpha`. + + theta : float [0 <= theta <= 1] + Emphasis frequency, :math:`\\theta`. + + Returns + ------- + w : float + Warped frequency. + + """ x = omega - theta y = omega + theta - return ( + w = ( omega + np.arctan2(alpha * np.sin(x), 1 - alpha * np.cos(x)) + np.arctan2(alpha * np.sin(y), 1 - alpha * np.cos(y)) ) + return w class SecondOrderAllPassFrequencyTransform(nn.Module): diff --git a/diffsptk/core/mgc2mgc.py b/diffsptk/core/mgc2mgc.py index 30522c7..df13f5f 100644 --- a/diffsptk/core/mgc2mgc.py +++ b/diffsptk/core/mgc2mgc.py @@ -29,7 +29,27 @@ class GeneralizedCepstrumToGeneralizedCepstrum(nn.Module): - def __init__(self, in_order, out_order, in_gamma, out_gamma, n_fft): + """Generalized cepstral transformation module. + + Parameters + ---------- + in_order : int >= 0 [scalar] + Order of input cepstrum, :math:`M_1`. + + out_order : int >= 0 [scalar] + Order of output cepstrum, :math:`M_2`. + + in_gamma : float [-1 <= in_gamma <= 1] + Input gamma, :math:`\\gamma_1`. + + out_gamma : float [-1 <= out_gamma <= 1] + Output gamma, :math:`\\gamma_2`. + + n_fft : int >> :math:`M_1, M_2` [scalar] + Number of FFT bins. Accurate conversion requires the large value. + + """ + def __init__(self, in_order, out_order, in_gamma, out_gamma, n_fft=512): super(GeneralizedCepstrumToGeneralizedCepstrum, self).__init__() self.in_order = in_order @@ -45,6 +65,19 @@ def __init__(self, in_order, out_order, in_gamma, out_gamma, n_fft): assert max(self.in_order, self.out_order) + 1 < self.n_fft def forward(self, c1): + """Perform generalized cepstral transformation. + + Parameters + ---------- + c1 : Tensor [shape=(..., M_1+1)] + Input cepstrum. + + Returns + ------- + c2 : Tensor [shape=(..., M_2+1)] + Output cepstrum. + + """ c01 = torch.cat((c1[..., :1] * 0, c1[..., 1:]), dim=-1) C1 = torch.fft.fft(c01, n=self.n_fft) diff --git a/diffsptk/core/mglsadf.py b/diffsptk/core/mglsadf.py index ff5fa04..46007b2 100644 --- a/diffsptk/core/mglsadf.py +++ b/diffsptk/core/mglsadf.py @@ -31,11 +31,27 @@ def mirror(x, half=False): + """Mirror the input tensor. + + Parameters + ---------- + x : Tensor [shape=(..., L)] + Input tensor. + + half : bool [scalar] + If True, multiply all elements except the first one by 0.5. + + Returns + ------- + y : Tensor [shape=(..., 2L-1)] + Output tensor. + + """ x0, x1 = torch.split(x, [1, x.size(-1) - 1], dim=-1) if half: x1 = x1 * 0.5 - x = torch.cat((x1.flip(-1), x0, x1), dim=-1) - return x + y = torch.cat((x1.flip(-1), x0, x1), dim=-1) + return y class PseudoMGLSADigitalFilter(nn.Module): diff --git a/diffsptk/core/pqmf.py b/diffsptk/core/pqmf.py index eea0c39..9a80e95 100644 --- a/diffsptk/core/pqmf.py +++ b/diffsptk/core/pqmf.py @@ -34,6 +34,43 @@ def make_filter_banks( decay=0.5, eps=1e-6, ): + """Make filter-bank coefficients. + + Parameters + ---------- + n_band : int >= 1 [scalar] + Number of subbands, :math:`K`. + + filter_order : int >= 1 [scalar] + Order of filter, :math:`M`. + + mode : ['analysis' or 'synthesis'] + Analysis or synthesis. + + alpha : float > 0 [scalar] + Stopband attenuation in dB. + + n_iter : int >= 1 [scalar] + Number of iterations. + + step_size : float > 0 [scalar] + Step size. + + decay : float > 0 [scalar] + Decay factor of step size. + + eps : float >= 0 [scalar] + Tolerance. + + Returns + ------- + filters : ndarray [shape=(K, M + 1)] + Filter-bank coefficients. + + is_converged : bool + Whether the algorithm converged. + + """ assert 1 <= n_band assert 1 <= filter_order assert 1 <= n_iter @@ -97,8 +134,9 @@ def alpha_to_beta(alpha): b = (-1) ** k * (np.pi / 4) * sign c = 2 * prototype_filter filters.append(c * np.cos(a + b)) + filters = np.asarray(filters) - return np.asarray(filters), is_converged + return filters, is_converged class PseudoQuadratureMirrorFilterBanks(nn.Module): From 02ab4e6290599b419c1ba6efe8625a3616898a6a Mon Sep 17 00:00:00 2001 From: takenori-y Date: Mon, 17 Apr 2023 11:27:30 +0900 Subject: [PATCH 06/12] add line --- diffsptk/core/mgc2mgc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/diffsptk/core/mgc2mgc.py b/diffsptk/core/mgc2mgc.py index df13f5f..fa77576 100644 --- a/diffsptk/core/mgc2mgc.py +++ b/diffsptk/core/mgc2mgc.py @@ -49,6 +49,7 @@ class GeneralizedCepstrumToGeneralizedCepstrum(nn.Module): Number of FFT bins. Accurate conversion requires the large value. """ + def __init__(self, in_order, out_order, in_gamma, out_gamma, n_fft=512): super(GeneralizedCepstrumToGeneralizedCepstrum, self).__init__() From 8df268417f5bff76688c22a61e5b2a9a40bc39b0 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Mon, 17 Apr 2023 16:44:27 +0900 Subject: [PATCH 07/12] fix doc --- diffsptk/core/mgc2mgc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diffsptk/core/mgc2mgc.py b/diffsptk/core/mgc2mgc.py index fa77576..91f5ddc 100644 --- a/diffsptk/core/mgc2mgc.py +++ b/diffsptk/core/mgc2mgc.py @@ -70,12 +70,12 @@ def forward(self, c1): Parameters ---------- - c1 : Tensor [shape=(..., M_1+1)] + c1 : Tensor [shape=(..., M1+1)] Input cepstrum. Returns ------- - c2 : Tensor [shape=(..., M_2+1)] + c2 : Tensor [shape=(..., M2+1)] Output cepstrum. """ From 66f139d142bb2e83091df8b36ec7ba98df51ab45 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Tue, 18 Apr 2023 12:58:06 +0900 Subject: [PATCH 08/12] remove setup.py --- .gitignore | 3 +-- Makefile | 33 ++++++++++++++---------- diffsptk/version.py | 2 +- pyproject.toml | 62 +++++++++++++++++++++++++++++++++++++++++++++ setup.py | 45 -------------------------------- tools/Makefile | 10 ++++++-- 6 files changed, 91 insertions(+), 64 deletions(-) delete mode 100644 setup.py diff --git a/.gitignore b/.gitignore index d98e498..82fb04d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ # project -*.egg-info/ -build/ dist/ venv/ @@ -13,6 +11,7 @@ _build/ # tools tools/SPTK/ +tools/toml/ # misc __pycache__/ diff --git a/Makefile b/Makefile index 8e2f720..bad2870 100644 --- a/Makefile +++ b/Makefile @@ -22,23 +22,16 @@ init: pip install -e . dev: - @if type virtualenv > /dev/null 2>&1; then \ - test -d venv || virtualenv -p python$(PYTHON_VERSION) venv; \ - else \ - test -d venv || python$(PYTHON_VERSION) -m venv venv; \ - fi + test -d venv || python$(PYTHON_VERSION) -m venv venv; \ . ./venv/bin/activate; pip install pip --upgrade; \ pip install torch==1.10.0+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html; \ pip install -e .[dev] dist: - ./venv/bin/python setup.py bdist_wheel - ./venv/bin/twine check dist/* + . ./venv/bin/activate; python -m build --wheel; \ + twine check dist/* dist-clean: - @if [ -f ./venv/bin/python ]; then \ - ./venv/bin/python setup.py clean --all; \ - fi rm -rf dist doc: @@ -72,6 +65,10 @@ test: . ./venv/bin/activate; export PATH=tools/SPTK/bin:$$PATH; \ python -m pytest -s --cov=./ --cov-report=xml $$module +test-clean: + rm -rf tests/__pycache__ + rm -rf *.wav + tool: cd tools; make @@ -79,14 +76,22 @@ tool-clean: cd tools; make clean update: + @if [ ! -x tools/toml/toml ]; then \ + echo ""; \ + echo "Error: please install toml-cli"; \ + echo ""; \ + echo " make tool"; \ + echo ""; \ + exit 1; \ + fi ./venv/bin/python -m pip install --upgrade pip - @for package in $$(cat setup.py | grep " " | sed "s/\s//g" | \ - sed 's/"//g' | tr ",\n" " "); do \ + @for package in $$(./tools/toml/toml get pyproject.toml project.optional-dependencies.dev | \ + sed 's/"//g' | tr -d '[]' | tr , ' '); do \ ./venv/bin/pip install --upgrade $$package; \ done -clean: dist-clean doc-clean tool-clean +clean: dist-clean doc-clean test-clean tool-clean rm -rf *.egg-info venv find . -name "__pycache__" -type d | xargs rm -rf -.PHONY: init dev dist dist-clean doc doc-clean check format test tool tool-clean update clean +.PHONY: init dev dist dist-clean doc doc-clean check format test test-clean tool tool-clean update clean diff --git a/diffsptk/version.py b/diffsptk/version.py index 906d362..49e0fc1 100644 --- a/diffsptk/version.py +++ b/diffsptk/version.py @@ -1 +1 @@ -__version__ = "0.6.0" +__version__ = "0.7.0" diff --git a/pyproject.toml b/pyproject.toml index c71e237..27b2d9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,65 @@ +[build-system] + requires = ["hatchling"] + build-backend = "hatchling.build" + +[project] + name = "diffsptk" + authors = [ + {name = "SPTK Working Group"} + ] + maintainers = [ + {name = "Takenori Yoshimura", email="takenori@sp.nitech.ac.jp"} + ] + description = "Speech signal processing modules for machine learning" + readme = "README.md" + requires-python = ">=3.8" + keywords = [ + "dsp", + "ddsp", + "sptk", + "pytorch", + "signal processing", + ] + license = {text = "Apache 2.0"} + classifiers = [ + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + ] + dynamic = ["version"] + dependencies = [ + "soundfile", + "torch >= 1.10.0", + "torchcrepe >= 0.0.16", + "numpy", + "vector-quantize-pytorch >= 0.8.0", + ] + +[project.optional-dependencies] + dev = [ + "black", + "build", + "isort", + "numpydoc", + "pydata-sphinx-theme", + "pyproject-flake8", + "pytest", + "pytest-cov", + "sphinx", + "twine", + ] + +[project.urls] + Documentation = "https://sp-nitech.github.io/diffsptk/latest/" + +[tool.hatch.build] + exclude = ["assets", "docs", "tests", "tools"] + +[tool.hatch.version] + path = "diffsptk/version.py" + [tool.flake8] max-line-length = 88 extend-ignore = ["E203"] diff --git a/setup.py b/setup.py deleted file mode 100644 index d0785ff..0000000 --- a/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -from setuptools import find_packages, setup - -exec(open("diffsptk/version.py").read()) - -with open("README.md", "r") as f: - long_description = f.read() - -setup( - name="diffsptk", - version=__version__, - description="Speech signal processing modules for machine learning", - author="SPTK Working Group", - author_email="takenori@sp.nitech.ac.jp", - url="https://github.com/sp-nitech/diffsptk", - packages=find_packages(exclude=("assets", "docs", "tests", "tools")), - long_description=long_description, - long_description_content_type="text/markdown", - keywords="dsp speech signal processing sptk pytorch", - license="Apache 2.0", - classifiers=[ - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python :: 3.8", - ], - python_requires=">= 3.8", - install_requires=[ - "soundfile", - "torch >= 1.10.0", - "torchcrepe >= 0.0.16", - "numpy", - "vector-quantize-pytorch >= 0.8.0", - ], - extras_require={ - "dev": [ - "black", - "isort", - "numpydoc", - "pydata-sphinx-theme", - "pyproject-flake8", - "pytest", - "pytest-cov", - "sphinx", - "twine", - ], - }, -) diff --git a/tools/Makefile b/tools/Makefile index 62b0168..acb6df1 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -14,16 +14,22 @@ # limitations under the License. # # ------------------------------------------------------------------------ # -all: SPTK +all: SPTK toml SPTK: git clone https://github.com/sp-nitech/SPTK.git cd SPTK; make +toml: + mkdir -p toml + wget https://github.com/gnprice/toml-cli/releases/download/v0.2.3/toml-0.2.3-x86_64-linux.tar.gz -O toml.tar.gz + tar xzvf toml.tar.gz -C toml --strip-components 1 + rm -rf toml.tar.gz + update: cd SPTK; git pull; make clean: - rm -rf SPTK + rm -rf SPTK toml .PHONY: all update clean From 8b4d4a16f15f47a7158216187a5521291a632a42 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Tue, 18 Apr 2023 13:49:52 +0900 Subject: [PATCH 09/12] minor fix [skip ci] --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bad2870..64ced81 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,7 @@ update: done clean: dist-clean doc-clean test-clean tool-clean - rm -rf *.egg-info venv + rm -rf venv find . -name "__pycache__" -type d | xargs rm -rf .PHONY: init dev dist dist-clean doc doc-clean check format test test-clean tool tool-clean update clean From e739f338007a371b8c53429d84214e70cf27e0ee Mon Sep 17 00:00:00 2001 From: takenori-y Date: Tue, 18 Apr 2023 14:43:36 +0900 Subject: [PATCH 10/12] replace NotImplementedError --- diffsptk/misc/utils.py | 4 ++-- pyproject.toml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/diffsptk/misc/utils.py b/diffsptk/misc/utils.py index c818a78..cdcfcff 100644 --- a/diffsptk/misc/utils.py +++ b/diffsptk/misc/utils.py @@ -113,7 +113,7 @@ def get_hts_alpha(sr): } key = str(int(sr)) if key not in sr_to_alpha: - raise NotImplementedError + raise ValueError("unsupported sample rate: {sr}") selected_alpha = sr_to_alpha[key] return selected_alpha @@ -145,7 +145,7 @@ def get_auto_alpha(sr, n_freq, n_alpha): elif mode == "auto": alpha = get_auto_alpha(sr, n_freq, n_alpha) else: - raise NotImplementedError + raise ValueError("only hts and auto are supported") return alpha diff --git a/pyproject.toml b/pyproject.toml index 27b2d9a..08cdfd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,6 @@ [tool.coverage.report] exclude_lines = [ "pragma: no cover", - "raise NotImplementedError", "raise RuntimeError", "raise ValueError", "self.verbose", From a3c8c053dc29a15287463ee03c2b5d0b3eef73f7 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Tue, 18 Apr 2023 15:10:58 +0900 Subject: [PATCH 11/12] add docs --- diffsptk/misc/signals.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/diffsptk/misc/signals.py b/diffsptk/misc/signals.py index 4750f9f..0ddbe65 100644 --- a/diffsptk/misc/signals.py +++ b/diffsptk/misc/signals.py @@ -30,6 +30,9 @@ def impulse(order, **kwargs): order : int >= 0 [scalar] Order of sequence, :math:`M`. + kwargs : additional keyword arguments + See `torch.eye `_. + Returns ------- x : Tensor [shape=(M+1,)] @@ -60,6 +63,9 @@ def step(order, value=1, **kwargs): value : float [scalar] Step value. + kwargs : additional keyword arguments + See `torch.full `_. + Returns ------- x : Tensor [shape=(M+1,)] @@ -96,6 +102,9 @@ def ramp(arg, end=None, step=1, eps=1e-8, **kwargs): eps : float [scalar] A correction value. + kwargs : additional keyword arguments + See `torch.arange `_. + Returns ------- x : Tensor [shape=(?,)] @@ -138,6 +147,9 @@ def sin(order, period=None, magnitude=1, **kwargs): magnitude : float [scalar] Magnitude. + kwargs : additional keyword arguments + See `torch.arange `_. + Returns ------- x : Tensor [shape=(M+1,)] @@ -174,6 +186,9 @@ def train(order, frame_period, norm="power", **kwargs): norm : ['none', 'power', 'magnitude'] Normalization type. + **kwargs : additional keyword arguments + See `torch.zeros `_. + Returns ------- x : Tensor [shape=(M+1,)] @@ -228,6 +243,9 @@ def nrand(*order, mean=0, stdv=1, var=None, **kwargs): var : float >= 0 [scalar] Variance. + **kwargs : additional keyword arguments + See `torch.randn `_. + Returns ------- x : Tensor [shape=(M+1,)] From cd0165bf5c6f28a80dfda68b7bcd278bc5371a26 Mon Sep 17 00:00:00 2001 From: takenori-y Date: Tue, 18 Apr 2023 18:20:41 +0900 Subject: [PATCH 12/12] format --- diffsptk/misc/signals.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/diffsptk/misc/signals.py b/diffsptk/misc/signals.py index 0ddbe65..415f35f 100644 --- a/diffsptk/misc/signals.py +++ b/diffsptk/misc/signals.py @@ -103,7 +103,8 @@ def ramp(arg, end=None, step=1, eps=1e-8, **kwargs): A correction value. kwargs : additional keyword arguments - See `torch.arange `_. + See `torch.arange + `_. Returns ------- @@ -148,7 +149,8 @@ def sin(order, period=None, magnitude=1, **kwargs): Magnitude. kwargs : additional keyword arguments - See `torch.arange `_. + See `torch.arange + `_. Returns -------