대외활동/포스텍 인공지능연구원 연구인턴 & 연장

[ 포스텍 인공지능연구원 연구인턴 ] HiFi-GAN Reproducing 코드 구현

hae-koos 2022. 7. 26. 17:08
728x90
반응형

https://hae-koos.tistory.com/79

[ 포스텍 인공지능연구원 연구인턴 ] HiFi-GAN 논문 리뷰 / Vocoder 개념 설명 및 정리

 

[ 포스텍 인공지능연구원 연구인턴 ] HiFi-GAN 논문 리뷰 / Vocoder 개념 설명 및 정리

Vocoder 배경지식 : Mel-spectrogram 넣으면 Wave 만드는 친구 → 공부하자 BACKGROUND 합성음 음질을 결정하는 요소 (Neural Speech Synthesis 관점) 주어진 텍스트로 멜 스펙트로그램을 얼마나 잘 생성해 낼 수..

hae-koos.tistory.com

https://github.com/jik876/hifi-gan

[ Official Repository ] HiFi-GAN: Generative Adversarial Networks for Efficient and High Fidelity Speech Synthesis

 

GitHub - jik876/hifi-gan: HiFi-GAN: Generative Adversarial Networks for Efficient and High Fidelity Speech Synthesis

HiFi-GAN: Generative Adversarial Networks for Efficient and High Fidelity Speech Synthesis - GitHub - jik876/hifi-gan: HiFi-GAN: Generative Adversarial Networks for Efficient and High Fidelity Spee...

github.com


Paper Review를 마치고, 논문의 흐름에 따라 모델을 직접 학습시켜봤다.

LJ Speech Dataset으로 학습을 시킨 후 해당 데이터로 진행한 Inference와

Unseen Data인 VCTK Dataset으로 Inference를 각각 시도하였으며,

Wav 파일로부터 Wav 파일을 Generation 한 경우와

Mel-spectrogram으로부터 Wav 파일을 Generation 한 경우를 구분하여 구현하였다.

최신 논문들까지 애용하는 이유가 확실히 존재하는 Vocoder라고 느꼈다.

 

 

  • Checkpoint 저장 형태torch.save로 저장했으니 torch.load로 불러오기 (utils.py 파일 체크)
# checkpointing
if steps % a.checkpoint_interval == 0 and steps != 0:
    checkpoint_path = "{}/g_{:08d}".format(a.checkpoint_path, steps)
    save_checkpoint(checkpoint_path,
                    {'generator': (generator.module if h.num_gpus > 1 else generator).state_dict()})
    checkpoint_path = "{}/do_{:08d}".format(a.checkpoint_path, steps)
    save_checkpoint(checkpoint_path, 
                    {'mpd': (mpd.module if h.num_gpus > 1
                                         else mpd).state_dict(),
                     'msd': (msd.module if h.num_gpus > 1
                                         else msd).state_dict(),
                     'optim_g': optim_g.state_dict(), 'optim_d': optim_d.state_dict(), 'steps': steps,
                     'epoch': epoch})

 

 

  • 학습 완료 및 Inference
    • 추후 기법개발을 위해 직접 만든 mel-spectrogram으로도 작동하는지 체크하는데 쇠 소리, 잡음 등 이상한 소리만 등장했다.
    • librosa.feature.melspectrogram (실패)
    • librosa.feature.melspectrogram + np.clip((S-min_level_db)/-min_level_db,0,1) (실패)
    • from librosa.filters import mel + torch.log(torch.clamp(x, min=clip_val) * 1) (성공)
    • -> 결국 stft하고, mel filter bank 만들어서 입히는 형태로 reproducing이 성공하였는데 시각화를 해보니 이 방식으로 mel-spectrogram을 만들고, exponential 먹이면 시각화도 잘 된다. 저자 방식이 normalized 형태인 듯
from librosa.filters import mel as librosa_mel_fn

def dynamic_range_compression_torch(x, C=1, clip_val=1e-5):
    return torch.log(torch.clamp(x, min=clip_val) * C)
def spectral_normalize_torch(magnitudes):
    output = dynamic_range_compression_torch(magnitudes)
    return output

MAX_WAV_VALUE = 32768.0
mel_basis = {}
hann_window = {}

def mel_spectrogram(y, n_fft, num_mels, sampling_rate, hop_size, win_size, fmin, fmax, center=False):
    if torch.min(y) < -1.:
        print('min value is ', torch.min(y))
    if torch.max(y) > 1.:
        print('max value is ', torch.max(y))

    global mel_basis, hann_window
    if fmax not in mel_basis:
        mel = librosa_mel_fn(sampling_rate, n_fft, num_mels, fmin, fmax)
        mel_basis[str(fmax)+'_'+str(y.device)] = torch.from_numpy(mel).float().to(y.device)
        hann_window[str(y.device)] = torch.hann_window(win_size).to(y.device)

    y = torch.nn.functional.pad(y.unsqueeze(1), (int((n_fft-hop_size)/2), int((n_fft-hop_size)/2)), mode='reflect')
    y = y.squeeze(1)

    spec = torch.stft(y, n_fft, hop_length=hop_size, win_length=win_size, window=hann_window[str(y.device)],
                      center=center, pad_mode='reflect', normalized=False, onesided=True)

    spec = torch.sqrt(spec.pow(2).sum(-1)+(1e-9))

    spec = torch.matmul(mel_basis[str(fmax)+'_'+str(y.device)], spec)
    spec = spectral_normalize_torch(spec)

    return spec

 

  • Reproducing Results
    • 순서대로
    • Source (LJSpeech)
    • Generated from wav (Seen LJSpeech)
    • Generated from mel (Seen LJSpeech)
    • Generated from mel (Unseen VCTK)

LJ001-0007.wav
0.35MB
LJ001-0007_generated.wav
0.35MB
LJ001-0007_3_generated_e2e.wav
0.35MB
VCTK-p225_1_generated_e2e.wav
0.09MB


사람 좋아하는 노벨이

 

728x90
반응형