-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathutils.py
207 lines (165 loc) · 8.08 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import numpy as np
import librosa, os, torch, shutil, random, copy, glob
from torch.utils.data import Dataset
from hparams import Hparams
from tqdm import tqdm
import soundfile as sf
# Загружаем гиперпараметры
hp = Hparams()
#----------Алгоритм Гриффин Лим-------------
def my_griffin_lim(spectrogram, n_iter=3):
#копируем спектр
x_best = copy.deepcopy(spectrogram)
for i in range(n_iter):
# получаем сигнал
x_t = librosa.istft(x_best, hp.hop_length, window="hann")
# получаем спектр
spec = librosa.stft(x_t, hp.n_fft, hp.hop_length)
# берём фазу
phase = np.angle(spec)
# Получаем полный спектр исходного сигнала
x_best = spectrogram*np.cos(phase) + 1j*spectrogram*np.sin(phase)
# Итоговый сигнал
x_t = librosa.istft(x_best, hp.hop_length, window="hann")
return x_t
#-------Функция обработки датасета--------------
def preprocess(format_wav):
#Создать папку
train_dir = os.path.join(hp.train_dir)
os.makedirs(train_dir, exist_ok=True)
eval_dir = os.path.join(hp.eval_dir)
os.makedirs(eval_dir, exist_ok=True)
# Датасет для тренировки
dataset = glob.glob(os.path.join(hp.data_dir, '**/*.'+hp.format), recursive=True)
for train_path in tqdm(dataset):
# Только название файла
train_name = os.path.basename(train_path)
# Обработать звук в мел
process_audio(train_path, hp.format, train_name, it_audio = format_wav)
print('Тренировачный датасет создан')
#----------Обработка аудио в мел, или в Гриффин Лим аудио-------------
def process_audio(wav_path, format = 'wav', wav_name=None, it_audio = True):
# чтение файла
wav, sr = librosa.core.load(wav_path, sr=hp.sr)
# Удалить тишину
wav, _ = librosa.effects.trim(wav, top_db=hp.trim)
# Получить спектр
spectrogram = librosa.stft(y=wav, n_fft=hp.n_fft, hop_length = hp.hop_length, win_length = hp.win_length)
# Получить мелспектрограмму
output = np.dot(hp.mel_basis, np.sqrt(np.abs(spectrogram**2)))
output = np.log10(output).astype(np.float32)
# синтезируем Гриффин Лим аудио
if it_audio:
amp = np.maximum(1e-10, np.dot(hp._inv_mel_filtr, 10**output))
output = my_griffin_lim(amp,5).astype(np.float32)
# Перевести в torch
output = torch.from_numpy(output)
# Получаем новый путь до файла
if wav_name is not None:
#print(wav_name)
if wav_name[3] =='8':
dir_folder = hp.eval_dir
else:
dir_folder = hp.train_dir
old_wav_path = wav_path
#print(dir_folder, wav_name)
wav_path = os.path.join(dir_folder, wav_name)
# Если было wav то копируем, иначе конвертируем
if format == 'wav':
# Копируем wav
shutil.copyfile(old_wav_path, wav_path)
else:
# Cоздаём wav из другого формата
sf.write(wav_path.replace('.'+format, '.wav'), wav, hp.sr)
# Сохраняем Мелспектрограмму, или Гриффин Лим аудио
if it_audio:
save_path = wav_path.replace('.'+format, '.glim')
else:
save_path = wav_path.replace('.'+format, '.mel')
torch.save(output, save_path)
return output.unsqueeze(0)
# Датасет
class AgainDataset(Dataset):
def __init__(self, dset):
super().__init__()
print(f'Загружаем {dset} датасет в память')
dataset = tqdm(glob.glob(os.path.join(dset, '*.mel'), recursive=True))
self.data = []
for train_path in dataset:
y = torch.load(train_path).numpy()
y[y==-np.inf] = -10
self.data.append(y)
def __len__(self):
return len(self.data)
def __getitem__(self, index):
mel = self.data[index]
# Обрезаем до одинаковой длины
if mel.shape[1] < hp.seglen:
pad_len = hp.seglen - mel.shape[1]
mel = np.pad(mel, ((0,0), (0,pad_len)), mode='wrap')
elif mel.shape[1] > hp.seglen:
start_index = random.randint(0,mel.shape[1] - hp.seglen)
mel = mel[:,start_index:start_index+hp.seglen]
return mel
class MelGanDataset(Dataset):
def __init__(self, mel_list):
# Инициализировать список мелспектрограмм
self.mel_list = mel_list
def __len__(self):
return len(self.mel_list)
def __getitem__(self, idx):
# Считываем mel
mel = torch.load(self.mel_list[idx])
# Считываем wav
wav_name = self.mel_list[idx].replace('.mel', '.wav')
wav, _ = librosa.core.load(wav_name, sr=None)
wav = torch.from_numpy(wav).float()
# Подгоняем все записи под одну длину, чтобы обучать пакетом
start_index = 0
if mel.shape[1] < hp.seglen:
pad_len = hp.seglen - mel.shape[1]
mel = torch.nn.functional.pad(mel, (0,pad_len))
wav = torch.nn.functional.pad(wav, (0,pad_len* hp.hop_length))
elif mel.shape[1] > hp.seglen:
start_index = random.randint(0,mel.shape[1] - hp.seglen)
mel = mel[:,start_index:start_index+hp.seglen]
start_index *= hp.hop_length
wav = wav[start_index : start_index + hp.seglen * hp.hop_length]
return mel, wav.unsqueeze(0)
class WavGanDataset(Dataset):
def __init__(self, mel_list, format_wav):
# Инициализировать список мелспектрограмм
self.mel_list = mel_list
self.format_wav = format_wav
def __len__(self):
return len(self.mel_list)
def __getitem__(self, idx):
# Считываем mel, или Гриффин Лим аудио
input = torch.load(self.mel_list[idx])
# Если это mel синтезировать
if not self.format_wav:
# Амплитуда
amp = np.maximum(1e-10, np.dot(hp._inv_mel_filtr, input))
# Синтезируем
input = my_griffin_lim(amp,5)
# В тензор
input = torch.from_numpy(input)
# Считываем wav
wav_name = self.mel_list[idx].replace('.mel', '.wav').replace('.glim', '.wav')
wav, _ = librosa.core.load(wav_name, sr=None)
wav = torch.from_numpy(wav).float()
"""
#Подмешиваем шум
type_f = np.random.sample()
if type_f<0.3:
# К Гриффин лим сигналу подмешиваем шум
input = input + torch.from_numpy(np.random.sample(input.shape) * np.random.sample()* 0.01).float()
elif type_f<0.6:
# В качестве исходных данный конечный сигнал с шумом
input = wav + torch.from_numpy(np.random.sample(wav.shape) * np.random.sample()* 0.01).float()
"""
# Подгоняем все записи под одну длину, чтобы обучать пакетом
start = random.randint(0,input.size(-1) - hp.seq_len * hp.hop_length - 1)
input = input[start : start + hp.seq_len * hp.hop_length]
wav = wav[start : start + hp.seq_len * hp.hop_length]
return input.unsqueeze(0), wav.unsqueeze(0)