def forward(self, x):
        """Performs a forward pass through the SyncANetBlock.

        Args:
            x (torch.Tensor): Input tensor of shape [B, C, T, Q] where 
                              B is batch size, C is number of channels, 
                              T is temporal dimension, and Q is frequency dimension.

        Returns:
            torch.Tensor: Output tensor of the same shape [B, C, T, Q].
        """
        B, C, old_T, old_Q = x.shape
        
        # Calculate new dimensions for padding
        T = math.ceil((old_T - self.emb_ks) / self.emb_hs) * self.emb_hs + self.emb_ks
        Q = math.ceil((old_Q - self.emb_ks) / self.emb_hs) * self.emb_hs + self.emb_ks
        
        # Pad the input tensor to match the new dimensions
        x = F.pad(x, (0, Q - old_Q, 0, T - old_T))

        # Intra-process
        input_ = x
        intra_rnn = self.intra_norm(input_)  # Normalize input for intra-process
        intra_rnn = self.Fconv(intra_rnn)    # Apply depthwise convolution
        intra_rnn = (
            intra_rnn.transpose(1, 2).contiguous().view(B * T, C * self.emb_ks, -1)
        )  # Reshape for subsequent operations

        intra_rnn = intra_rnn.transpose(1, 2)  # Reshape for processing
        intra_rnn_u = self.intra_to_u(intra_rnn)  # Linear transformation
        intra_rnn_v = self.intra_to_v(intra_rnn)  # Linear transformation
        intra_rnn_u = self.intra_rnn(intra_rnn_u)  # Apply FSMN
        intra_rnn = intra_rnn_v * intra_rnn_u  # Element-wise multiplication
        intra_rnn = intra_rnn.transpose(1, 2)  # Reshape back
        intra_rnn = self.intra_linear(intra_rnn)  # Linear projection
        intra_rnn = intra_rnn.transpose(1, 2)  # Reshape for mossformer
        intra_rnn = intra_rnn.view([B, T, Q, C])  # Reshape for mossformer
        intra_rnn = self.intra_mossformer(intra_rnn)  # Apply MossFormer
        intra_rnn = intra_rnn.transpose(1, 2)  # Reshape back
        intra_rnn = intra_rnn.view([B, T, C, Q])  # Reshape back
        intra_rnn = intra_rnn.transpose(1, 2).contiguous()  # Final reshape
        intra_rnn = self.intra_se(intra_rnn)  # Squeeze-and-excitation layer
        intra_rnn = intra_rnn + input_  # Residual connection

        # Inter-process
        input_ = intra_rnn
        inter_rnn = self.inter_norm(input_)  # Normalize input for inter-process
        inter_rnn = (
            inter_rnn.permute(0, 3, 1, 2).contiguous().view(B * Q, C, T)
        )  # Reshape for processing
        inter_rnn = F.unfold(
            inter_rnn[..., None], (self.emb_ks, 1), stride=(self.emb_hs, 1)
        )  # Extract sliding windows
        inter_rnn = inter_rnn.transpose(1, 2)  # Reshape for further processing
        inter_rnn_u = self.inter_to_u(inter_rnn)  # Linear transformation
        inter_rnn_v = self.inter_to_v(inter_rnn)  # Linear transformation
        inter_rnn_u = self.inter_rnn(inter_rnn_u)  # Apply FSMN
        inter_rnn = inter_rnn_v * inter_rnn_u  # Element-wise multiplication
        inter_rnn = inter_rnn.transpose(1, 2)  # Reshape back
        inter_rnn = self.inter_linear(inter_rnn)  # Linear projection
        inter_rnn = inter_rnn.transpose(1, 2)  # Reshape for mossformer
        inter_rnn = inter_rnn.view([B, Q, T, C])  # Reshape for mossformer
        inter_rnn = self.inter_mossformer(inter_rnn)  # Apply MossFormer
        inter_rnn = inter_rnn.transpose(1, 2)  # Reshape back
        inter_rnn = inter_rnn.view([B, Q, C, T])  # Final reshape
        inter_rnn = inter_rnn.permute(0, 2, 3, 1).contiguous()  # Permute for SE layer
        inter_rnn = self.inter_se(inter_rnn)  # Squeeze-and-excitation layer
        inter_rnn = inter_rnn + input_  # Residual connection

        # Attention mechanism
        inter_rnn = inter_rnn[..., :old_T, :old_Q]  # Trim to original shape

        batch = inter_rnn
        all_Q, all_K, all_V = [], [], []
        
        # Compute query, key, and value for each attention head
        for ii in range(self.n_head):
            all_Q.append(self["attn_conv_Q_%d" % ii](batch))  # Query
            all_K.append(self["attn_conv_K_%d" % ii](batch))  # Key
            all_V.append(self["attn_conv_V_%d" % ii](batch))  # Value

        Q = torch.cat(all_Q, dim=0)  # Concatenate all queries
        K = torch.cat(all_K, dim=0)  # Concatenate all keys
        V = torch.cat(all_V, dim=0)  # Concatenate all values

        # Reshape for attention calculation
        Q = Q.transpose(1, 2)
        Q = Q.flatten(start_dim=2)  # Flatten for attention calculation
        K = K.transpose(1, 2)
        K = K.flatten(start_dim=2)  # Flatten for attention calculation
        V = V.transpose(1, 2)  # Reshape for attention calculation
        old_shape = V.shape
        V = V.flatten(start_dim=2)  # Flatten for attention calculation
        emb_dim = Q.shape[-1]

        # Compute scaled dot-product attention
        attn_mat = torch.matmul(Q, K.transpose(1, 2)) / (emb_dim**0.5)  # Attention matrix
        attn_mat = F.softmax(attn_mat, dim=2)  # Softmax over attention scores
        V = torch.matmul(attn_mat, V)  # Weighted sum of values

        V = V.reshape(old_shape)  # Reshape back
        V = V.transpose(1, 2)  # Final reshaping
        emb_dim = V.shape[1]

        batch = V.view([self.n_head, B, emb_dim, old_T, -1])  # Reshape for multi-head
        batch = batch.transpose(0, 1)  # Permute for batch processing
        batch = batch.contiguous().view(
            [B, self.n_head * emb_dim, old_T, -1]
        )  # Final reshape for concatenation
        batch = self["attn_concat_proj"](batch)  # Final linear projection

        # Combine inter-process result with attention output
        out = batch + inter_rnn
        return out  # Return the output tensor
Performs a forward pass through the SyncANetBlock.

        Args:
            x (torch.Tensor): Input tensor of shape [B, C, T, Q] where 
                              B is batch size, C is number of channels, 
                              T is temporal dimension, and Q is frequency dimension.

        Returns:
            torch.Tensor: Output tensor of the same shape [B, C, T, Q].
        
clearvoice/clearvoice/models/mossformer_gan_se/generator.py