class_docstr: Implementation of the imperceptible attack against a speech recognition model.
  
  | Paper link: http://proceedings.mlr.press/v97/qin19a.html
docstr: Compute loss gradient of the global masking threshold w.r.t. the PSD approximate of the perturbation.
  
  The loss is defined as the hinge loss w.r.t. to the frequency masking threshold of the original audio input `x`
  and the normalized power spectral density estimate of the perturbation. In order to stabilize the optimization
  problem during back-propagation, the `10*log`-terms are canceled out.
  
  :param perturbation: Adversarial perturbation.
  :param x: An array with the original inputs to be attacked.
  :param masking_threshold_stabilized: Stabilized masking threshold for the original input `x`.
  :param psd_maximum_stabilized: Stabilized maximum across frames, i.e. shape is `(batch_size, frame_length)`, of
      the original unnormalized PSD of `x`.
  :return: Tuple consisting of the loss gradient, which has same shape as `perturbation`, and loss value.
code: def _loss_gradient_masking_threshold(
      self,
      perturbation: np.ndarray,
      x: np.ndarray,
      masking_threshold_stabilized: np.ndarray,
      psd_maximum_stabilized: np.ndarray,
  ) -> Tuple[np.ndarray, np.ndarray]:
      """
      Compute loss gradient of the global masking threshold w.r.t. the PSD approximate of the perturbation.
  
      The loss is defined as the hinge loss w.r.t. to the frequency masking threshold of the original audio input `x`
      and the normalized power spectral density estimate of the perturbation. In order to stabilize the optimization
      problem during back-propagation, the `10*log`-terms are canceled out.
  
      :param perturbation: Adversarial perturbation.
      :param x: An array with the original inputs to be attacked.
      :param masking_threshold_stabilized: Stabilized masking threshold for the original input `x`.
      :param psd_maximum_stabilized: Stabilized maximum across frames, i.e. shape is `(batch_size, frame_length)`, of
          the original unnormalized PSD of `x`.
      :return: Tuple consisting of the loss gradient, which has same shape as `perturbation`, and loss value.
      """
      # pad input
      perturbation_padded, delta_mask = pad_sequence_input(perturbation)
  
      if self._framework == "tensorflow":
          # get loss gradients (TensorFlow)
          feed_dict = {
              self._delta: perturbation_padded,
              self._power_spectral_density_maximum_tf: psd_maximum_stabilized,
              self._masking_threshold_tf: masking_threshold_stabilized,
          }
          # pylint: disable=W0212
          gradients_padded, loss = self.estimator._sess.run(
              self._loss_gradient_masking_threshold_op_tf, feed_dict
          )
      elif self._framework == "pytorch":
          # get loss gradients (TensorFlow)
          (
              gradients_padded,
              loss,
          ) = self._loss_gradient_masking_threshold_torch(
              perturbation_padded,
              psd_maximum_stabilized,
              masking_threshold_stabilized,
          )
      else:
          raise NotImplementedError
  
      # undo padding, i.e. change gradients shape from (nb_samples, max_length) to (nb_samples)
      lengths = delta_mask.sum(axis=1)
      gradients = []
      for gradient_padded, length in zip(gradients_padded, lengths):
          gradient = gradient_padded[:length]
          gradients.append(gradient)
  
      # for ragged input, use object dtype
      dtype = np.float32 if x.ndim != 1 else object
      return np.array(gradients, dtype=dtype), loss
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import TYPE_CHECKING, Optional, Tuple, Union
  import numpy
  import scipy.signal
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator, LossGradientsMixin, NeuralNetworkMixin
  from art.estimators.pytorch import PyTorchEstimator
  from art.estimators.speech_recognition.speech_recognizer import SpeechRecognizerMixin
  from art.estimators.tensorflow import TensorFlowV2Estimator
  from art.utils import pad_sequence_input
label_desc: Use image node_id 7 for calling the ImperceptibleASR obj's underlying member method code with example usage: obj._loss_gradient_masking_threshold(perturbation, x, masking_threshold_stabilized, psd_maximum_stabilized) and returns: np,  loss