안녕하세요. 오늘은 스펙트로그램을 통해서 해시값을 추출한 후에, 두 노래가 어느 구간에서 일치율이 높은지를 알아보는 코드를 소개하려합니다.
즉, 전체 노래가 DB에 저장되어 있고, 인식되는 노래가 DB의 어느 노래와 일치하는지, 그리고 그 노래의 어떤 부분에서 일치하는지를 확인하는 코드를 소개해드립니다. (설명을 생략하고 코드만 궁금하신 분들은 하단으로 내리시면 확인하실 수 있습니다.)
설명에 앞서 아래의 모든 내용은, Shazam의 논문에 근거하여 작성된 글을 바탕으로 작성됨을 미리 알려드립니다.
이 코드는 "Shazam"에서 오픈 소스로 공개된 코드를 기반으로 구성했습니다. 샤잠에서는 스펙트로그램을 통해서 peak point를 추출하고, 해당 peak point를 통해서 해시값을 구성합니다. 이런 해시값들을 통해서 노래의 구간을 찾는 방법입니다.
그럼 조금 더 자세히 해당 과정에 대해서 소개해드리겠습니다.
우선, 어떤 노래에 대해서 해시테이블을 어떻게 구성하는지에 대해서 먼저 알려드리겠습니다.
1. 우선 인식된 음성에 대해서 스펙트로그램을 만듭니다.
- 스펙트로그램이란 시간축과 주파수 축의 변화에 따라 진폭의 차이를 색상의 차이로 나타내는 방법을 의미합니다.
2. 해당 스펙트로그램에서의 peak point를 찾습니다.
- peak point란 어떤 영역 내에서의 스펙트로그램의 최댓값을 의미합니다.
그럼 어떻게 저희는 peak point를 찾을 수 있을까요??
바로 Maximum Filter를 이용합니다. 특정 구간에서 Maximum Filter를 씌워, 그 구간 내에 있는 값을 모두 최댓값으로 변경합니다.
그렇게 했을 때, 바뀌지 않는 부분 즉, 최대값이 peak point가 됨을 알 수 있습니다.
이 사진에서는 하얀색 점이 peak point가 됩니다.
우리가 그럼 왜 Maximum 값을 peak point로 사용하는 것일까요?? 그 이유는 인식되는 소리에 잡음이 많이 섞여있어도 peak point를
넘지 않는 한은 노래 인식에 크게 영향을 줄 수 없기 때문입니다!
3. peak point끼리만 모아놓은 Constellation Map(별자리 지도)을 만듭니다.
그렇게 되면 아래와 같이 나타나집니다.
이제 이렇게 형성된 peak point들로 해시값을 구성합니다.
4. anchor point를 기준으로 target zone을 생성하여 target zone 내에 있는 peak point들로 해시값을 구합니다. 이러한 해시값이 여러개가 존재하므로 우리는 하나의 anchor point에 대해서 해시 테이블을 갖게됩니다.
그럼 이제 해시테이블을 통해서 노래들이 인식되는지를 알아봅시다.
우리는 샘플이 주어졌을 때, 기존에 저장되어 있는 DB에 있는 해시값들과 비교를 하게 될 것입니다. 이 때, 샘플의 해시테이블을 DB에 있는 모든 해시 테이블에 대해서 슬라이딩하면서 일치율을 확인합니다. 이 때, 이 두 해시테이블 사이에는 time offset. 즉 시간정보만을 계산합니다.
그 이유는, 어떤 음성에 대해서 (비슷한 peak point끼리가) 동일한 시간 차를 갖고있다면 그것이 같은 노래일 확률이 높기 때문입니다.
이렇게 보니, 일치하는 해시들끼리의 시간 차이를 어떻게 이용하는지 아시겠나요??
이렇게 계산된 시간차이를 histogram으로 나타냈을 때, 어느 threshold 이상인 값이 존재한다면 해당 노래와 일치한다고 할 수 있게 됩니다.
이제 어느정도 눈치 채셨겠지만, 저는 이 코드에서 time offset을 이용했습니다. 전체 음성에 대해서 sample의 음성이 어디에서 시작하는지 알 수 있게 된 것이죠.
코드는 저의 깃헙을 통해서 확인하실 수 있습니다.
(프로젝트 목적으로 만든 것이라 제 목적에 맞게 재사용하시면 되겠습니다)
https://github.com/shxnzxxn/FindMusicStartTIme
'Python' 카테고리의 다른 글
[파이썬/Python] 도커 이미지를 생성하고 배포해보자 (0) | 2023.08.24 |
---|---|
[파이썬/Python] 네이버 검색 API를 이용해 관련 이미지 불러오기 (0) | 2023.08.16 |
[Python/파이썬] 목소리와 음악을 구분하자 - 2편(with Resnet) (0) | 2023.08.01 |
[Python/파이썬] 목소리와 음악을 구분하자 - 1편(with Spleeter) (0) | 2023.07.25 |
[파이썬/Python] 유튜브 API를 사용하여 원하는 검색 결과 불러오기 (0) | 2023.07.02 |