docstr: Forward pass that uses both text and voice in either text conditioning mode or voice conditioning mode
  (actuated by `text_first`).
  
  text_inputs: long tensor, (b,t)
  text_lengths: long tensor, (b,)
  mel_inputs:  long tensor, (b,m)
  wav_lengths: long tensor, (b,)
  cond_mels: MEL float tensor, (b, 1, 80,s)
  cond_idxs: cond start and end indexs, (b, 2)
  
  If return_attentions is specified, only logits are returned.
  If return_latent is specified, loss & logits are not computed or returned. Only the predicted latents are returned.
docstr_tok: ["Forward","pass","that","uses","both","text","and","voice","in","either","text","conditioning","mode","or","voice","conditioning","mode","(","actuated","by","`","text_first","`",")",".","text_inputs",":","long","tensor",",","(","b",",","t",")","text_lengths",":","long","tensor",",","(","b",",",")","mel_inputs",":","long","tensor",",","(","b",",","m",")","wav_lengths",":","long","tensor",",","(","b",",",")","cond_mels",":","MEL","float","tensor",",","(","b",",","1",",","80",",","s",")","cond_idxs",":","cond","start","and","end","indexs",",","(","b",",","2",")","If","return_attentions","is","specified",",","only","logits","are","returned",".","If","return_latent","is","specified",",","loss","&","logits","are","not","computed","or","returned",".","Only","the","predicted","latents","are","returned","."]
code: def forward(
      self,
      text_inputs,
      text_lengths,
      audio_codes,
      wav_lengths,
      cond_mels=None,
      cond_idxs=None,
      cond_lens=None,
      cond_latents=None,
      return_attentions=False,
      return_latent=False,
  ):
      """
      Forward pass that uses both text and voice in either text conditioning mode or voice conditioning mode
      (actuated by `text_first`).
  
      text_inputs: long tensor, (b,t)
      text_lengths: long tensor, (b,)
      mel_inputs:  long tensor, (b,m)
      wav_lengths: long tensor, (b,)
      cond_mels: MEL float tensor, (b, 1, 80,s)
      cond_idxs: cond start and end indexs, (b, 2)
  
      If return_attentions is specified, only logits are returned.
      If return_latent is specified, loss & logits are not computed or returned. Only the predicted latents are returned.
      """
      # ❗ FIXIT
      if self.max_conditioning_inputs == 0:
          assert (
              cond_mels is None
          ), " ❗ cond_mels is not None, but max_conditioning_inputs == 0"
  
      max_text_len = text_lengths.max()
      code_lengths = (
          torch.ceil(wav_lengths / self.code_stride_len).long() + 3
      )
  
      if cond_lens is not None:
          if self.use_perceiver_resampler:
              cond_lens = (
                  cond_lens // self.perceiver_cond_length_compression
              )
          else:
              cond_lens = cond_lens // self.code_stride_len
  
      if cond_idxs is not None:
          # recompute cond idxs for mel lengths
          for idx in range(cond_idxs.size(0)):
              if self.use_perceiver_resampler:
                  cond_idxs[idx] = (
                      cond_idxs[idx]
                      // self.perceiver_cond_length_compression
                  )
              else:
                  cond_idxs[idx] = (
                      cond_idxs[idx] // self.code_stride_len
                  )
  
      # ensure that the cond_mel does not have padding
      # if cond_lens is not None and cond_idxs is None:
      #     min_cond_len = torch.min(cond_lens)
      #     cond_mels = cond_mels[:, :, :, :min_cond_len]
  
      # If len(codes) + 3 is larger than maxiumum allowed length, we truncate the codes.
      max_mel_len = code_lengths.max()
  
      if max_mel_len > audio_codes.shape[-1]:
          audio_codes = F.pad(
              audio_codes, (0, max_mel_len - audio_codes.shape[-1])
          )
  
      # 💖 Lovely assertions
      assert (
          max_mel_len <= audio_codes.shape[-1]
      ), f" ❗ max_mel_len ({max_mel_len}) > audio_codes.shape[-1] ({audio_codes.shape[-1]})"
      assert (
          max_text_len <= text_inputs.shape[-1]
      ), f" ❗ max_text_len ({max_text_len}) > text_inputs.shape[-1] ({text_inputs.shape[-1]})"
  
      # Append stop token to text inputs
      text_inputs = F.pad(
          text_inputs[:, :max_text_len],
          (0, 1),
          value=self.stop_text_token,
      )
  
      # Append silence token to mel codes
      audio_codes = F.pad(
          audio_codes[:, :max_mel_len],
          (0, 1),
          value=self.stop_audio_token,
      )
  
      # Pad mel codes with stop_audio_token
      audio_codes = self.set_mel_padding(
          audio_codes, code_lengths - 3
      )  # -3 to get the real code lengths without consider start and stop tokens that was not added yet
  
      # Build input and target tensors
      # Prepend start token to inputs and append stop token to targets
      text_inputs, text_targets = self.set_inputs_and_targets(
          text_inputs, self.start_text_token, self.stop_text_token
      )
      audio_codes, mel_targets = self.set_inputs_and_targets(
          audio_codes, self.start_audio_token, self.stop_audio_token
      )
  
      # Set attn_mask
      attn_mask_cond = None
      attn_mask_text = None
      attn_mask_mel = None
      if not return_latent:
          attn_mask_cond = torch.ones(
              cond_mels.shape[0],
              cond_mels.shape[-1],
              dtype=torch.bool,
              device=text_inputs.device,
          )
          attn_mask_text = torch.ones(
              text_inputs.shape[0],
              text_inputs.shape[1],
              dtype=torch.bool,
              device=text_inputs.device,
          )
          attn_mask_mel = torch.ones(
              audio_codes.shape[0],
              audio_codes.shape[1],
              dtype=torch.bool,
              device=audio_codes.device,
          )
  
          if cond_idxs is not None:
              # use masking approach
              for idx, r in enumerate(cond_idxs):
                  l = r[1] - r[0]
                  attn_mask_cond[idx, l:] = 0.0
          elif cond_lens is not None:
              for idx, l in enumerate(cond_lens):
                  attn_mask_cond[idx, l:] = 0.0
  
          for idx, l in enumerate(text_lengths):
              attn_mask_text[idx, l + 1 :] = 0.0
  
          for idx, l in enumerate(code_lengths):
              attn_mask_mel[idx, l + 1 :] = 0.0
  
      # Compute text embeddings + positional embeddings
      text_emb = self.text_embedding(
          text_inputs
      ) + self.text_pos_embedding(text_inputs)
  
      # Compute mel embeddings + positional embeddings
      mel_emb = self.mel_embedding(
          audio_codes
      ) + self.mel_pos_embedding(audio_codes)
  
      # Compute speech conditioning input
      if cond_latents is None:
          cond_latents = self.get_style_emb(cond_mels).transpose(1, 2)
  
      # Get logits
      sub = -5  # don't ask me why 😄
      if self.training:
          sub = -1
  
      text_logits, mel_logits = self.get_logits(
          text_emb,
          self.text_head,
          mel_emb,
          self.mel_head,
          prompt=cond_latents,
          get_attns=return_attentions,
          return_latent=return_latent,
          attn_mask_cond=attn_mask_cond,
          attn_mask_text=attn_mask_text,
          attn_mask_mel=attn_mask_mel,
      )
      if return_latent:
          return mel_logits[:, :sub]  # sub to prevent bla.
  
      if return_attentions:
          return mel_logits
  
      # Set paddings to -1 to ignore them in loss
      for idx, l in enumerate(text_lengths):
          text_targets[idx, l + 1 :] = -1
  
      for idx, l in enumerate(code_lengths):
          mel_targets[idx, l + 1 :] = -1
  
      # check if stoptoken is in every row of mel_targets
      assert (
          mel_targets == self.stop_audio_token
      ).sum() >= mel_targets.shape[
          0
      ], f" ❗ mel_targets does not contain stop token ({self.stop_audio_token}) in every row."
  
      # ignore the loss for the segment used for conditioning
      # coin flip for the segment to be ignored
      if cond_idxs is not None:
          cond_start = cond_idxs[idx, 0]
          cond_end = cond_idxs[idx, 1]
          mel_targets[idx, cond_start:cond_end] = -1
  
      # Compute losses
      loss_text = F.cross_entropy(
          text_logits,
          text_targets.long(),
          ignore_index=-1,
          label_smoothing=self.label_smoothing,
      )
      loss_mel = F.cross_entropy(
          mel_logits,
          mel_targets.long(),
          ignore_index=-1,
          label_smoothing=self.label_smoothing,
      )
      return loss_text.mean(), loss_mel.mean(), mel_logits
  
imports: import functools
  import math
  import random
  import torch
  import torch.nn
  import torch.nn.functional
  from transformers import GPT2Config
  from TTS.tts.layers.xtts.gpt_inference import GPT2InferenceModel
  from TTS.tts.layers.xtts.latent_encoder import ConditioningEncoder
  from TTS.tts.layers.xtts.perceiver_encoder import PerceiverResampler
label_desc: Use image node_id 10 for calling the GPT obj's underlying member method code with example usage: obj.forward(text_inputs, text_lengths, audio_codes, wav_lengths, cond_mels, cond_idxs, cond_lens, cond_latents, return_attentions, return_latent) and returns: loss_text,  loss_mel,  mel_logits, mel_logits, mel_logits