Source code for pysptk.synthesis

"""
High-level interface for waveform synthesis
===========================================

Module ``pysptk.synthesis`` provides high-leve interface that wraps low-level
SPTK waveform synthesis functions (e.g. ``mlsadf``),

Synthesis filter interface
--------------------------

.. autoclass:: SynthesisFilter
    :members:

Synthesizer
-----------
.. autoclass::  Synthesizer
    :members:

SynthesisFilters
----------------

LMADF
^^^^^
.. autoclass::  LMADF
    :members:

MLSADF
^^^^^^
.. autoclass::  MLSADF
    :members:

GLSADF
^^^^^^
.. autoclass::  GLSADF
    :members:

MGLSADF
^^^^^^^
.. autoclass::  MGLSADF
    :members:

AllZeroDF
^^^^^^^^^
.. autoclass::  AllZeroDF
    :members:

AllPoleDF
^^^^^^^^^
.. autoclass::  AllPoleDF
    :members:

AllPoleLatticeDF
^^^^^^^^^^^^^^^^
.. autoclass::  AllPoleLatticeDF
    :members:

"""

from abc import abstractmethod

import numpy as np
import pysptk
import six
from pysptk.util import assert_pade, assert_stage


[docs]class SynthesisFilter(object): """Synthesis filter interface All synthesis filters must implement this interface. """
[docs] @abstractmethod def filt(self, x, coef): """Filter one sample Parameters ---------- x : float A input sample coef : array Filter coefficients Returns ------- y : float A filtered sample """
[docs] def filtt(self, x, coef): """Transpose filter Can be optional. Parameters ---------- x : float A input sample coef : array Filter coefficients Returns ------- y : float A filtered sample """ raise NotImplementedError()
[docs]class Synthesizer(object): """Speech waveform synthesizer Attributes ---------- filt : SynthesisFilter A speech synthesis filter hopsize : int Hop size transpose : bool Transpose filter or not. Default is False. """ def __init__(self, filt, hopsize, transpose=False): """Initialization Raises ------ TypeError if ``filt`` is not a instance of ``SynthesisFilter`` """ if not isinstance(filt, SynthesisFilter): raise TypeError("filt must be an instance of SynthesisFilter") self.filt = filt self.hopsize = hopsize self.transpose = transpose
[docs] def synthesis_one_frame(self, source, prev_b, curr_b): """Synthesize one frame waveform Parameters ---------- source : array Source excitation prev_b : array Filter coefficients of previous frame curr_b : array Filter coefficients of current frame Returns ------- y : array Synthesized waveform """ assert len(prev_b) == len(curr_b) slope = (curr_b - prev_b) / len(source) interpolated_coef = prev_b.copy() y = np.empty_like(source) # filter function filt = self.filt.filtt if self.transpose else self.filt.filt for i in six.moves.range(len(source)): scaled_source = source[i] * np.exp(interpolated_coef[0]) y[i] = filt(scaled_source, interpolated_coef) interpolated_coef += slope return y
[docs] def synthesis(self, source, b): """Synthesize a waveform given a source excitation and sequence of filter coefficients (e.g. cepstrum). Parameters ---------- source : array Source excitation b : array Filter coefficients Returns ------- y : array, shape (same as ``source``) Synthesized waveform """ y = np.zeros_like(source) b_prev = b[0, :] b_curr = b_prev for i in six.moves.range(b.shape[0]): if i > 0: b_prev = b[i - 1, :] b_curr = b[i, :] s, e = i * self.hopsize, (i + 1) * self.hopsize if e > len(source): break y[s:e] = self.synthesis_one_frame(source[s:e], b_prev, b_curr) return y
[docs]class LMADF(SynthesisFilter): """LMA digital filter that wraps ``lmadf`` Attributes ---------- pd : int Order of pade approximation. Default is 4. delay : array Delay """ def __init__(self, order=25, pd=4): """Initialization Raises ====== ValueError if invalid order of pade approximation is specified """ self.order = order assert_pade(pd) self.pd = pd self.delay = pysptk.lmadf_delay(order, pd)
[docs] def filt(self, x, coef): """Filter one sample using ``lmadf`` Parameters ---------- x : float A input sample coef: array LMA filter coefficients (i.e. Cepstrum) Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.lmadf """ return pysptk.lmadf(x, coef, self.pd, self.delay)
[docs]class MLSADF(SynthesisFilter): """MLSA digital filter that wraps ``mlsadf`` Attributes ---------- alpha : float All-pass constant pd : int Order of pade approximation. Default is 4. delay : array Delay """ def __init__(self, order=25, alpha=0.35, pd=4): """Initialization Raises ====== ValueError if invalid order of pade approximation is specified """ self.order = order assert_pade(pd) self.alpha = alpha self.pd = pd self.delay = pysptk.mlsadf_delay(order, pd)
[docs] def filt(self, x, coef): """Filter one sample using ``mlsadf`` Parameters ---------- x : float A input sample coef: array MLSA filter coefficients Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.mlsadf pysptk.sptk.mc2b """ return pysptk.mlsadf(x, coef, self.alpha, self.pd, self.delay)
[docs] def filtt(self, x, coef): """Transpose filter using ``mlsadft`` Parameters ---------- x : float A input sample coef: array MLSA filter coefficients Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.mlsadft """ return pysptk.mlsadft(x, coef, self.alpha, self.pd, self.delay)
[docs]class GLSADF(SynthesisFilter): """GLSA digital filter that wraps ``glsadf`` Attributes ---------- stage : int -1/gamma delay : array Delay """ def __init__(self, order=25, stage=1): """Initialization Raises ------ ValueError if invalid number of stage is specified """ self.order = order assert_stage(stage) self.stage = stage self.delay = pysptk.glsadf_delay(order, stage)
[docs] def filt(self, x, coef): """Filter one sample using ``glsadf`` Parameters ---------- x : float A input sample coef: array GLSA filter coefficients Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.glsadf """ return pysptk.glsadf(x, coef, self.stage, self.delay)
[docs] def filtt(self, x, coef): """Filter one sample using ``glsadft`` Parameters ---------- x : float A input sample coef: array GLSA filter coefficients Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.glsadft """ return pysptk.glsadft(x, coef, self.stage, self.delay)
[docs]class MGLSADF(SynthesisFilter): """MGLSA digital filter that wraps ``mglsadf`` Attributes ---------- alpha : float All-pass constant stage : int -1/gamma delay : array Delay """ def __init__(self, order=25, alpha=0.35, stage=1): """Initialization Raises ------ ValueError if invalid number of stage is specified """ self.order = order assert_stage(stage) self.alpha = alpha self.stage = stage self.delay = pysptk.mglsadf_delay(order, stage)
[docs] def filt(self, x, coef): """Filter one sample using ``mglsadf`` Parameters ---------- x : float A input sample coef: array MGLSA filter coefficients Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.mglsadf """ return pysptk.mglsadf(x, coef, self.alpha, self.stage, self.delay)
[docs] def filtt(self, x, coef): """Filter one sample using ``mglsadft`` Parameters ---------- x : float A input sample coef: array MGLSA filter coefficients Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.mglsadft """ return pysptk.mglsadft(x, coef, self.alpha, self.stage, self.delay)
[docs]class AllZeroDF(SynthesisFilter): """All-zero digital filter that wraps ``zerodf`` Attributes ---------- delay : array Delay """ def __init__(self, order=25): """Initialization""" self.order = order self.delay = pysptk.zerodf_delay(order)
[docs] def filt(self, x, coef): """Filter one sample using using ``zerodf`` Parameters ---------- x : float A input sample coef: array FIR parameters _ Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.zerodf """ return pysptk.zerodf(x, coef, self.delay)
[docs] def filtt(self, x, coef): """Filter one sample using using ``zerodft`` Parameters ---------- x : float A input sample coef: array FIR parameters Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.zerodft """ return pysptk.zerodf(x, coef, self.delay)
[docs]class AllPoleDF(SynthesisFilter): """All-pole digital filter that wraps ``poledf`` Attributes ---------- delay : array Delay """ def __init__(self, order=25): """Initialization""" self.order = order self.delay = pysptk.poledf_delay(order)
[docs] def filt(self, x, coef): """Filter one sample using using ``poledf`` Parameters ---------- x : float A input sample coef: array LPC (with loggain) Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.poledf """ return pysptk.poledf(x, coef, self.delay)
[docs] def filtt(self, x, coef): """Filter one sample using using ``poledft`` Parameters ---------- x : float A input sample coef: array LPC (with loggain) Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.poledft """ return pysptk.poledf(x, coef, self.delay)
[docs]class AllPoleLatticeDF(SynthesisFilter): """All-pole lttice digital filter that wraps ``ltcdf`` Attributes ---------- delay : array Delay """ def __init__(self, order=25): """Initialization""" self.order = order self.delay = pysptk.ltcdf_delay(order)
[docs] def filt(self, x, coef): """Filter one sample using using ``ltcdf`` Parameters ---------- x : float A input sample coef: array PARCOR coefficients (with loggain) Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.ltcdf """ return pysptk.ltcdf(x, coef, self.delay)
class LSPDF(SynthesisFilter): """All-pole digital filter that wraps ``lspdf`` Attributes ---------- delay : array Delay """ def __init__(self, order=25): """Initialization""" self.order = order self.delay = pysptk.lspdf_delay(order) def filt(self, x, coef): """Filter one sample using using ``lspdf`` Parameters ---------- x : float A input sample coef: array LSP (with loggain) Returns ------- y : float A filtered sample See Also -------- pysptk.sptk.lspdf """ return pysptk.lspdf(x, coef, self.delay)