class_docstr: Convolutions with Batch Normalization and non-linear activation.
  
  Args:
      in_channels (int): number of input channels.
      out_channels (int): number of output channels.
      kernel_size (int): convolution kernel size.
      activation (str): 'relu', 'tanh', None (linear).
  
  Shapes:
      - input: (B, C_in, T)
      - output: (B, C_out, T)
code: def __init__(
      self, in_channels, out_channels, kernel_size, activation=None
  ):
      super().__init__()
      assert (kernel_size - 1) % 2 == 0
      padding = (kernel_size - 1) // 2
      self.convolution1d = nn.Conv1d(
          in_channels, out_channels, kernel_size, padding=padding
      )
      self.batch_normalization = nn.BatchNorm1d(
          out_channels, momentum=0.1, eps=1e-5
      )
      self.dropout = nn.Dropout(p=0.5)
      if activation == "relu":
          self.activation = nn.ReLU()
      elif activation == "tanh":
          self.activation = nn.Tanh()
      else:
          self.activation = nn.Identity()
  
imports: import torch
  from torch import nn
  from torch.nn import functional
  from .attentions import init_attn
  from .common_layers import Linear, Prenet
label_desc: Use image node_id 1 to create a new ConvBNBlock object from inherited base classes: nn with example: obj = ConvBNBlock(in_channels, out_channels, kernel_size, activation)