Exemple #1
0
def _dct2_1d(signals, name=None):
  """Computes the type II 1D Discrete Cosine Transform (DCT) of `signals`.

  Args:
    signals: A `[..., samples]` `float32` `Tensor` containing the signals to
      take the DCT of.
    name: An optional name for the operation.

  Returns:
    A `[..., samples]` `float32` `Tensor` containing the DCT of `signals`.

  """
  with ops.name_scope(name, 'dct', [signals]):
    # We use the FFT to compute the DCT and TensorFlow only supports float32 for
    # FFTs at the moment.
    signals = ops.convert_to_tensor(signals, dtype=dtypes.float32)

    axis_dim = signals.shape[-1].value or array_ops.shape(signals)[-1]
    axis_dim_float = math_ops.to_float(axis_dim)
    scale = 2.0 * math_ops.exp(math_ops.complex(
        0.0, -math.pi * math_ops.range(axis_dim_float) /
        (2.0 * axis_dim_float)))

    rfft = spectral_ops.rfft(signals, fft_length=[2 * axis_dim])[..., :axis_dim]
    dct2 = math_ops.real(rfft * scale)
    return dct2
def stft(signals, frame_length, frame_step, fft_length=None,
         window_fn=functools.partial(window_ops.hann_window, periodic=True),
         pad_end=False, name=None):
  """Computes the [Short-time Fourier Transform][stft] of `signals`.

  Implemented with GPU-compatible ops and supports gradients.

  Args:
    signals: A `[..., samples]` `float32` `Tensor` of real-valued signals.
    frame_length: An integer scalar `Tensor`. The window length in samples.
    frame_step: An integer scalar `Tensor`. The number of samples to step.
    fft_length: An integer scalar `Tensor`. The size of the FFT to apply.
      If not provided, uses the smallest power of 2 enclosing `frame_length`.
    window_fn: A callable that takes a window length and a `dtype` keyword
      argument and returns a `[window_length]` `Tensor` of samples in the
      provided datatype. If set to `None`, no windowing is used.
    pad_end: Whether to pad the end of `signals` with zeros when the provided
      frame length and step produces a frame that lies partially past its end.
    name: An optional name for the operation.

  Returns:
    A `[..., frames, fft_unique_bins]` `Tensor` of `complex64` STFT values where
    `fft_unique_bins` is `fft_length // 2 + 1` (the unique components of the
    FFT).

  Raises:
    ValueError: If `signals` is not at least rank 1, `frame_length` is
      not scalar, or `frame_step` is not scalar.

  [stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform
  """
  with ops.name_scope(name, 'stft', [signals, frame_length,
                                     frame_step]):
    signals = ops.convert_to_tensor(signals, name='signals')
    signals.shape.with_rank_at_least(1)
    frame_length = ops.convert_to_tensor(frame_length, name='frame_length')
    frame_length.shape.assert_has_rank(0)
    frame_step = ops.convert_to_tensor(frame_step, name='frame_step')
    frame_step.shape.assert_has_rank(0)

    if fft_length is None:
      fft_length = _enclosing_power_of_two(frame_length)
    else:
      fft_length = ops.convert_to_tensor(fft_length, name='fft_length')

    framed_signals = shape_ops.frame(
        signals, frame_length, frame_step, pad_end=pad_end)

    # Optionally window the framed signals.
    if window_fn is not None:
      window = window_fn(frame_length, dtype=framed_signals.dtype)
      framed_signals *= window

    # spectral_ops.rfft produces the (fft_length/2 + 1) unique components of the
    # FFT of the real windowed signals in framed_signals.
    return spectral_ops.rfft(framed_signals, [fft_length])
Exemple #3
0
 def testRFFT(self):
   self._VerifyFftMethod(
       INNER_DIMS_1D, np.real, lambda x: np.fft.rfft(x, n=x.shape[-1]),
       lambda x: spectral_ops.rfft(x, fft_length=[x.shape[-1].value]))
Exemple #4
0
 def testRFFT(self):
     self._VerifyFftMethod(
         INNER_DIMS_1D, np.real, lambda x: np.fft.rfft(x, n=x.shape[-1]),
         lambda x: spectral_ops.rfft(x, fft_length=[x.shape[-1].value]))
Exemple #5
0
def stft(signals,
         frame_length,
         frame_step,
         fft_length=None,
         window_fn=functools.partial(window_ops.hann_window, periodic=True),
         pad_end=False,
         name=None):
    """Computes the [Short-time Fourier Transform][stft] of `signals`.

  Implemented with GPU-compatible ops and supports gradients.

  Args:
    signals: A `[..., samples]` `float32` `Tensor` of real-valued signals.
    frame_length: An integer scalar `Tensor`. The window length in samples.
    frame_step: An integer scalar `Tensor`. The number of samples to step.
    fft_length: An integer scalar `Tensor`. The size of the FFT to apply.
      If not provided, uses the smallest power of 2 enclosing `frame_length`.
    window_fn: A callable that takes a window length and a `dtype` keyword
      argument and returns a `[window_length]` `Tensor` of samples in the
      provided datatype. If set to `None`, no windowing is used.
    pad_end: Whether to pad the end of `signals` with zeros when the provided
      frame length and step produces a frame that lies partially past its end.
    name: An optional name for the operation.

  Returns:
    A `[..., frames, fft_unique_bins]` `Tensor` of `complex64` STFT values where
    `fft_unique_bins` is `fft_length // 2 + 1` (the unique components of the
    FFT).

  Raises:
    ValueError: If `signals` is not at least rank 1, `frame_length` is
      not scalar, or `frame_step` is not scalar.

  [stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform
  """
    with ops.name_scope(name, 'stft', [signals, frame_length, frame_step]):
        signals = ops.convert_to_tensor(signals, name='signals')
        signals.shape.with_rank_at_least(1)
        frame_length = ops.convert_to_tensor(frame_length, name='frame_length')
        frame_length.shape.assert_has_rank(0)
        frame_step = ops.convert_to_tensor(frame_step, name='frame_step')
        frame_step.shape.assert_has_rank(0)

        if fft_length is None:
            fft_length = _enclosing_power_of_two(frame_length)
        else:
            fft_length = ops.convert_to_tensor(fft_length, name='fft_length')

        framed_signals = shape_ops.frame(signals,
                                         frame_length,
                                         frame_step,
                                         pad_end=pad_end)

        # Optionally window the framed signals.
        if window_fn is not None:
            window = window_fn(frame_length, dtype=framed_signals.dtype)
            framed_signals *= window

        # spectral_ops.rfft produces the (fft_length/2 + 1) unique components of the
        # FFT of the real windowed signals in framed_signals.
        return spectral_ops.rfft(framed_signals, [fft_length])