Source code for diffsptk.core.ifreqt2
# ------------------------------------------------------------------------ #
# Copyright 2022 SPTK Working Group #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ------------------------------------------------------------------------ #
import numpy as np
import torch
import torch.nn as nn
from ..misc.utils import numpy_to_torch
from .freqt2 import warp
[docs]class SecondOrderAllPassInverseFrequencyTransform(nn.Module):
"""Second-order all-pass inverse frequecy transform module.
Parameters
----------
in_order : int >= 0 [scalar]
Order of input sequence, :math:`M_1`.
out_order : int >= 0 [scalar]
Order of output sequence, :math:`M_2`.
alpha : float [-1 < alpha < 1]
Frequency warping factor, :math:`\\alpha`.
theta : float [0 <= theta <= 1]
Emphasis frequency, :math:`\\theta`.
n_fft : int >> math:`M_1` [scalar]
Number of FFT bins. Accurate conversion requires the large value.
"""
def __init__(self, in_order, out_order, alpha=0, theta=0, n_fft=512):
super(SecondOrderAllPassInverseFrequencyTransform, self).__init__()
assert 0 <= in_order
assert 0 <= out_order
assert in_order < n_fft
assert abs(alpha) < 1
assert 0 <= theta <= 1
theta *= np.pi
delta = 2 * np.pi / n_fft
omega = np.arange(n_fft) * delta
ww = warp(omega, alpha, theta)
m1 = np.arange(-in_order, in_order + 1)
wwm1 = ww.reshape(-1, 1) * m1.reshape(1, -1)
real = np.cos(wwm1)
imag = -np.sin(wwm1)
M2 = out_order + 1
A = np.fft.ifft(real + 1j * imag, axis=0).real
A[:M2, in_order + 1 :] += np.flip(A[:M2, :in_order], axis=1)
A = A[:M2, in_order:]
A[0, 1:] /= 2
A[1:, 0] *= 2
self.register_buffer("A", numpy_to_torch(A.T))
[docs] def forward(self, c1):
"""Perform second-order all-pass inverse frequency transform.
Parameters
----------
c1 : Tensor [shape=(..., M1+1)]
Warped sequence.
Returns
-------
c2 : Tensor [shape=(..., M2+1)]
Output sequence.
Examples
--------
>>> c1 = diffsptk.nrand(3)
>>> c1
tensor([ 0.0304, 0.5849, -0.8668, -0.7278])
>>> freqt2 = diffsptk.SecondOrderAllPassFrequencyTransform(3, 4, .1, .3)
>>> c2 = freqt2(c1)
>>> c2
tensor([ 0.0682, 0.4790, -1.0168, -0.6026, 0.1094])
>>> ifreqt2 = diffsptk.SecondOrderAllPassInverseFrequencyTransform(4, 3, .1, .3)
>>> c3 = ifreqt2(c2)
>>> c3
tensor([ 0.0682, 0.4790, -1.0168, -0.6026, 0.1094])
"""
c2 = torch.matmul(c1, self.A)
return c2