Choirless를 위한 새롭고 더욱 강력한 동기화 알고리즘

Choirless의 주요 기능 중 하나는 업로드된 부분을 자동으로 동기화한다는 것입니다. 그것이 일종의 존재 이유입니다. 각 사람은 일반적으로 합창단/밴드 리더가 부르거나 연주하는 '참조' 파트를 따라 부르고, 다른 사람들은 모두 따라 부르거나 연주합니다.

부품이 참조 부품보다 얼마나 뒤처지거나 앞서 있는지 식별하려고 시도하는 것이 상당히 까다로운 것으로 판명되었기 때문에 이 문제를 올바르게 해결하는 것은 실제로 상당히 어려운 일이었습니다.



첫째, 왜 동기화되지 않습니까? Choirless와 함께 노래를 부를 때 참조 부분을 보여주므로 노래하는 사람을 보고 들을 수 있습니다.

파형을 보고 확대하면 동기화되지 않은 것이 분명할 수 있습니다.



위의 이미지에서, 그것들이 동기화되지 않았으며 빨간색 파형을 약간 앞으로 이동하면 꽤 잘 일치한다는 것이 분명합니다.

그러나 이것은 알고리즘에서 수행하기 어렵습니다! 나는 written about this before 을(를) 수행했고 video on it 을(를) 수행했습니다. 그러나 여전히 실제 테스트와 일치하는 것은 없습니다!

목소리에 동기화하는 것은 어렵지 않습니다, 드럼과 튜바? 훨씬 더 어렵습니다. 수많은 사람들이 Choirless와 모든 종류의 음성 및 악기를 테스트했습니다. 가장 최근의 테스트는 소웨토 가스펠 합창단이었습니다. 그들의 녹음 세션은 마이크와 스피커가 내장된 Android 휴대폰을 사용하고 있었기 때문에 기대만큼 잘 진행되지 않았습니다. 주요 문제는 참조 트랙의 사운드가 후속 녹음 부분으로 번지는 것입니다. 공교롭게도 그들의 참조 부분은 키보드와 일부 드럼이었습니다. 드럼 사운드는 매우 독특하고 다른 모든 부분에서 쉽게 눈에 띕니다. 그리고 훨씬 더 눈에 띄는 것은 그것이 얼마나 동기화되지 않았는지였습니다 :(

내 원래 알고리즘은 참조 및 후속 부품을 스캔하고 특정 기능을 동기화에 사용할 '랜드마크'로 추출하려고 합니다. 그런 다음 해당 랜드마크를 가져오고 반복적으로 앞뒤로 이동하여 최상의 정렬을 얻습니다.



두 신호 사이의 평균 제곱 오차(MSE)를 측정합니다.

# function to measure two waveforms with one offset by a certian amount                                                                                                                                                                       
def measure_error(x0, x1, offset):
    max_len = min(len(x0), len(x1))

    # calculate the mean squared error of the two signals                                                                                                                                                                                     
    diff = x0[:max_len] - np.roll(x1[:max_len], offset)
    err = np.sum(diff**2) / len(diff)
    return err


다른 오프셋을 통해 반복함으로써 오프셋에 대해 오류를 그릴 수 있습니다. '가장' 일치하는 항목은 해당 그래프의 최소 지점입니다.



때때로 그것은 명백할 것입니다. 그러나 꽤 자주 알고리즘은 속아서 잘못된 일치 항목을 찾습니다. 때때로 MSE를 줄이는 오디오를 정렬하는 여러 가지 '최상의' 방법이 있을 수 있습니다. 그리고 종종 그것은 틀렸습니다.

그래서 이번 주말에 나는 그것을 더 견고하게 만들기 시작했습니다. 전체 트랙을 하나로 비교하는 대신 작은 창만 여러 번 비교하는 아이디어를 생각해 냈습니다. 그래서 저는 길이 10초, 보폭 2초의 슬라이딩 윈도우를 사용합니다. 각 창에서 '최상의' 일치를 계산합니다. 최종 결과는 다음과 같은 차트입니다.



예쁜! 그러나 더 중요한 것은 각 10초 창에 대해 최상의 동기화를 보여줍니다. 최소값의 히스토그램을 플로팅하면 다음과 같은 결과를 얻습니다.



그리고 210ms가 오디오 업과 일치하는 가장 일반적인 '최상의' 오프셋임을 알 수 있습니다.

이 일을 한 후에도 나는 여전히 동기화되지 않았습니다. Audacity에서 파형을 모두 함께 보면 파형이 여전히 제대로 정렬되지 않았음을 알 수 있습니다. 더 좋지만 여전히 충분하지 않습니다.



많은 고민 끝에 문제를 찾았습니다. 나는 surfboard 이라는 훌륭한 라이브러리를 사용하고 있습니다. 특히 spectral_flux 이라는 메서드가 있습니다. 이 메서드는 매개변수hop_length_seconds를 사용하며 기본값은 0.01, 즉 10밀리초입니다. 우리가 사용하고 있는 오디오의 표준 44.1kHz 샘플 속도에서 10밀리초는 441 샘플입니다. 그러나 코드에서 it rounds that up to a power of 2 , 즉 512 . 그래서 프레임의 '최고' 오프셋을 샘플로 변환할 때 각 프레임이 441개 샘플이라고 가정했는데 실제로는 512개였습니다... 따라서 동기화가 중단되었습니다!

이제 부품이 서로 훨씬 더 동기화되었습니다.



Choirless에 대한 자세한 내용은 다음에서 확인할 수 있습니다.

https://choirless.com

좋은 웹페이지 즐겨찾기