text: # MIT License
  #
  # Copyright (c) 2021 Soohwan Kim and Sangchun Ha and Soyoung Cho
  #
  # Permission is hereby granted, free of charge, to any person obtaining a copy
  # of this software and associated documentation files (the "Software"), to deal
  # in the Software without restriction, including without limitation the rights
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  # copies of the Software, and to permit persons to whom the Software is
  # furnished to do so, subject to the following conditions:
  #
  # The above copyright notice and this permission notice shall be included in all
  # copies or substantial portions of the Software.
  #
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  # SOFTWARE.
  
  import torch.nn as nn
  from torch import Tensor
  from typing import Optional
  
  from openspeech.modules.conv_base import BaseConv1d
  
  
  class TimeChannelSeparableConv1d(BaseConv1d):
      r"""
      The total number of weights for a time-channel separable convolution block is K × cin + cin × cout weights. Since K is
      generally several times smaller than cout, most weights are
      concentrated in the pointwise convolution part.
      """
      def __init__(
              self,
              in_channels: int,
              out_channels: int,
              kernel_size: int = 1,
              padding: int = 0,
              groups: int = 1,
              bias: bool = True,
      ):
          super(TimeChannelSeparableConv1d, self).__init__()
          self.conv = nn.Conv1d(
              in_channels=in_channels,
              out_channels=out_channels,
              kernel_size=kernel_size,
              stride=1,
              dilation=1,
              padding=padding,
              groups=groups,
              bias=bias,
          )
  
      def forward(self, inputs: Tensor, input_lengths: Optional[Tensor] = None) -> Tensor:
          if input_lengths is None:
              return self.conv(inputs)
          else:
              return self.conv(inputs), self._get_sequence_lengths(input_lengths)
  