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_ste
(signals, frame_length, frame_step, fft_length=None,
window_fn=window_ops.hann_window,
pad_end=False, name=None)
| 35 | |
| 36 | @tf_export('signal.stft') |
| 37 | def stft(signals, frame_length, frame_step, fft_length=None, |
| 38 | window_fn=window_ops.hann_window, |
| 39 | pad_end=False, name=None): |
| 40 | """Computes the [Short-time Fourier Transform][stft] of `signals`. |
| 41 | |
| 42 | Implemented with GPU-compatible ops and supports gradients. |
| 43 | |
| 44 | Args: |
| 45 | signals: A `[..., samples]` `float32` `Tensor` of real-valued signals. |
| 46 | frame_length: An integer scalar `Tensor`. The window length in samples. |
| 47 | frame_step: An integer scalar `Tensor`. The number of samples to step. |
| 48 | fft_length: An integer scalar `Tensor`. The size of the FFT to apply. |
| 49 | If not provided, uses the smallest power of 2 enclosing `frame_length`. |
| 50 | window_fn: A callable that takes a window length and a `dtype` keyword |
| 51 | argument and returns a `[window_length]` `Tensor` of samples in the |
| 52 | provided datatype. If set to `None`, no windowing is used. |
| 53 | pad_end: Whether to pad the end of `signals` with zeros when the provided |
| 54 | frame length and step produces a frame that lies partially past its end. |
| 55 | name: An optional name for the operation. |
| 56 | |
| 57 | Returns: |
| 58 | A `[..., frames, fft_unique_bins]` `Tensor` of `complex64` STFT values where |
| 59 | `fft_unique_bins` is `fft_length // 2 + 1` (the unique components of the |
| 60 | FFT). |
| 61 | |
| 62 | Raises: |
| 63 | ValueError: If `signals` is not at least rank 1, `frame_length` is |
| 64 | not scalar, or `frame_step` is not scalar. |
| 65 | |
| 66 | [stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform |
| 67 | """ |
| 68 | with ops.name_scope(name, 'stft', [signals, frame_length, |
| 69 | frame_step]): |
| 70 | signals = ops.convert_to_tensor(signals, name='signals') |
| 71 | signals.shape.with_rank_at_least(1) |
| 72 | frame_length = ops.convert_to_tensor(frame_length, name='frame_length') |
| 73 | frame_length.shape.assert_has_rank(0) |
| 74 | frame_step = ops.convert_to_tensor(frame_step, name='frame_step') |
| 75 | frame_step.shape.assert_has_rank(0) |
| 76 | |
| 77 | if fft_length is None: |
| 78 | fft_length = _enclosing_power_of_two(frame_length) |
| 79 | else: |
| 80 | fft_length = ops.convert_to_tensor(fft_length, name='fft_length') |
| 81 | |
| 82 | framed_signals = shape_ops.frame( |
| 83 | signals, frame_length, frame_step, pad_end=pad_end) |
| 84 | |
| 85 | # Optionally window the framed signals. |
| 86 | if window_fn is not None: |
| 87 | window = window_fn(frame_length, dtype=framed_signals.dtype) |
| 88 | framed_signals *= window |
| 89 | |
| 90 | # fft_ops.rfft produces the (fft_length/2 + 1) unique components of the |
| 91 | # FFT of the real windowed signals in framed_signals. |
| 92 | return fft_ops.rfft(framed_signals, [fft_length]) |
| 93 | |
| 94 |
nothing calls this directly
no test coverage detected