def compute_loss_and_decoded_output(
        self, masked_adv_input: "torch.Tensor", original_output: np.ndarray, **kwargs
    ) -> tuple["torch.Tensor", np.ndarray]:
        """
        Compute loss function and decoded output.

        :param masked_adv_input: The perturbed inputs.
        :param original_output: Target values of shape (nb_samples). Each sample in `original_output` is a string, and
                                it may possess different lengths. A possible example of `original_output` could be:
                                `original_output = np.array(['SIXTY ONE', 'HELLO'])`.
        :param real_lengths: Real lengths of original sequences.
        :return: The loss and the decoded output.
        """
        # This estimator needs to have real lengths for loss computation
        real_lengths = kwargs.get("real_lengths")
        if real_lengths is None:  # pragma: no cover
            raise ValueError(
                "The PyTorchDeepSpeech estimator needs information about the real lengths of input sequences to "
                "compute loss and decoded output."
            )

        # Transform data into the model input space
        inputs, targets, input_rates, target_sizes, batch_idx = self._preprocess_transform_model_input(
            x=masked_adv_input.to(self.device),
            y=original_output,
            real_lengths=real_lengths,
        )

        # Compute real input sizes
        input_sizes = input_rates.mul_(inputs.size()[-1]).int()

        # Call to DeepSpeech model for prediction
        outputs, output_sizes, _ = self.model(inputs.to(self.device), input_sizes.to(self.device))
        outputs_ = outputs.transpose(0, 1)

        if self._version == 2:
            outputs_ = outputs_.float()
        else:
            outputs_ = outputs_.log_softmax(-1)

        # Compute the loss
        loss = self.criterion(outputs_, targets, output_sizes, target_sizes).to(self._device)

        # Average the loss by mini batch if version 2 of DeepSpeech is used
        if self._version == 2:
            loss = loss / inputs.size(0)

        # Compute transcription
        decoded_output, _ = self.decoder.decode(outputs, output_sizes)
        decoded_output = [do[0] for do in decoded_output]
        decoded_output = np.array(decoded_output)

        # Rearrange to the original order
        decoded_output_ = decoded_output.copy()
        decoded_output[batch_idx] = decoded_output_

        return loss, decoded_output

        Compute loss function and decoded output.

        :param masked_adv_input: The perturbed inputs.
        :param original_output: Target values of shape (nb_samples). Each sample in `original_output` is a string, and
                                it may possess different lengths. A possible example of `original_output` could be:
                                `original_output = np.array(['SIXTY ONE', 'HELLO'])`.
        :param real_lengths: Real lengths of original sequences.
        :return: The loss and the decoded output.
        
art/estimators/speech_recognition/pytorch_deep_speech.py