class_docstr: Stochastic duration predictor with Spline Flows.
  
  It applies Variational Dequantization and Variational Data Augmentation.
  
  Paper:
      SDP: https://arxiv.org/pdf/2106.06103.pdf
      Spline Flow: https://arxiv.org/abs/1906.04032
  
  ::
      ## Inference
  
      x -> TextCondEncoder() -> Flow() -> dr_hat
      noise ----------------------^
  
      ## Training
                                                                            |---------------------|
      x -> TextCondEncoder() -> + -> PosteriorEncoder() -> split() -> z_u, z_v -> (d - z_u) -> concat() -> Flow() -> noise
      d -> DurCondEncoder()  -> ^                                                    |
      |------------------------------------------------------------------------------|
  
  Args:
      in_channels (int): Number of input tensor channels.
      hidden_channels (int): Number of hidden channels.
      kernel_size (int): Kernel size of convolutional layers.
      dropout_p (float): Dropout rate.
      num_flows (int, optional): Number of flow blocks. Defaults to 4.
      cond_channels (int, optional): Number of channels of conditioning tensor. Defaults to 0.
code: def __init__(
      self,
      in_channels: int,
      hidden_channels: int,
      kernel_size: int,
      dropout_p: float,
      num_flows=4,
      cond_channels=0,
      language_emb_dim=0,
  ):
      super().__init__()
  
      # add language embedding dim in the input
      if language_emb_dim:
          in_channels += language_emb_dim
  
      # condition encoder text
      self.pre = nn.Conv1d(in_channels, hidden_channels, 1)
      self.convs = DilatedDepthSeparableConv(
          hidden_channels,
          kernel_size,
          num_layers=3,
          dropout_p=dropout_p,
      )
      self.proj = nn.Conv1d(hidden_channels, hidden_channels, 1)
  
      # posterior encoder
      self.flows = nn.ModuleList()
      self.flows.append(ElementwiseAffine(2))
      self.flows += [
          ConvFlow(2, hidden_channels, kernel_size, num_layers=3)
          for _ in range(num_flows)
      ]
  
      # condition encoder duration
      self.post_pre = nn.Conv1d(1, hidden_channels, 1)
      self.post_convs = DilatedDepthSeparableConv(
          hidden_channels,
          kernel_size,
          num_layers=3,
          dropout_p=dropout_p,
      )
      self.post_proj = nn.Conv1d(hidden_channels, hidden_channels, 1)
  
      # flow layers
      self.post_flows = nn.ModuleList()
      self.post_flows.append(ElementwiseAffine(2))
      self.post_flows += [
          ConvFlow(2, hidden_channels, kernel_size, num_layers=3)
          for _ in range(num_flows)
      ]
  
      if cond_channels != 0 and cond_channels is not None:
          self.cond = nn.Conv1d(cond_channels, hidden_channels, 1)
  
      if language_emb_dim != 0 and language_emb_dim is not None:
          self.cond_lang = nn.Conv1d(
              language_emb_dim, hidden_channels, 1
          )
  
imports: import math
  import torch
  from torch import nn
  from torch.nn import functional
  from TTS.tts.layers.generic.normalization import LayerNorm2
  from TTS.tts.layers.vits.transforms import piecewise_rational_quadratic_transform
label_desc: Use image node_id 1 to create a new StochasticDurationPredictor object from inherited base classes: nn with example: obj = StochasticDurationPredictor(in_channels, hidden_channels, kernel_size, dropout_p, num_flows, cond_channels, language_emb_dim)