class_docstr: Neural HMM Encoder
  
  Same as Tacotron 2 encoder but increases the input length by states per phone
  
  Args:
      num_chars (int): Number of characters in the input.
      state_per_phone (int): Number of states per phone.
      in_out_channels (int): number of input and output channels.
      n_convolutions (int): number of convolutional layers.
class_docstr_tok: ["Neural","HMM","Encoder","Same","as","Tacotron","2","encoder","but","increases","the","input","length","by","states","per","phone","Args",":","num_chars","(","int",")",":","Number","of","characters","in","the","input",".","state_per_phone","(","int",")",":","Number","of","states","per","phone",".","in_out_channels","(","int",")",":","number","of","input","and","output","channels",".","n_convolutions","(","int",")",":","number","of","convolutional","layers","."]
code: def __init__(
      self,
      num_chars,
      state_per_phone,
      in_out_channels=512,
      n_convolutions=3,
  ):
      super().__init__()
  
      self.state_per_phone = state_per_phone
      self.in_out_channels = in_out_channels
  
      self.emb = nn.Embedding(num_chars, in_out_channels)
      self.convolutions = nn.ModuleList()
      for _ in range(n_convolutions):
          self.convolutions.append(
              ConvBNBlock(in_out_channels, in_out_channels, 5, "relu")
          )
      self.lstm = nn.LSTM(
          in_out_channels,
          int(in_out_channels / 2) * state_per_phone,
          num_layers=1,
          batch_first=True,
          bias=True,
          bidirectional=True,
      )
      self.rnn_state = None
  
imports: from typing import List, Tuple
  import torch
  import torch.nn.functional
  from torch import nn
  from tqdm.auto import tqdm
  from TTS.tts.layers.tacotron.common_layers import Linear
  from TTS.tts.layers.tacotron.tacotron2 import ConvBNBlock
label_desc: Use image node_id 1 to create a new Encoder object from inherited base classes: nn with example: obj = Encoder(num_chars, state_per_phone, in_out_channels, n_convolutions)