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