data_function.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. # Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # MIT License
  15. #
  16. # Copyright (c) 2020 Jungil Kong
  17. #
  18. # Permission is hereby granted, free of charge, to any person obtaining a copy
  19. # of this software and associated documentation files (the "Software"), to deal
  20. # in the Software without restriction, including without limitation the rights
  21. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  22. # copies of the Software, and to permit persons to whom the Software is
  23. # furnished to do so, subject to the following conditions:
  24. #
  25. # The above copyright notice and this permission notice shall be included in all
  26. # copies or substantial portions of the Software.
  27. #
  28. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  31. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  32. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  33. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  34. # SOFTWARE.
  35. # The following functions/classes were based on code from https://github.com/jik876/hifi-gan:
  36. # mel_spectrogram, MelDataset
  37. import math
  38. import os
  39. import numpy as np
  40. import torch
  41. import torch.nn.functional as F
  42. import torch.utils.data
  43. from librosa.filters import mel as librosa_mel_fn
  44. from librosa.util import normalize
  45. from numpy import random
  46. from torch.utils.data import DataLoader
  47. from torch.utils.data.distributed import DistributedSampler
  48. from common.audio_processing import dynamic_range_compression
  49. from common.utils import load_filepaths_and_text, load_wav
  50. MAX_WAV_VALUE = 32768.0
  51. mel_basis = {}
  52. hann_window = {}
  53. def mel_spectrogram(y, n_fft, num_mels, sampling_rate, hop_size, win_size,
  54. fmin, fmax, center=False):
  55. if torch.min(y) < -1.:
  56. print('min value is ', torch.min(y))
  57. if torch.max(y) > 1.:
  58. print('max value is ', torch.max(y))
  59. global mel_basis, hann_window
  60. fmax_key = f'{fmax}_{y.device}'
  61. if fmax_key not in mel_basis:
  62. mel = librosa_mel_fn(sr=sampling_rate, n_fft=n_fft, n_mels=num_mels,
  63. fmin=fmin, fmax=fmax)
  64. mel_basis[fmax_key] = torch.from_numpy(mel).float().to(y.device)
  65. hann_window[str(y.device)] = torch.hann_window(win_size).to(y.device)
  66. pad = int((n_fft-hop_size)/2)
  67. y = F.pad(y.unsqueeze(1), (pad, pad), mode='reflect')
  68. y = y.squeeze(1)
  69. spec = torch.stft(y, n_fft, hop_length=hop_size, win_length=win_size,
  70. window=hann_window[str(y.device)], center=center,
  71. pad_mode='reflect', normalized=False, onesided=True,
  72. return_complex=True)
  73. spec = torch.view_as_real(spec)
  74. spec = torch.sqrt(spec.pow(2).sum(-1)+(1e-9))
  75. spec = torch.matmul(mel_basis[str(fmax)+'_'+str(y.device)], spec)
  76. spec = dynamic_range_compression(spec) # spectral normalize
  77. return spec
  78. class MelDataset(torch.utils.data.Dataset):
  79. def __init__(self, training_files, segment_size, n_fft, num_mels,
  80. hop_size, win_size, sampling_rate, fmin, fmax, split=True,
  81. device=None, fmax_loss=None, fine_tuning=False,
  82. base_mels_path=None, repeat=1, deterministic=False,
  83. max_wav_value=MAX_WAV_VALUE):
  84. self.audio_files = training_files
  85. self.segment_size = segment_size
  86. self.sampling_rate = sampling_rate
  87. self.split = split
  88. self.n_fft = n_fft
  89. self.num_mels = num_mels
  90. self.hop_size = hop_size
  91. self.win_size = win_size
  92. self.fmin = fmin
  93. self.fmax = fmax
  94. self.fmax_loss = fmax_loss
  95. self.max_wav_value = max_wav_value
  96. self.fine_tuning = fine_tuning
  97. self.base_mels_path = base_mels_path
  98. self.repeat = repeat
  99. self.deterministic = deterministic
  100. self.rng = random.default_rng()
  101. def __getitem__(self, index):
  102. if index >= len(self):
  103. raise IndexError('Dataset index out of range')
  104. rng = random.default_rng(index) if self.deterministic else self.rng
  105. index = index % len(self.audio_files) # collapse **after** setting seed
  106. filename = self.audio_files[index]
  107. audio, sampling_rate = load_wav(filename)
  108. audio = audio / self.max_wav_value
  109. if not self.fine_tuning:
  110. audio = normalize(audio) * 0.95
  111. if sampling_rate != self.sampling_rate:
  112. raise ValueError("{} SR doesn't match target {} SR".format(
  113. sampling_rate, self.sampling_rate))
  114. audio = torch.FloatTensor(audio)
  115. audio = audio.unsqueeze(0)
  116. if not self.fine_tuning:
  117. if self.split:
  118. if audio.size(1) >= self.segment_size:
  119. max_audio_start = audio.size(1) - self.segment_size
  120. audio_start = rng.integers(0, max_audio_start)
  121. audio = audio[:, audio_start:audio_start+self.segment_size]
  122. else:
  123. audio = F.pad(audio, (0, self.segment_size - audio.size(1)))
  124. mel = mel_spectrogram(audio, self.n_fft, self.num_mels,
  125. self.sampling_rate, self.hop_size,
  126. self.win_size, self.fmin, self.fmax,
  127. center=False)
  128. else:
  129. mel = np.load(
  130. os.path.join(self.base_mels_path,
  131. os.path.splitext(os.path.split(filename)[-1])[0] + '.npy'))
  132. mel = torch.from_numpy(mel).float()
  133. if len(mel.shape) < 3:
  134. mel = mel.unsqueeze(0)
  135. if self.split:
  136. frames_per_seg = math.ceil(self.segment_size / self.hop_size)
  137. if audio.size(1) >= self.segment_size:
  138. mel_start = rng.integers(0, mel.size(2) - frames_per_seg)
  139. mel = mel[:, :, mel_start:mel_start + frames_per_seg]
  140. a = mel_start * self.hop_size
  141. b = (mel_start + frames_per_seg) * self.hop_size
  142. audio = audio[:, a:b]
  143. else:
  144. mel = F.pad(mel, (0, frames_per_seg - mel.size(2)))
  145. audio = F.pad(audio, (0, self.segment_size - audio.size(1)))
  146. mel_loss = mel_spectrogram(audio, self.n_fft, self.num_mels,
  147. self.sampling_rate, self.hop_size,
  148. self.win_size, self.fmin, self.fmax_loss,
  149. center=False)
  150. return (mel.squeeze(), audio.squeeze(0), filename, mel_loss.squeeze())
  151. def __len__(self):
  152. return len(self.audio_files) * self.repeat
  153. def get_data_loader(args, distributed_run, train=True, batch_size=None,
  154. val_kwargs=None):
  155. filelists = args.training_files if train else args.validation_files
  156. files = load_filepaths_and_text(args.dataset_path, filelists)
  157. files = list(zip(*files))[0]
  158. dataset_kw = {
  159. 'segment_size': args.segment_size,
  160. 'n_fft': args.filter_length,
  161. 'num_mels': args.num_mels,
  162. 'hop_size': args.hop_length,
  163. 'win_size': args.win_length,
  164. 'sampling_rate': args.sampling_rate,
  165. 'fmin': args.mel_fmin,
  166. 'fmax': args.mel_fmax,
  167. 'fmax_loss': args.mel_fmax_loss,
  168. 'max_wav_value': args.max_wav_value,
  169. 'fine_tuning': args.fine_tuning,
  170. 'base_mels_path': args.input_mels_dir,
  171. 'deterministic': not train
  172. }
  173. if train:
  174. dataset = MelDataset(files, **dataset_kw)
  175. sampler = DistributedSampler(dataset) if distributed_run else None
  176. else:
  177. dataset_kw.update(val_kwargs or {})
  178. dataset = MelDataset(files, **dataset_kw)
  179. sampler = (DistributedSampler(dataset, shuffle=False)
  180. if distributed_run else None)
  181. loader = DataLoader(dataset,
  182. num_workers=args.num_workers if train else 1,
  183. shuffle=(train and not distributed_run),
  184. sampler=sampler,
  185. batch_size=batch_size or args.batch_size,
  186. pin_memory=True,
  187. persistent_workers=True,
  188. drop_last=train)
  189. return loader