def generate(args): # Создаём папку с выходными файлами generate_dir = os.path.join(hp.generate_dir, 'output') os.makedirs(generate_dir, exist_ok=True) # Создать модель model = AgainModel().to(device) model.eval() # Загрузить чекпоинт ckpt = torch.load(hp.again_checkpoint) model.load_state_dict(ckpt['model']) # Создаём вокодер и Загружаем веса vocoder = GeneratorMel(hp.n_mels).to(device) ckpt = torch.load(hp.mel_checkpoint, map_location=device) vocoder.load_state_dict(ckpt['G']) # Загрузить звук source = process_audio(args.source, 'mel', wav_name=None, it_audio=False)[0] target = process_audio(args.target, 'mel', wav_name=None, it_audio=False)[0] # Обрезать до одной длины if hp.seglen is not None: target = target[:, :hp.seglen] source = source[:, :hp.seglen] # Получить новый путь source_path = os.path.join( generate_dir, f'{os.path.basename(args.source).replace(".wav","")}') target_path = os.path.basename(args.target).replace('.wav', '') # Получить новый файл with torch.no_grad(): mel_output = model( source.unsqueeze(0).to(device), target.unsqueeze(0).to(device)) audio_output = vocoder(10**mel_output).squeeze().cpu().numpy() #amp = np.maximum(1e-10, np.dot(hp._inv_mel_filtr,10**(mel_output.squeeze().cpu().numpy()) )) #audio_output = my_griffin_lim(amp,5) sf.write(source_path + f'_to_{target_path}' + '.wav', audio_output, hp.sr) # Нарисовать Мелспектрограммы librosa.display.specshow(source.numpy(), cmap='viridis') plt.savefig(source_path + '.png') librosa.display.specshow(mel_output.squeeze().cpu().numpy(), cmap='viridis') plt.savefig(source_path + f'_to_{target_path}' + '.png')
def read_audio_into_chunks( file_path: Text, length: Optional[float] = 20000 / 1001, split_on_silence: Optional[bool] = False, noise_threshold: Optional[float] = -36, sample_width: Optional[int] = 2, channels: Optional[int] = 1, frame_rate: Optional[int] = 48000) -> List[AudioSegment]: """ Loads audio from file, preprocessess and splits into chunks Parameters ---------- file_path : str path to audio file length : float, optional length of each chunk, by default 20000/1001 split_on_silence : bool, optional wether to split audio when silence is identified, by default False noise_threshold : float, optional noise threshold denoting silence, by default -36 sample_width : int, optional new sample width of audio, by default 2 channels : int, optional new amount of channels of audio, by default 1 frame_rate : int, optional new frame rate of audio, by default 48000 Returns ------- list chunks of processed audio """ audio = AudioSegment.from_file(file_path, format='ogg') audio = process_audio(audio, remove_silence=False, sample_width=sample_width, channels=channels, frame_rate=frame_rate) return split_into_chunks(audio, length=length, split_on_silence=split_on_silence, noise_threshold=noise_threshold)
def generate(format_wav): # Создаём папку с выходными файлами generate_dir = os.path.join(hp.generate_dir, 'output') os.makedirs(generate_dir, exist_ok=True) # Создаём вокодер vocoder = GeneratorMel(hp.n_mels) # Загружаем веса ckpt = torch.load(hp.mel_checkpoint, map_location='cpu') vocoder.load_state_dict(ckpt['G']) # Информация о чекпоинте step = ckpt['step'] epochs = int(ckpt['epoch']) print('Чекпоинт загружен: Эпоха %d, Шаг %d' % (epochs, step)) # Загружаем тестовые файлы if format_wav: testset = glob.glob(os.path.join(hp.generate_dir, '*.wav')) else: testset = glob.glob(os.path.join(hp.generate_dir, '*.mel')) for i, test_path in enumerate(tqdm(testset)): test_name = os.path.basename(test_path).replace('.mel', '.wav') # Загружаем Мелспектр, или получаем его из звука if format_wav: # Получаем Мелспектр из аудио mel = 10**process_audio(test_path, it_audio = False) else: # Загружаем Мелспектр mel = torch.load(test_path).unsqueeze(0) # Сгенерировать сигнал из mel audio_output = vocoder(mel) # Убрать лишнюю размерность, градиенты и перевести в numpy audio_output = audio_output.squeeze().detach().numpy() # Сохранить в файл sf.write(generate_dir +'/mel_' + test_name, audio_output, hp.sr)
def tts(fp, sentence, silence_duration=300): """ Uses the models to create the audio file Parameters ---------- fp : str path to save the audio file sentence : str sentence to synthesize """ start = time.time() br = 240 wavs = [] length = 0 for sent in filter(lambda x: x, re.split(r'[.|;|!|?|\n]', sentence)): for frase in textwrap.wrap(sent, width=br, break_long_words=False): cached = hashlib.sha1(str.encode(frase)).hexdigest() cached = tts_cache / '{}.wav'.format(cached) if cached not in tts_cache.glob('*.wav'): waveform = model_inference(model, vocoder_model, ' ' + frase + ' ', config, use_cuda) if waveform is None: continue length += len(waveform) ap.save_wav(waveform, cached) wavs.append(cached) wavs = [ AudioSegment.from_wav(w) + AudioSegment.silent(silence_duration) for w in wavs ] waveform = sum(wavs) if len(waveform): waveform = process_audio(waveform, remove_silence=False) waveform.export(fp, format='ogg') end = time.time() total = end - start rtf = total / (length / ap.sample_rate) print(' > Run-time: {:.03f} seconds'.format(total)) print(' > Real-time factor: {:.03f} x'.format(rtf))
def train(): # Создать папку для логов save_dir = os.path.join(hp.save_dir) os.makedirs(save_dir, exist_ok=True) # Загрузить список тренировачных mel mel_list = glob.glob(os.path.join(hp.train_dir, '*.mel')) # Создать Датасет trainset = MelGanDataset(mel_list) train_loader = DataLoader(trainset, batch_size=hp.batch_size, shuffle=True, drop_last=True) # Загрузить тестовый датасет test_mels = glob.glob(os.path.join(hp.eval_dir, '*.wav'))[:3] testset = [process_audio(test_mel, it_audio = False) for test_mel in test_mels] # создать Generator и 3*Discriminator G = GeneratorMel(hp.n_mels).cuda() D = MultiScale().cuda() g_optimizer = optim.Adam(G.parameters(), lr=hp.lr, betas=(hp.betas1, hp.betas2)) d_optimizer = optim.Adam(D.parameters(), lr=hp.lr, betas=(hp.betas1, hp.betas2)) # Загружаем модель step, epochs = 0, 0 if hp.mel_checkpoint != '': print("Загрузка чекпоинтов") ckpt = torch.load(hp.mel_checkpoint) G.load_state_dict(ckpt['G']) g_optimizer.load_state_dict(ckpt['g_optimizer']) D.load_state_dict(ckpt['D']) d_optimizer.load_state_dict(ckpt['d_optimizer']) step = ckpt['step'] epochs = int(ckpt['epoch']) print('Чекпоинт загружен: Эпоха %d, Шаг %d' % (epochs, step)) #Попытка оптимизировать сеть torch.backends.cudnn.benchmark = True # Процесс обучения start = time.time() for epoch in range(epochs, hp.max_epoch): for (mel, audio) in train_loader: # Помещаем входной и выходной файл в видеокарту mel = mel.cuda() audio = audio.cuda() # Получаем сигнал из спектра 16*1*8192 fake_audio = G(mel) # Получаем отклик на созданное аудио без градиентов 3*7*16*16*8192(4096,2048) d_fake_detach = D(fake_audio.cuda().detach()) # Получаем отклик на реальное аудио d_real = D(audio) # ------------Дискриминатор--------------- # Считаем ошибку на отклике на реальный сигнал. чем больше d_real тем лучше d_loss_real = 0 for scale in d_real: d_loss_real += F.relu(1 - scale[-1]).mean() # Считаем ошибку на отклике на созданном сигнале без градиента. чем меньше d_loss_fake, тем лучше d_loss_fake = 0 for scale in d_fake_detach: d_loss_fake += F.relu(1 + scale[-1]).mean() # Суммарная ошибка d_loss = d_loss_real + d_loss_fake # вычисляем градиенты и делаем шаг D.zero_grad() d_loss.backward() d_optimizer.step() # ---------------Генератор---------------------- # Получаем отклик на созданное аудио d_fake = D(fake_audio.cuda()) # Считаем ошибку на отклик созданного сигнала с градиентом g_loss = 0 for scale in d_fake: g_loss += -scale[-1].mean() # Считаем ошибку между откликом на реальный сигнал и на созданный feature_loss = 0 for i in range(len(d_fake)): for j in range(len(d_fake[i]) - 1): feature_loss += F.l1_loss(d_fake[i][j], d_real[i][j].detach()) # Суммарная ошибка g_loss += hp.lambda_feat * feature_loss # вычисляем градиенты и делаем шаг G.zero_grad() g_loss.backward() g_optimizer.step() # выводим ошибку step += 1 if step % hp.log_interval == 0: print('Эпоха: %-5d, Шаг: %-7d, D_loss: %.05f, G_loss: %.05f, ms/batch: %5.2f' % (epoch, step, d_loss, g_loss, 1000 * (time.time() - start) / hp.log_interval)) start = time.time() # Сохраняем модель и синтезируем тестовые файлы if step % hp.save_interval == 0: print("Сохраняем модель") torch.save({ 'G': G.state_dict(), 'g_optimizer': g_optimizer.state_dict(), 'D': D.state_dict(), 'd_optimizer': d_optimizer.state_dict(), 'step': step, 'epoch': epoch, }, save_dir +'/mel_ckpt_%dk.pt' % (step // 1000)) if testset: print("Синтезируем тестовые файлы") with torch.no_grad(): for i, mel_test in enumerate(testset): audio_output = G(mel_test.cuda()) audio_output = audio_output.squeeze().cpu().numpy() sf.write(save_dir +'/mel_gen_%d_%dk_%d.wav' % (epoch, step // 1000, i), audio_output, hp.sr) else: print("Нет файлов для тестирования. Поместите их в test_dir")
def test_process_audio(): input_file = f"{PATH}/test_input/copypasta.mp4" output_file = f"{PATH}/test_output/copypasta_processed_AUDIO.mp4" result, output = utils.process_audio(input_file, output_file)
def train(format_wav): # Создать папку для логов save_dir = os.path.join(hp.save_dir) os.makedirs(save_dir, exist_ok=True) # Загрузить список тренировачных mel if format_wav: # Синтезированные Гриффин Лим файлы mel_list = glob.glob(os.path.join(hp.train_dir, '*.glim')) else: # Мел файлы mel_list = glob.glob(os.path.join(hp.train_dir, '*.mel')) # Создать Датасет trainset = WavGanDataset(mel_list, format_wav) train_loader = DataLoader(trainset, batch_size=hp.batch_size, shuffle=True, drop_last=True) # Загрузить тестовый датасет test_wavs = glob.glob(os.path.join(hp.test_dir, '*.wav')) testset = [ process_audio(test_mel, it_audio=True).unsqueeze(0) for test_mel in test_wavs ] # создать Generator и 3*Discriminator G = GeneratorWav().cuda() D = MultiScale().cuda() g_optimizer = optim.Adam(G.parameters(), lr=hp.lr, betas=(hp.betas1, hp.betas2)) d_optimizer = optim.Adam(D.parameters(), lr=hp.lr, betas=(hp.betas1, hp.betas2)) # Загружаем модель step, epochs = 0, 0 if hp.wav_checkpoint is not None: print("Загрузка чекпоинтов") ckpt = torch.load(hp.wav_checkpoint) G.load_state_dict(ckpt['G']) g_optimizer.load_state_dict(ckpt['g_optimizer']) D.load_state_dict(ckpt['D']) d_optimizer.load_state_dict(ckpt['d_optimizer']) step = ckpt['step'] epochs = int(ckpt['epoch']) print('Чекпоинт загружен: Эпоха %d, Шаг %d' % (epochs, step)) #Попытка оптимизировать сеть torch.backends.cudnn.benchmark = True # Процесс обучения start = time.time() for epoch in range(epochs, hp.max_epoch): for (audio_input, audio_output) in train_loader: # Помещаем входной и выходной файл в видеокарту audio_input = audio_input.cuda() audio_output = audio_output.cuda() # Получаем выходной сигнал из входного 16*1*8192 fake_audio = G(audio_input) # Получаем отклик на созданное аудио без градиентов 3*7*16*16*8192(4096,2048) d_fake_detach = D(fake_audio.cuda().detach()) # Получаем отклик на созданное аудио d_fake = D(fake_audio.cuda()) # Получаем отклик на реальное аудио d_real = D(audio_output) # ------------Дискриминатор--------------- # Считаем ошибку на отклике на реальный сигнал. чем больше d_real тем лучше d_loss_real = 0 for scale in d_real: d_loss_real += F.relu(1 - scale[-1]).mean() # Считаем ошибку на отклике на созданном сигнале без градиента. чем меньше d_loss_fake, тем лучше d_loss_fake = 0 for scale in d_fake_detach: d_loss_fake += F.relu(1 + scale[-1]).mean() # Суммарная ошибка d_loss = d_loss_real + d_loss_fake # Вычисляем градиенты и делаем шаг D.zero_grad() d_loss.backward() d_optimizer.step() # ---------------Генератор---------------------- # Считаем ошибку на отклик созданного сигнала с градиентом g_loss = 0 for scale in d_fake: g_loss += -scale[-1].mean() # Считаем ошибку между откликом на реальный сигнал и на созданный feature_loss = 0 for i in range(len(d_fake)): for j in range(len(d_fake[i]) - 1): feature_loss += F.l1_loss(d_fake[i][j], d_real[i][j].detach()) # Суммарная ошибка g_loss += hp.lambda_feat * feature_loss # вычисляем градиенты и делаем шаг G.zero_grad() g_loss.backward() g_optimizer.step() # выводим ошибку step += 1 if step % hp.log_interval == 0: print( 'Эпоха: %-5d, Шаг: %-7d, D_loss: %.05f, G_loss: %.05f, ms/batch: %5.2f' % (epoch, step, d_loss, g_loss, 1000 * (time.time() - start) / hp.log_interval)) start = time.time() # Сохраняем модель и синтезируем тестовые файлы if step % hp.save_interval == 0: print("Сохраняем модель") torch.save( { 'G': G.state_dict(), 'g_optimizer': g_optimizer.state_dict(), 'D': D.state_dict(), 'd_optimizer': d_optimizer.state_dict(), 'step': step, 'epoch': epoch, #}, save_dir +'/wav_ckpt_%dk.pt' % (step // 10000)) }, save_dir + '/wav_ckpt_%d.pt' % (step)) if testset: print("Синтезируем тестовые файлы") with torch.no_grad(): for i, audio_input in enumerate(testset): audio_output = G(audio_input.cuda()) audio_output = audio_output.squeeze().detach().cpu( ).numpy() audio_input = audio_input.squeeze().detach().cpu( ).numpy() spectr = librosa.stft(y=audio_input, hop_length=hp.hop_length, n_fft=hp.n_fft) ampl = np.abs(spectr) #Амплитуда phasa = np.angle(spectr) #Фаза spectr2 = librosa.stft(y=audio_output, hop_length=hp.hop_length, n_fft=hp.n_fft) #ampl2 = np.abs(spectr2) #Амплитуда phasa2 = np.angle(spectr2) #Фаза p1 = phasa.shape[1] p2 = phasa2.shape[1] if p1 > p2: delta_shape = p1 - p2 ph2 = np.pad(phasa2, ((0, 0), (0, delta_shape)), mode='constant', constant_values=0) else: ph2 = np.delete(phasa2, np.s_[p1:], 1) ampl_phasa = ampl * np.cos( ph2) + 1j * ampl * np.sin(ph2) y_ampl_phasa = librosa.istft( ampl_phasa, hop_length=hp.hop_length) sf.write( save_dir + '/wav_gen_%d_%dk_%d.wav' % (epoch, step // 1000, i), audio_output, hp.sr) sf.write( save_dir + '/wav_phase_%d_%dk_%d.wav' % (epoch, step // 1000, i), y_ampl_phasa, hp.sr) else: print( "Нет файлов для тестирования. Поместите их в test_dir")