- Audio Decomposition은 음악을 악보로 옮기기 위해 오디오를 구성 음표와 악기로 나누려는 오픈소스 프로그램임
- 악기 샘플은 University of Iowa Electronic Music Studios instrument database에서 가져오며, 각 파형의 푸리에 변환과 엔벨로프를 저장해 비교 기준으로 사용함
- 음악 파일을 0.1초 단위로 분석해 스펙트로그램을 만들고, 저장된 악기별 푸리에 변환을 조합해 해당 구간의 악기별 크기를 추정함
- 엔벨로프 분석은 attack·sustain·release 구간과 정적/동적 감쇠를 나눈 뒤, 필터링된 음표 대역에서 악기별 비용을 계산함
- 결과는 오디오 재생성보다 matplotlib 산점도로 악보처럼 표시하는 방식을 택해 문제 해결과 희소 데이터 표시를 쉽게 만듦
악보 변환을 위한 오디오 분해
- Audio Decomposition은 음악을 악보로 바꾸는 프로그램을 만들려는 목표에서 시작함
- 개인적으로 음악을 악보로 옮기고 싶었고, 오픈소스이면서 단순한 오디오 소스 분리 알고리듬이 부족하다고 느낀 점이 동기가 됨
- 데모 영상은 YouTube에 공개되어 있음
- GitHub 저장소는 mbird1258/Audio-Decomposition임
- 악기 샘플은 University of Iowa Electronic Music Studios instrument database에서 가져옴
- 각 파일에 대해 전체 파형의 푸리에 변환과 엔벨로프를 계산해 저장함
0.1초 단위 푸리에 변환
- 악기 소리는 주로 푸리에 변환과 엔벨로프로 특징지을 수 있다고 보고, 두 정보를 이용해 어떤 악기가 어떤 음을 내는지 추정함
- 음악 파일은 0.1초마다 푸리에 변환을 수행해 스펙트로그램 형태로 처리함
- 각 0.1초 구간의 푸리에 변환을 재현하기 위해 저장된 악기별 푸리에 변환을 더함
- 악기별 크기는 MSE 비용 함수의 주파수별 편미분에서 나온 행렬을 풀어 계산함
- 행렬의 각 행은 cello, piano 등 각 악기에 대한 편미분에 해당함
- 예시는 5Hz의 푸리에 변환 값 같은 주파수별 값에 대한 비용 계산임
엔벨로프와 음의 구간 분리
- 엔벨로프는 파형의 상한선이며, 기존 함수들이 노이즈나 특정 파형에서 잘 동작하지 않는 경우가 있어 별도 방식을 사용함
- 계산 과정은 파형을 청크로 나눈 뒤 각 청크의 최댓값을 취하는 방식임
- 이후 엔벨로프가 원본 파형보다 낮은 지점을 찾아 새 점을 추가해 결과를 다듬음
- 엔벨로프는 attack, sustain, release로 나눔
- attack: 음의 초기 소리
- sustain: 음이 유지되는 구간
- release: 음이 멈추는 구간
- 악기 샘플에서는 첫 번째 0이 아닌 값을 attack 시작점으로 사용함
- attack과 sustain의 경계는 함수가 처음으로 아래로 오목하거나 감소하는 지점으로 정함
- sustain과 release의 경계는 끝에서부터 보며 함수가 증가하거나 아래로 오목한 첫 지점으로 정함
- release의 끝은 끝에서부터 보며 처음으로 0이 아닌 지점으로 찾음
감쇠 유형과 악기 매칭
- 파형의 주요 형태를 구분하기 위해 정적 감쇠와 동적 감쇠를 고려함
- piano 같은 일부 악기는 대체로 지수 감쇠 형태를 따르는 정적 감쇠를 가짐
- violin 같은 일부 악기는 sustain 중에도 음량이 증가하거나 감소할 수 있음
- 악기 샘플 중에는 소리가 자연히 사라질 때까지 유지된 파일도 있고, 일찍 release된 파일도 있음
- 감쇠가 정적인지 동적인지는 감쇠 계수가 1보다 크거나 감쇠 곡선에서 너무 많이 벗어나는지로 구분함
- 엔벨로프가 release를 갖는지, 즉 AS인지 ASR인지는 sustain과 release의 평균 변화율을 비교해 판단함
- release의 변화율이 더 낮으면 release가 없는 것으로 봄
- 음악 파일 처리에서는 각 음표 주파수에 대해 대역통과 필터를 적용함
- 필터링된 파형에 대해 각 악기를 순회하며 정규화된 attack과 release의 상호상관을 계산해 음의 시작과 끝을 찾음
- 이후 악기 파형과 필터링된 오디오의 MSE를 계산해 해당 시점의 악기 비용으로 사용함
- 최종 크기는 푸리에 변환 단계의 크기와 엔벨로프 단계의
1 / 비용을 곱해 계산함
산점도 기반 결과 표시
- 결과는 matplotlib의 scatter plot을 사용해
-모양 점으로 악보처럼 나타냄 - 원래는 계산된 크기에서 오디오를 재생성하려 했지만 문제가 많고 시간이 걸렸으며 디버깅도 어려웠음
- matplotlib의 imshow도 시도했지만, 대부분의 값이 0인 상황에서는 매우 비효율적이었음
- 화면을 이동하거나 확대·축소할 때 화면에 보이는지와 상관없이 모든 점을 다시 그려야 했기 때문임
- 결과적으로 악보 재현을 더 잘 만드는 데 사용할 수 있으며, 특히 올바른 피치나 코드를 찾기 어려운 경우에 도움이 됨
- 예시로 YouTube 영상을 바탕으로 Noteflight 악보를 재현하는 데 사용함
- 실행 시간도 너무 오래 걸리지는 않는 수준임