def train(generator, discriminator, optimizer_generator, optimizer_discriminator, training_data_loader):
    for data_sample in training_data_loader:
        # Ground-truth waveform
        waveform_gt = data_sample["wav"]
        # Generator forwarding
        loss_generator, waveform = generator(data_sample)

        # Discriminator
        real, fake, _, _ = discriminator(waveform.detach(), waveform_gt)
        loss_discriminator = discriminator_loss(real, fake)
        optimizer_discriminator.zero_grad()
        loss_discriminator.backward()
        clip_gradient(discriminator.parameters(), 1.0)
        optimizer_discriminator.step()

        # Generator
        real, fake, real_feature_map, fake_feature_map = discriminator(waveform, waveform_gt)
        loss_feature_map = feature_loss(real_feature_map, fake_feature_map)
        loss_adversarial = adversarial_loss(fake)
        loss_generator_all = loss_adversarial + loss_feature_map + loss_generator
        optimizer_generator.zero_grad()
        loss_generator_all.step()
        clip_gradient(generator.parameters(), 1.0)
        optimizer_generator.step()
