code: def power_to_db(
      S: _ScalarOrSequence[_ComplexLike_co],
      *,
      ref: Union[float, Callable] = 1.0,
      amin: float = 1e-10,
      top_db: Optional[float] = 80.0,
  ) -> Union[np.floating[Any], np.ndarray]:
      """Convert a power spectrogram (amplitude squared) to decibel (dB) units
  
      This computes the scaling ``10 * log10(S / ref)`` in a numerically
      stable way.
  
      Parameters
      ----------
      S : np.ndarray
          input power
  
      ref : scalar or callable
          If scalar, the amplitude ``abs(S)`` is scaled relative to ``ref``::
  
              10 * log10(S / ref)
  
          Zeros in the output correspond to positions where ``S == ref``.
  
          If callable, the reference value is computed as ``ref(S)``.
  
      amin : float > 0 [scalar]
          minimum threshold for ``abs(S)`` and ``ref``
  
      top_db : float >= 0 [scalar]
          threshold the output at ``top_db`` below the peak:
          ``max(10 * log10(S/ref)) - top_db``
  
      Returns
      -------
      S_db : np.ndarray
          ``S_db ~= 10 * log10(S) - 10 * log10(ref)``
  
      See Also
      --------
      perceptual_weighting
      db_to_power
      amplitude_to_db
      db_to_amplitude
  
      Notes
      -----
      This function caches at level 30.
  
      Examples
      --------
      Get a power spectrogram from a waveform ``y``
  
      >>> y, sr = librosa.load(librosa.ex('trumpet'))
      >>> S = np.abs(librosa.stft(y))
      >>> librosa.power_to_db(S**2)
      array([[-41.809, -41.809, ..., -41.809, -41.809],
             [-41.809, -41.809, ..., -41.809, -41.809],
             ...,
             [-41.809, -41.809, ..., -41.809, -41.809],
             [-41.809, -41.809, ..., -41.809, -41.809]], dtype=float32)
  
      Compute dB relative to peak power
  
      >>> librosa.power_to_db(S**2, ref=np.max)
      array([[-80., -80., ..., -80., -80.],
             [-80., -80., ..., -80., -80.],
             ...,
             [-80., -80., ..., -80., -80.],
             [-80., -80., ..., -80., -80.]], dtype=float32)
  
      Or compare to median power
  
      >>> librosa.power_to_db(S**2, ref=np.median)
      array([[16.578, 16.578, ..., 16.578, 16.578],
             [16.578, 16.578, ..., 16.578, 16.578],
             ...,
             [16.578, 16.578, ..., 16.578, 16.578],
             [16.578, 16.578, ..., 16.578, 16.578]], dtype=float32)
  
      And plot the results
  
      >>> import matplotlib.pyplot as plt
      >>> fig, ax = plt.subplots(nrows=2, sharex=True, sharey=True)
      >>> imgpow = librosa.display.specshow(S**2, sr=sr, y_axis='log', x_axis='time',
      ...                                   ax=ax[0])
      >>> ax[0].set(title='Power spectrogram')
      >>> ax[0].label_outer()
      >>> imgdb = librosa.display.specshow(librosa.power_to_db(S**2, ref=np.max),
      ...                                  sr=sr, y_axis='log', x_axis='time', ax=ax[1])
      >>> ax[1].set(title='Log-Power spectrogram')
      >>> fig.colorbar(imgpow, ax=ax[0])
      >>> fig.colorbar(imgdb, ax=ax[1], format="%+2.0f dB")
      """
      S = np.asarray(S)
  
      if amin <= 0:
          raise ParameterError("amin must be strictly positive")
  
      if np.issubdtype(S.dtype, np.complexfloating):
          warnings.warn(
              "power_to_db was called on complex input so phase "
              "information will be discarded. To suppress this warning, "
              "call power_to_db(np.abs(D)**2) instead.",
              stacklevel=2,
          )
          magnitude = np.abs(S)
      else:
          magnitude = S
  
      if callable(ref):
          # User supplied a function to calculate reference power
          ref_value = ref(magnitude)
      else:
          ref_value = np.abs(ref)
  
      log_spec: np.ndarray = 10.0 * np.log10(
          np.maximum(amin, magnitude)
      )
      log_spec -= 10.0 * np.log10(np.maximum(amin, ref_value))
  
      if top_db is not None:
          if top_db < 0:
              raise ParameterError("top_db must be non-negative")
          log_spec = np.maximum(log_spec, log_spec.max() - top_db)
  
      return log_spec
  
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 13 for calling a global function with example usage: power_to_db(S) and returns: log_spec