이제는 공부한 내용에 강의를 정리하는 것과 더불어 프로젝트 진행 중에 만나게 된 작은 문제들을 기록하는 것이 좋을 듯 하다.
https://abcnotation.com/
pyabc는 abc로 표기된 music의 악보(symbolic music)를 parsing 해주는 작업을 하는 라이브러리이다. 이번에 AI music generation 프로젝트를 하면서 만나게된 대부분의 데이터들은 abc 데이터였으므로 이를 tokenizing 하기 위해서는 제대로 parsing 해주는 것이 필요했다.
우선 language 모델을 생각해보면 abc note들은 token으로 나뉘어져서 140개 정도의 vocab으로 구성이 된다. abc파일은 open으로 읽는다. f는 open objec이고, 이를 read()로 읽어주면 통채로 읽은 string이 된다. 만약에 readlines()를 사용하면 \n으로 스플릿된 리스트로 읽어진다.
https://github.com/campagnola/pyabc
우리는 해당 링크의 pyabc를 폴더 채로 from pyabc import pyabc로 사용했지만 문제가 있었는데, the session 데이터의 경우에는 하나의 abc 파일안에 같은 곡의 여러개의 변주들의 tune이 들어가 있어서 parsing 작업이 되지 않았던 것이다. 그래서 교수님께서 Tunes라는 class를 만들어 주었다. Tunes로 읽은 Tunes 클래스는 해당하는 개수만큼의 tune 데이터들이 리스트의 형태로 들어가 있으며 이는 tunes method로 읽어올 수 있다.
with open(abc_path, 'r') as f:
fr = f.read()
print(abc_path) # PosixPath('dataset/the_session/1.abc')
print(f) # _io.TextIOWrapper object이다.
print(fr) # abc의 string이다.
tune = pyabc.Tune(abc=fr) # <pyabc.pyabc.Tune at 0x7f8f99ef60d0>
tunes = pyabc.Tunes(abc=fr) # <pyabc.pyabc.Tunes at 0x7f8f99e91160>
tunes = read_tunes(abc_list[0])
print(tunes.tunes) # [<pyabc.pyabc.Tune object at ...]
이후에 시간이 정말 오래 걸린 작업은 rule base로 도돌이표, da capo를 체크해서 measure를 순서대로 읽어올 수 있게 한 부분이었다.
pyabc를 pip 모듈로 설치를 한 경우에는 sys에서 지워주고 사용을 해야한다.
import pyabc
pyabc.__file__
import sys
sys.path
sys.path.remove()
irish, the_session 외에도 추가적인 데이터 중에서 folk_rnn은 하나의 파일에 4만 5천여개의 데이터들이 모두 모여있었다. 이를 나눠주고 다시 적어줄 필요가 있었는데 나눠주는 코드는 날아가버리고, 이미 나누어진 .abc 파일을 읽어서 수정할 코드만 남았다. 'r'로 읽고, lines에 저장한 뒤에 'w'로 쓴다.
for i in range(1, 45851):
with open (str(i).zfill(5)+'.abc', 'r') as f:
lines = f.readlines()
lines[0] = f'X:{i}\n'
lines = ''.join(lines)
with open (str(i).zfill(5)+'.abc', 'w') as f:
f.write(lines)
# 저장 경로를 지정하고 싶은 경우에 아래와 같이 사용
with open (f'[폴더경로]/{str(i).zfill(5)}.abc', 'w') as f:
f.write(lines)