ISTFT

The Inverse Short-Time Fourier Transform (ISTFT) reconstructs a time-domain signal from its STFT representation.

Faithful reconstruction requires that the STFT parameters (window, overlap, etc.) match those used in the forward transform and that the Constant OverLap Add (COLA) constraint is satisfied.

Excel Usage

=ISTFT(zxx_grid, fs, window, nperseg, noverlap, input_onesided, boundary)
  • zxx_grid (list[list], required): The STFT grid as returned by the stft function (Excel range).
  • fs (float, optional, default: 1): Sampling frequency.
  • window (str, optional, default: “hann”): Desired window to use.
  • nperseg (int, optional, default: null): Number of data points per segment.
  • noverlap (int, optional, default: null): Number of points to overlap between segments.
  • input_onesided (bool, optional, default: true): If True, interpret input as one-sided.
  • boundary (bool, optional, default: true): If True, input signal was extended at boundaries.

Returns (list[list]): A 2D array where the first row is segment times and the second row is the reconstructed time-domain signal.

Example 1: STFT/ISTFT roundtrip

Inputs:

zxx_grid fs
0 0.5 1
0 (Re) 1 1
0 (Im) 0 0

Excel formula:

=ISTFT({"",0,0.5;"0 (Re)",1,1;"0 (Im)",0,0}, 1)

Expected output:

Result
0
0.5
Example 2: ISTFT with two frequency bins

Inputs:

zxx_grid fs
0 0.5 2
0 (Re) 1 1
0 (Im) 0 0
0.5 (Re) 0 0
0.5 (Im) 0 0

Excel formula:

=ISTFT({"",0,0.5;"0 (Re)",1,1;"0 (Im)",0,0;"0.5 (Re)",0,0;"0.5 (Im)",0,0}, 2)

Expected output:

Result
0
0.5
Example 3: ISTFT with explicit segment and overlap

Inputs:

zxx_grid fs nperseg noverlap
0 1 2 4 2
0 (Re) 1 0
0 (Im) 0 0
0.5 (Re) 0.5 0.5
0.5 (Im) 0 0

Excel formula:

=ISTFT({"",0,1;"0 (Re)",1,0;"0 (Im)",0,0;"0.5 (Re)",0.5,0.5;"0.5 (Im)",0,0}, 2, 4, 2)

Expected output:

Result
0 0.5
0 0.5
Example 4: ISTFT without boundary extension

Inputs:

zxx_grid fs boundary
0 0.5 1 false
0 (Re) 0.5 0.5
0 (Im) 0 0

Excel formula:

=ISTFT({"",0,0.5;"0 (Re)",0.5,0.5;"0 (Im)",0,0}, 1, FALSE)

Expected output:

Result
0 1 2
0 0.25 0.25

Python Code

Show Code
import numpy as np
from scipy.signal import istft as scipy_istft

def istft(zxx_grid, fs=1, window='hann', nperseg=None, noverlap=None, input_onesided=True, boundary=True):
    """
    Perform the Inverse Short-Time Fourier Transform (ISTFT).

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.istft.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        zxx_grid (list[list]): The STFT grid as returned by the stft function (Excel range).
        fs (float, optional): Sampling frequency. Default is 1.
        window (str, optional): Desired window to use. Default is 'hann'.
        nperseg (int, optional): Number of data points per segment. Default is None.
        noverlap (int, optional): Number of points to overlap between segments. Default is None.
        input_onesided (bool, optional): If True, interpret input as one-sided. Default is True.
        boundary (bool, optional): If True, input signal was extended at boundaries. Default is True.

    Returns:
        list[list]: A 2D array where the first row is segment times and the second row is the reconstructed time-domain signal.
    """
    try:
      if not isinstance(zxx_grid, list) or not all(isinstance(row, list) for row in zxx_grid):
        return "Error: zxx_grid must be a 2D list"
      if len(zxx_grid) < 3:
        return "Error: zxx_grid must include header and at least one complex row pair"
      if (len(zxx_grid) - 1) % 2 != 0:
        return "Error: zxx_grid must contain pairs of real and imaginary rows"

      row_length = len(zxx_grid[0])
      if row_length < 2:
        return "Error: zxx_grid must include at least one time column"
      if any(len(row) != row_length for row in zxx_grid):
        return "Error: zxx_grid rows must all have the same length"

      zxx_rows = []
      for i in range(1, len(zxx_grid), 2):
          re_row = [float(x) for x in zxx_grid[i][1:]]
          im_row = [float(x) for x in zxx_grid[i+1][1:]]
          complex_row = [complex(r, im) for r, im in zip(re_row, im_row)]
          zxx_rows.append(complex_row)

      zxx_arr = np.array(zxx_rows)

      # Infer a reasonable nperseg from the given STFT matrix if not explicitly provided.
      # For a one-sided (default) STFT, the number of frequency bins is nperseg//2 + 1.
      # For a two-sided STFT, the number of frequency bins equals nperseg.
      if nperseg is None:
        bins = zxx_arr.shape[0]
        if bool(input_onesided):
          nperseg_val = max(2, 2 * (bins - 1))
        else:
          nperseg_val = max(1, bins)
      else:
        nperseg_val = int(nperseg)

      noverlap_val = None
      if noverlap is not None:
        noverlap_val = int(noverlap)
        if noverlap_val >= nperseg_val:
          return "Error: noverlap must be less than nperseg"

      # Ensure the STFT matrix has the expected number of frequency bins for the chosen nperseg.
      expected_bins = (nperseg_val // 2 + 1) if bool(input_onesided) else nperseg_val
      if zxx_arr.shape[0] < expected_bins:
        pad_rows = expected_bins - zxx_arr.shape[0]
        zxx_arr = np.vstack([zxx_arr, np.zeros((pad_rows, zxx_arr.shape[1]), dtype=complex)])
      elif zxx_arr.shape[0] > expected_bins:
        return "Error: zxx_grid has more frequency bins than expected for the given nperseg"

      t, x = scipy_istft(
          zxx_arr,
          fs=float(fs),
          window=window,
          nperseg=nperseg_val,
          noverlap=noverlap_val,
          input_onesided=bool(input_onesided),
          boundary=bool(boundary),
      )

      t_list = list(t)
      x_list = list(x)
      max_len = max(len(t_list), len(x_list))
      t_list += [""] * (max_len - len(t_list))
      x_list += [""] * (max_len - len(x_list))

      return [t_list, x_list]
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

The STFT grid as returned by the stft function (Excel range).
Sampling frequency.
Desired window to use.
Number of data points per segment.
Number of points to overlap between segments.
If True, interpret input as one-sided.
If True, input signal was extended at boundaries.