//  [python]
def __init__(self, n_in_channels, n_mel_channels, n_layers, n_channels, # audio_channels, mel_channels*n_group, n_layers, n_conv_channels
                 kernel_size, speaker_embed_dim, rezero): # bool: ReZero
        super(WN, self).__init__()
        assert(kernel_size % 2 == 1)
        assert(n_channels % 2 == 0)
        self.n_layers = n_layers
        self.n_channels = n_channels
        self.speaker_embed_dim = speaker_embed_dim
        
        self.in_layers = nn.ModuleList()
        self.res_skip_layers = nn.ModuleList()
        if rezero:
            self.alpha_i = nn.ParameterList()
        
        n_speakers = 512 # TODO: add to config
        if self.speaker_embed_dim:
            self.speaker_embed = nn.Embedding(n_speakers, self.speaker_embed_dim)
            self.speaker_embed.weight.data.mul_(0.05) # use smaller values for init weights
        
        start = nn.Conv1d(n_in_channels, n_channels, 1)
        start = nn.utils.weight_norm(start, name='weight')
        self.start = start
        
        # Initializing last layer to 0 makes the affine coupling layers
        # do nothing at first.  This helps with training stability
        end = nn.Conv1d(n_channels, 2*n_in_channels, 1)
        end.weight.data.zero_()
        end.bias.data.zero_()
        self.end = end
        
        if 0: # normal speaker stufs
            self.cond_layers = nn.ModuleList()
            cond_layer = nn.Conv1d(n_mel_channels+speaker_embed_dim, 2*n_channels*n_layers, 1)# (in_channels, out_channels, kernel_size)
            cond_layer = nn.utils.weight_norm(cond_layer, name='weight')
            self.cond_layers.append(cond_layer)
        else: # many layers deep speaker stuffs
            self.cond_layers = nn.ModuleList()
            hidden_dim = 256
            cond_layer = nn.Conv1d(n_mel_channels+speaker_embed_dim, hidden_dim, 1)# (in_channels, out_channels, kernel_size)
            cond_layer = nn.utils.weight_norm(cond_layer, name='weight')
            self.cond_layers.append(cond_layer)
            
            for i in range(1):
                cond_layer = nn.Conv1d(hidden_dim, hidden_dim, 1)# (in_channels, out_channels, kernel_size)
                cond_layer = nn.utils.weight_norm(cond_layer, name='weight')
                self.cond_layers.append(cond_layer)
            
            cond_layer = nn.Conv1d(hidden_dim, 2*n_channels*n_layers, 1)# (in_channels, out_channels, kernel_size)
            cond_layer = nn.utils.weight_norm(cond_layer, name='weight')
            self.cond_layers.append(cond_layer)
        
        for i in range(n_layers):
            dilation = 2 ** i
            padding = int((kernel_size*dilation - dilation)/2)
            in_layer = nn.Conv1d(n_channels, 2*n_channels, kernel_size,
                                       dilation=dilation, padding=padding)
            in_layer = nn.utils.weight_norm(in_layer, name='weight')
            self.in_layers.append(in_layer)
            
            # last one is not necessary
            if i < n_layers - 1:
                res_skip_channels = 2*n_channels
            else:
                res_skip_channels = n_channels
            res_skip_layer = nn.Conv1d(n_channels, res_skip_channels, 1)
            res_skip_layer = nn.utils.weight_norm(res_skip_layer, name='weight')
            
            if rezero:
                alpha_ = nn.Parameter(torch.rand(1)*0.02+0.09) # rezero initial state (0.1±0.01)
                self.alpha_i.append(alpha_)
            self.res_skip_layers.append(res_skip_layer)