code: def stft(
      signals: torch.Tensor,
      frame_length: int,
      frame_step: int,
      /,
      *,
      fft_length: Optional[int] = None,
      window_fn: Optional[Callable] = None,
      pad_end: Optional[bool] = False,
      name: Optional[str] = None,
      out: Optional[torch.Tensor] = None,
  ) -> torch.Tensor:
      if not isinstance(frame_length, int):
          raise ivy.utils.exceptions.IvyError(
              f"Expecting <class 'int'> instead of {type(frame_length)}"
          )
  
      if frame_length < 1:
          raise ivy.utils.exceptions.IvyError(
              f"Invalid data points {frame_length}, expecting frame_length larger than or"
              " equal to 1"
          )
  
      if not isinstance(frame_step, int):
          raise ivy.utils.exceptions.IvyError(
              f"Expecting <class 'int'> instead of {type(frame_step)}"
          )
  
      if frame_step < 1:
          raise ivy.utils.exceptions.IvyError(
              f"Invalid data points {frame_length}, expecting frame_length larger than or"
              " equal to 1"
          )
  
      if fft_length is not None:
          if not isinstance(fft_length, int):
              raise ivy.utils.exceptions.IvyError(
                  f"Expecting <class 'int'> instead of {type(fft_length)}"
              )
  
          if fft_length < 1:
              raise ivy.utils.exceptions.IvyError(
                  f"Invalid data points {frame_length}, expecting frame_length larger"
                  " than or equal to 1"
              )
  
      input_dtype = signals.dtype
      if input_dtype == torch.float32:
          dtype = torch.complex64
      elif input_dtype == torch.float64:
          dtype = torch.complex128
  
      def stft_1D(
          signals, frame_length, frame_step, fft_length, pad_end
      ):
          if fft_length is None:
              fft_length = 1
              while fft_length < frame_length:
                  fft_length *= 2
  
          num_samples = signals.shape[-1]
  
          if pad_end:
              num_samples = signals.shape[-1]
              num_frames = -(-num_samples // frame_step)
              pad_length = max(
                  0,
                  frame_length
                  + frame_step * (num_frames - 1)
                  - num_samples,
              )
  
              signals = torch.nn.functional.pad(
                  signals, (0, pad_length)
              )
          else:
              num_frames = (
                  1 + (num_samples - frame_length) // frame_step
              )
  
          stft_result = []
  
          if window_fn is None:
              window = 1
          else:
              window = window_fn(frame_length)
  
          for i in range(num_frames):
              start = i * frame_step
              end = start + frame_length
              frame = signals[..., start:end]
              windowed_frame = frame * window
              pad_length = fft_length - frame_length
              windowed_frame = torch.nn.functional.pad(
                  windowed_frame, (0, pad_length)
              )
              windowed_frame = torch.tensor(windowed_frame, dtype=dtype)
  
              fft_frame = torch.fft.fft(windowed_frame, axis=-1)
              slit = int(fft_length // 2 + 1)
              stft_result.append(fft_frame[..., 0:slit])
  
          stft = torch.stack(stft_result, axis=0)
          return stft
  
      def stft_helper(
          nested_list, frame_length, frame_step, fft_length
      ):
          nested_list = nested_list
          if len(nested_list.shape) > 1:
              return [
                  stft_helper(
                      sublist, frame_length, frame_step, fft_length
                  )
                  for sublist in nested_list
              ]
          else:
              return stft_1D(
                  nested_list,
                  frame_length,
                  frame_step,
                  fft_length,
                  pad_end,
              )
  
      to_return = stft_helper(
          signals, frame_length, frame_step, fft_length
      )
      flat_list = [
          item if isinstance(item, torch.Tensor) else torch.tensor(item)
          for sublist in to_return
          for item in sublist
      ]
      result = torch.stack(flat_list)
      original_shape = (len(to_return), len(to_return[0]))
      result = result.view(original_shape + result.shape[1:])
      return result
  
imports: from typing import Optional, Union, Tuple, List, Literal, Sequence, Callable
  import torch
  import math
  import ivy
  from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes
  from .None import backend_version
  from ivy.functional.ivy.layers import _handle_padding, _get_num_padded_values, _validate_max_pool_params, _depth_max_pooling_helper
  from ivy.functional.ivy.experimental.layers import _padding_ceil_mode, _broadcast_pooling_helper
label_desc: Use image node_id 28 for calling a global function with example usage: stft() and returns: result, stft, unknown, stft_1D