chldkato

한국어 노래 합성 정리 본문

딥러닝

한국어 노래 합성 정리

chldkato 2022. 9. 19. 20:43

음성 합성 TTS는 타코트론에서 hifigan을 거치면서 많은 발전이 있었고, diffusion을 적용한 모델 등 많은 모델이 있다.

TTS의 다음 스텝으로 연구해볼 만한 분야는 노래 합성인데, 연구하기가 만만치 않다.

이유로 첫째는 데이터 부족, 두번째는 TTS의 타코트론처럼 표준적인 모델이 없다는 점, 그리고 추가적으로 미디 데이터를 다루는 오디오 믹싱 지식이 어느정도는 필요하다는 점이다.

 

노래 합성은 singing voice synthesis (SVS) 를 키워드로 검색해보면 된다.

오픈소스 중에서 begansing은 한국어 보컬 데이터 Children's Song Data (CSD) 를 사용했기 때문에 가장 접근하기 쉽다.

CSD는 오픈된 데이터라서 검색하면 다운 받을 수 있다.

그리고 aihub에 보컬 데이터가 올라오긴 했는데, 추가적으로 가공을 해야 사용할 수 있다

 

파이썬에서 midi 파일 다루기

 

mido 라이브러리를 사용하면 midi 파일을 처리할 수 있다.

midi format 1 기준으로 불러오면 아래와 같이 나온다

mido.MidiFile(midi_file_name)

>>> print(midi)
MidiFile(type=1, ticks_per_beat=960, tracks=[
  MidiTrack([
    MetaMessage('track_name', name='mid', time=0),
    MetaMessage('time_signature', numerator=4, denominator=4, clocks_per_click=24, notated_32nd_notes_per_beat=8, time=0),
    MetaMessage('key_signature', key='C', time=0),
    MetaMessage('set_tempo', tempo=461538, time=0),
    MetaMessage('end_of_track', time=0)]),
  MidiTrack([
    MetaMessage('track_name', name='Track 1', time=0),
    Message('note_on', channel=0, note=59, velocity=100, time=1920),
    Message('note_on', channel=0, note=59, velocity=0, time=480),
    Message('note_on', channel=0, note=59, velocity=100, time=0),
    Message('note_on', channel=0, note=59, velocity=0, time=480),
    Message('note_on', channel=0, note=59, velocity=100, time=0),
    Message('note_on', channel=0, note=59, velocity=0, time=960),
    ...
    MetaMessage('end_of_track', time=0)])
])

 

여기서 모든 정보가 필요한건 아니라서 필요한거만 추리면 아래와 같다

ticks_per_beat = midi.ticks_per_beat

msg_list = []
for track in midi.tracks:
    for msg in track:
        if msg.type == 'set_tempo':
            tempo = msg.tempo
        elif msg.type == 'note_on':
            msg_list.append([msg.note, msg.time])
            
>>> print(ticks_per_beat)
960

>>> print(tempo)
461538

>>> print(msg_list)
[[59, 1920], [59, 480], [59, 0], [59, 480], [59, 0], [59, 960], ...]

각 음의 time은 초 단위가 아니라서, ticks_per_beat, tempo를 저장해서 시간 초로 변환해줘야 한다.

그리고 음에 해당하는 msg.note와 msg.time을 리스트로 해서 따로 저장해 두었다.

위의 코드는 어디까지나 예시이기에 사용자 필요에 따라서 수정하면 된다.

 

note는 가운데 도 C4를 60으로 두고 정수로 기록한 것이다.

따라서 59는 '시' 가 된다.

만약 C4 같은 형태로 저장해야 한다면 librosa.midi_to_note 를 사용하면 된다. (반대는 librosa.note_to_midi)

 

time은 tick 단위인데, 앞의 ticks_per_beat 와 tempo를 사용해서 아래 코드처럼 사용해서 초 단위로 바꿔줄 수 있다.

scale = tempo * 1e-6 / ticks_per_beat
sec = msg_list[2*idx+1][1] * scale

msg_list에 저장한 것을 해석해보자면,

[59, 1920]: 첫 음 '시' (59) 가 1920 tick 다음에 나온다 (다시 말해 맨 앞 1920 tick은 묵음 구간이다)

[59, 480]: 이 음이 480 tick의 길이를 가진다.

[59, 0], [59, 480]: 그리고 다음 음 '시' 가 묵음 없이 바로 이어서 480 tick 나온다.

[59, 0,] [59, 960]: 다시 또 음 '시' 가 묵음 없이 바로 이어서 960 tick 나온다.

이런식으로 보면 된다.

 

 

아래는 csd 데이터만으로 single singer 학습해서 테스트해본 샘플이다.

 

'딥러닝' 카테고리의 다른 글

Montreal Forced Aligner (MFA) 한국어 사용법  (25) 2021.06.02
DCTTS 정리  (0) 2020.10.28
Tacotron2 정리  (0) 2020.05.08
윈도우에서 MelGAN 학습하기  (42) 2020.04.08
Tacotron 정리  (8) 2020.04.03
Comments