Source code for diffsptk.core.c2mpir

# ------------------------------------------------------------------------ #
# 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 torch
import torch.nn as nn


[docs]class CepstrumToImpulseResponse(nn.Module): """See `this page <https://sp-nitech.github.io/sptk/latest/main/c2mpir.html>`_ for details. Parameters ---------- cep_order : int >= 1 [scalar] Order of cepstrum, :math:`M`. impulse_response_length : int >= 1 [scalar] Length of impulse response, :math:`N`. """ def __init__(self, cep_order, impulse_response_length): super(CepstrumToImpulseResponse, self).__init__() self.cep_order = cep_order self.impulse_response_length = impulse_response_length assert 1 <= self.cep_order assert 1 <= self.impulse_response_length self.register_buffer("ramp", torch.arange(1, self.cep_order + 1))
[docs] def forward(self, c): """Convert cepstrum to impulse response. Parameters ---------- c : Tensor [shape=(..., M+1)] Cepstral coefficients. Returns ------- h : Tensor [shape=(..., N)] Truncated impulse response. Examples -------- >>> c = diffsptk.ramp(3) >>> c2mpir = diffsptk.CepstrumToImpulseResponse(3, 5) >>> h = c2mpir(c) >>> h tensor([1.0000, 1.0000, 2.5000, 5.1667, 6.0417]) """ c0 = c[..., 0] c1 = c[..., 1:] * self.ramp c1 = c1.flip(-1) h = torch.empty( (*(c.shape[:-1]), self.impulse_response_length), device=c.device ) h[..., 0] = torch.exp(c0) for n in range(1, self.impulse_response_length): s = n - self.cep_order h[..., n] = ( torch.einsum( "...d,...d->...", h[..., max(0, s) : n].clone(), c1[..., max(0, -s) :], ) / n ) return h