code: def istft(
      stft_matrix: np.ndarray,
      *,
      hop_length: Optional[int] = None,
      win_length: Optional[int] = None,
      n_fft: Optional[int] = None,
      window: _WindowSpec = "hann",
      center: bool = True,
      dtype: Optional[DTypeLike] = None,
      length: Optional[int] = None,
      out: Optional[np.ndarray] = None,
  ) -> np.ndarray:
      """
      Inverse short-time Fourier transform (ISTFT).
  
      Converts a complex-valued spectrogram ``stft_matrix`` to time-series ``y``
      by minimizing the mean squared error between ``stft_matrix`` and STFT of
      ``y`` as described in [#]_ up to Section 2 (reconstruction from MSTFT).
  
      In general, window function, hop length and other parameters should be same
      as in stft, which mostly leads to perfect reconstruction of a signal from
      unmodified ``stft_matrix``.
  
      .. [#] D. W. Griffin and J. S. Lim,
          "Signal estimation from modified short-time Fourier transform,"
          IEEE Trans. ASSP, vol.32, no.2, pp.236–243, Apr. 1984.
  
      Parameters
      ----------
      stft_matrix : np.ndarray [shape=(..., 1 + n_fft//2, t)]
          STFT matrix from ``stft``
  
      hop_length : int > 0 [scalar]
          Number of frames between STFT columns.
          If unspecified, defaults to ``win_length // 4``.
  
      win_length : int <= n_fft = 2 * (stft_matrix.shape[0] - 1)
          When reconstructing the time series, each frame is windowed
          and each sample is normalized by the sum of squared window
          according to the ``window`` function (see below).
  
          If unspecified, defaults to ``n_fft``.
  
      n_fft : int > 0 or None
          The number of samples per frame in the input spectrogram.
          By default, this will be inferred from the shape of ``stft_matrix``.
          However, if an odd frame length was used, you can specify the correct
          length by setting ``n_fft``.
  
      window : string, tuple, number, function, np.ndarray [shape=(n_fft,)]
          - a window specification (string, tuple, or number);
            see `scipy.signal.get_window`
          - a window function, such as `scipy.signal.windows.hann`
          - a user-specified window vector of length ``n_fft``
  
          .. see also:: `filters.get_window`
  
      center : boolean
          - If ``True``, ``D`` is assumed to have centered frames.
          - If ``False``, ``D`` is assumed to have left-aligned frames.
  
      dtype : numeric type
          Real numeric type for ``y``.  Default is to match the numerical
          precision of the input spectrogram.
  
      length : int > 0, optional
          If provided, the output ``y`` is zero-padded or clipped to exactly
          ``length`` samples.
  
      out : np.ndarray or None
          A pre-allocated, complex-valued array to store the reconstructed signal
          ``y``.  This must be of the correct shape for the given input parameters.
  
          If not provided, a new array is allocated and returned.
  
      Returns
      -------
      y : np.ndarray [shape=(..., n)]
          time domain signal reconstructed from ``stft_matrix``.
          If ``stft_matrix`` contains more than two axes
          (e.g., from a stereo input signal), then ``y`` will match shape on the leading dimensions.
  
      See Also
      --------
      stft : Short-time Fourier Transform
  
      Notes
      -----
      This function caches at level 30.
  
      Examples
      --------
      >>> y, sr = librosa.load(librosa.ex('trumpet'))
      >>> D = librosa.stft(y)
      >>> y_hat = librosa.istft(D)
      >>> y_hat
      array([-1.407e-03, -4.461e-04, ...,  5.131e-06, -1.417e-05],
            dtype=float32)
  
      Exactly preserving length of the input signal requires explicit padding.
      Otherwise, a partial frame at the end of ``y`` will not be represented.
  
      >>> n = len(y)
      >>> n_fft = 2048
      >>> y_pad = librosa.util.fix_length(y, size=n + n_fft // 2)
      >>> D = librosa.stft(y_pad, n_fft=n_fft)
      >>> y_out = librosa.istft(D, length=n)
      >>> np.max(np.abs(y - y_out))
      8.940697e-08
      """
      if n_fft is None:
          n_fft = 2 * (stft_matrix.shape[-2] - 1)
  
      # By default, use the entire frame
      if win_length is None:
          win_length = n_fft
  
      # Set the default hop, if it's not already specified
      if hop_length is None:
          hop_length = int(win_length // 4)
  
      ifft_window = get_window(window, win_length, fftbins=True)
  
      # Pad out to match n_fft, and add broadcasting axes
      ifft_window = util.pad_center(ifft_window, size=n_fft)
      ifft_window = util.expand_to(
          ifft_window, ndim=stft_matrix.ndim, axes=-2
      )
  
      # For efficiency, trim STFT frames according to signal length if available
      if length:
          if center:
              padded_length = length + 2 * (n_fft // 2)
          else:
              padded_length = length
          n_frames = min(
              stft_matrix.shape[-1],
              int(np.ceil(padded_length / hop_length)),
          )
      else:
          n_frames = stft_matrix.shape[-1]
  
      if dtype is None:
          dtype = util.dtype_c2r(stft_matrix.dtype)
  
      shape = list(stft_matrix.shape[:-2])
      expected_signal_len = n_fft + hop_length * (n_frames - 1)
  
      if length:
          expected_signal_len = length
      elif center:
          expected_signal_len -= 2 * (n_fft // 2)
  
      shape.append(expected_signal_len)
  
      if out is None:
          y = np.zeros(shape, dtype=dtype)
      elif not np.allclose(out.shape, shape):
          raise ParameterError(
              f"Shape mismatch for provided output array out.shape={out.shape} != {shape}"
          )
      else:
          y = out
          # Since we'll be doing overlap-add here, this needs to be initialized to zero.
          y.fill(0.0)
  
      fft = get_fftlib()
  
      if center:
          # First frame that does not depend on padding
          #  k * hop_length - n_fft//2 >= 0
          # k * hop_length >= n_fft // 2
          # k >= (n_fft//2 / hop_length)
  
          start_frame = int(np.ceil((n_fft // 2) / hop_length))
  
          # Do overlap-add on the head block
          ytmp = ifft_window * fft.irfft(
              stft_matrix[..., :start_frame], n=n_fft, axis=-2
          )
  
          shape[-1] = n_fft + hop_length * (start_frame - 1)
          head_buffer = np.zeros(shape, dtype=dtype)
  
          __overlap_add(head_buffer, ytmp, hop_length)
  
          # If y is smaller than the head buffer, take everything
          if y.shape[-1] < shape[-1] - n_fft // 2:
              y[..., :] = head_buffer[
                  ..., n_fft // 2 : y.shape[-1] + n_fft // 2
              ]
          else:
              # Trim off the first n_fft//2 samples from the head and copy into target buffer
              y[..., : shape[-1] - n_fft // 2] = head_buffer[
                  ..., n_fft // 2 :
              ]
  
          # This offset compensates for any differences between frame alignment
          # and padding truncation
          offset = start_frame * hop_length - n_fft // 2
  
      else:
          start_frame = 0
          offset = 0
  
      n_columns = int(
          util.MAX_MEM_BLOCK
          // (np.prod(stft_matrix.shape[:-1]) * stft_matrix.itemsize)
      )
      n_columns = max(n_columns, 1)
  
      frame = 0
      for bl_s in range(start_frame, n_frames, n_columns):
          bl_t = min(bl_s + n_columns, n_frames)
  
          # invert the block and apply the window function
          ytmp = ifft_window * fft.irfft(
              stft_matrix[..., bl_s:bl_t], n=n_fft, axis=-2
          )
  
          # Overlap-add the istft block starting at the i'th frame
          __overlap_add(
              y[..., frame * hop_length + offset :], ytmp, hop_length
          )
  
          frame += bl_t - bl_s
  
      # Normalize by sum of squared window
      ifft_window_sum = window_sumsquare(
          window=window,
          n_frames=n_frames,
          win_length=win_length,
          n_fft=n_fft,
          hop_length=hop_length,
          dtype=dtype,
      )
  
      if center:
          start = n_fft // 2
      else:
          start = 0
  
      ifft_window_sum = util.fix_length(
          ifft_window_sum[..., start:], size=y.shape[-1]
      )
  
      approx_nonzero_indices = ifft_window_sum > util.tiny(
          ifft_window_sum
      )
  
      y[..., approx_nonzero_indices] /= ifft_window_sum[
          approx_nonzero_indices
      ]
  
      return y
  
imports: from __future__ import annotations
  import warnings
  import numpy
  import scipy
  import scipy.ndimage
  import scipy.signal
  import scipy.interpolate
  from numba import jit
  from .None import convert
  from .fft import get_fftlib
  from .audio import resample
  from .._cache import cache
  from ..None import util
  from ..util.exceptions import ParameterError
  from ..filters import get_window, semitone_filterbank
  from ..filters import window_sumsquare
  from numpy.typing import DTypeLike
  from typing import Any, Callable, Optional, Tuple, List, Union, overload
  from typing_extensions import Literal
  from .._typing import _WindowSpec, _PadMode, _PadModeSTFT, _SequenceLike, _ScalarOrSequence, _ComplexLike_co, _FloatLike_co
label_desc: Use image node_id 2 for calling a global function with example usage: istft(stft_matrix) and returns: y