뒤로가기back

소리 만들어주는 AI는 없나요? : 사운드와 생성 AI

2023.04.18 by Keunwoo Choi

ChatGPT가 불러온 생성 AI 돌풍

(Writer: Keunwoo Choi)

ChatGPT 만큼 사람들의 삶에 빠르게 스며든 기술이 또 있었을까 싶을 정도로 생성 AI에 대한 관심이 뜨겁습니다. 마치 스마트폰의 초창기를 보는 듯, 새로운 패러다임이 찾아오는 것이 아닐까 하는 기대까지 하게 됩니다. 이처럼 ChatGPT에서 시작된 생성 AI 열풍이 글쓰기가 아닌 미술, 음악과 같은 다른 콘텐츠 영역까지 그 영향력을 확장하고 있음을 실감합니다.

 

사운드 분야의 생성 AI

 

사운드 분야도 예외는 아닌데요, 목소리를 AI로 합성하거나 음악을 작곡하는 등의 기술은 이미 많은 관심을 받아왔습니다. 하지만, 우리 주변에서 들려오는 소리를 생각해보면 음성이나 음악의 비중은 사실 크지 않습니다. 오히려 키보드 치는 소리, 옆 사람의 숨소리, 냉장고 소음과 같이 작은 소리가 모여 우리를 둘러싼 소리 환경을 만들고 있습니다. 결국 이러한 소리들이 없으면 아무리 잘 생성된 음성과 음악이라도 충분히 그 빛을 발할 수 없다는 것이기도 합니다.

 

 

이렇게 중요하다면, 그동안 우리 주변의 소리(원활한 표현을 위해 ‘효과음(Foley Sound)’이라고 칭하겠습니다)를 만드는 AI가 없었던 이유는 무엇일까요? 답은 간단합니다. 이것이 가장 난이도 높은 일이기 때문입니다. 세상의 모든 소리를 만들기 위해서는 세상의 모든 소리에 대응하는 소리의 데이터를 갖추고 있어야 합니다. 그만큼 고려해야하는 변수도 많을 수 밖에 없습니다. 

 

하지만 이런 어려움에 굴복할 가우디오랩이 아닙니다.  세상의 모든 소리를 만들기 위해서는 세상의 모든 소리에 대응하는 소리의 데이터를 갖추고 있어야 합니다. 그만큼 고려해야하는 변수도 많을 수 밖에 없습니다. 

 

긴 말 할 것 없이 데모부터 들어보시죠.

 

AI가 만든 소리 VS 실제 소리

 

 

여러분은 몇 개의 정답을 맞추셨나요?
들으신 것 처럼 AI가 생성한 사운드의 수준은 실제 녹음된 사운드에 버금갈 정도로 많은 발전을 이루었습니다.

이젠 본격적으로 이렇게 놀랄 정도로 사실적인 사운드를 만들기 위한 AI 기술의 원리를 더 자세히 들여다 보겠습니다.

 

소리를 AI로 만듭니다.

 

소리를 표현하는 방식: 파형 그래프

 

뜬금없어 보이지만 AI로 소리를 만들어내는 과정을 설명하기 위해서는 소리를 표현하는 방식부터 짚고 넘어가야 합니다. 이런 이미지는 아마 많이 보셨을 것 같습니다.

 

 

소리의 파형을 시간대별로 나타낸 그래프로, 언제 어느 정도 크기의 소리가 나는지는 짐작할 수 있지만 이 소리가 어떤 특성을 가졌는지까지 파악할 수는 없습니다.

 

소리를 표현하는 방식: 스펙트로그램 (Spectrogram)

 

이러한 한계를 극복하고자 만들어진 것이 스펙트로그램입니다.

 

 

한눈에 봐도 앞선 그래프보다 많은 정보를 담고 있는 것처럼 보입니다.

 

자세히 살펴보면, x축은 시간, y축은 주파수, 그리고 각 픽셀의 색깔은 소리의 크기를 나타냅니다. 즉, 스펙트로그램은 어떤 소리에 대한 모든 정보를 담고 있는, 마치 소리의 DNA와 같은 존재라고 할 수 있습니다. 그렇기에 스펙트로그램을 오디오 신호로 변환할 수 있는 도구만 있다면, 소리를 만드는 것은 곧 이미지를 만드는 작업과 동일하다고 볼 수 있는것이죠. 이렇게 되면 많은 일이 간단해집니다. Open AI의 DALL-E 2 에서 사용된 것과 같은 디퓨전 기반 이미지 생성 알고리즘을 그대로 사용할 수 있기 때문입니다.

 

자, 이제 스펙트로그램을 설명한 이유를 아시겠나요? 이젠 정말로 소리를 만드는 과정을 자세히 살펴보겠습니다.

 

AI로 소리 만들기, 이렇게 합니다.

 

 

1단계: 텍스트 입력에서 작은 스펙트로그램 생성하기

 

첫 단계에서는 만들고 싶은 소리에 대한 입력을 처리합니다. ‘우렁찬 호랑이의 포효’라는 텍스트를 입력으로 받으면, 디퓨전 모델이 랜덤한 노이즈에서 작은 사이즈의 스펙트로그램을 만들어냅니다.


이 때 만들어진 스펙트로그램은 16x64 픽셀로 이루어진 작은 이미지인데요, 각 숫자는 16개의 주파수 밴드와 64개의 프레임을 나타냅니다. 얼핏 보면 이걸로 뭘 할 수 있겠냐는 의문이 드시겠지만 작은 스펙트로그램도 소리에 대한 상당한 정보를 담고 있습니다.


2단계: 슈퍼 레졸루션(Super Resolution)

 

그 이후에는 이런 작은 이미지를 점차 개선해 나가는 ‘슈퍼 레졸루션’ 단계를 거칩니다. 디퓨전 모델이 여러 단계를 거쳐 해상도를 개선하면 위에서 본 것과 같은 명료한 형태의 스펙트로그램이 완성됩니다.


3단계: 보코더 (Vocoder)

 

이제 마지막 단계로 스펙트로그램을 오디오 신호로 변환해주기만 하면 됩니다. 이 때 사용되는 것이 보코더 입니다. 하지만 시중에 오픈소스로 공개되어있는 대부분의 보코더는 음성 신호를 학습하여 제작되었기 때문에 다양한 소리에 대응해야 하는 지금과 같은 시나리오에 적합하지 않다는 점이 문제였습니다. 이에 가우디오랩은 내부 데이터로 학습시킨 세계 최고 수준의 보코더를 개발했습니다. 2023년 상반기 중에는 이러한 보코더를 오픈 소스로 공개할 계획도 가지고 있습니다.

 

사운드 생성 AI, 가우디오랩이 잘 만들 수 밖에 없는 이유

 

사운드 생성 AI 개발, 왜 어려울까요?

 

얼핏 보면 쉬워보이는 과정이지만, 마침내 그럴듯한 소리가 나오기까지 정말 많은 장애물을 거쳐야 했습니다. AI는 도구일 뿐, 실제로는 ‘오디오를 잘 해야만’ 풀 수 있는 문제이기 때문입니다.

 

일단 오디오 데이터는 그 크기가 남다릅니다. ChatGPT가 학습한 데이터는 약 570GB, 지난 10년간 딥러닝 발전을 이끌어온 이미지넷이 다루는 데이터는 약 1,000개의 카테고리에서 150GB 정도입니다. 하지만, 가우디오랩이 다뤄야 했던 데이터는 약 10TB에 달합니다. 이를 시간으로 바꿔보면 약 1만 시간 분량의 데이터입니다. 이것들을 수집하고 관리하는 데만 해도 상당한 노하우가 필요했을 뿐만 아니라, 학습을 위해 오디오 데이터를 불러오는 시간(i/o 오버헤드)를 줄이는 것도 큰 과제였습니다.

 

어렵게 학습을 시키더라도 오디오의 경우 AI 모델을 평가하는 것 자체가 어렵습니다. 생성된 시간만큼 들어봐야 하기 때문에 평가에 필요한 시간이 클 뿐더러, 청취 환경에도 큰 영향을 받기 때문입니다. 

 

사운드 생성 AI도 전문가가 만들면 다릅니다.

 

다행히 가우디오랩에는 프라운호퍼, 삼성전자, 스포티파이 등 글로벌 레벨의 기업에서 풍부한 오디오 연구 경험을 쌓은 음향공학 분야의 석박사급 전문가들이 존재하고, 그들이 직접 청취 평가에 참여하고 있습니다. 그렇기 때문에 그들의 소위 ‘골든 이어’ 로서의 예민함, 좋은 소리에 대한 집착, 그리고 뛰어난 전문성이 그대로 AI 성능에도 반영되고, 이것이 세계 최고 수준의 생성 AI를 만들 수 있는 가우디오랩만의 따라올 수 없는 강점이 되고 있습니다.

 

사운드 생성 AI, 이렇게 발전합니다

 

가우디오랩이 그리는 미래는 메타버스에 있습니다. 사운드 생성 AI를 만들게 된 것도 소리 없는 메타버스에 소리를 채우기 위함이었습니다. 물론 지금까지 만들어진 모델의 성능이 뛰어나지만, 세상의 모든 소리를 담으려면 가야할 길이 꽤 많이 남았습니다.

 

Dcase participation

 

DCASE 2023 이벤트 참여 소식 

 

그래서 가우디오랩은 이렇게 어려운 문제를 해결하기 위해 DCASE 라는 이벤트에 Lead Organizer로 참여합니다! 세계 곳곳에서 모인 최고 수준의 오디오 연구자들과 함께 더 좋은 소리를 만드는 여정을 응원하고, 또 가우디오랩이 만들어낸 사운드가 얼마나 좋은지를 널리 알리기 위한 목적입니다. 

 

DCASE의 결과는 5월에 발표됩니다. 과연 이렇게나 뛰어난 가우디오랩의 사운드 생성 AI가 세계에서는 어떤 평가를 받게 될까요? 좋은 소식으로 여러분을 찾아뵐 수 있도록 많은 응원 부탁드립니다! 

 

곧 AI로 만든 소리도 함께 공개할 예정이니 많은 관심 부탁드려요! 

 

pre-image
공간음향의 퀄리티를 높여주는 Motion-to-sound 레이턴시 측정(Motion to Sound Latency Measurement)

공간음향의 퀄리티를 높여주는 Motion-to-sound 레이턴시 측정(Motion to Sound Latency Measurement) (Writer: James Seo)   [Introduction: 들어가며]   Spatial Audio(공간 음향)는 사용자가 헤드폰이나 이어폰을 통해 듣는 소리를 사용자의 위치와 방향에 맞게 재현하여, 소리가 실제와 똑같은 듯 자연스러운 착각을 주는 오디오 렌더링 기술입니다. Spatial Audio의 품질과 성능에는 공간과 방향의 특성을 렌더링하는 음질 뿐만 아니라 사용자의 움직임으로부터 렌더링되어 소리가 재생되는 데에 소요되는 시간(motion-to-sound latency) 역시 큰 영향을 끼치게 됩니다.   -Motion-to-sound latency가 너무 길게 되면, 시각을 비롯한 현실의 자극체계와 청각 경험의 불일치로 인해 사용자는 몰입감을 잃게 될 뿐만 아니라 심한 경우 멀미가 발생하기도 합니다. 이것은 VR 기기를 사용하였을 때, 시각에서 발생하는 멀미 현상의 원인인, motion-to-photon latency와 동일한 개념입니다.   Spatial audio에 대한 고객 경험을 평가하는 데에는 이러한 motion-to-sound latency의 측정이 필수적인데, 이 측정은 단순한 작업은 아닙니다. 전체적인 motion-to-sound latency는 Figure 1과 같이 나누어서 생각해 볼 수 있습니다. (1) 사용자의 motion을 인지하는 motion-to-sensor latency, (2) sensor가 인지한 움직임이 오디오 프로세서로 전달되는 sensor-to-processor latency, (3) processor에서 rendering 과정에서 발생되는rendering latency, (4) rendering 된 신호가 Bluetooth 등의 통신 경로를 통해 전달되는 과정에서 발생하는 communication latency등이 있는데, 이를 독립적으로 측정하는 것은 쉽지 않고, 특히 시중에 판매되고 있는 완제품의 경우 내부 모듈을 Breakdown하여 측정하는 것은 불가능하다는 문제점이 있습니다.   이 글에서는 motion-to-sound latency를 좀 더 정확하게 측정하기 위한 방법을 설명합니다. 어렵지 않은 내용이니 천천히 따라오시면 잘 이해하실 수 있으리라 생각합니다.   Figure 1 Breakdown of Motion-to-Sound Latency   [Measurement Hypothesis: Binaural Rendering & Crosstalk Cancellation]   앞서 말씀드린 것과 같이 Spatial Audio 는 어떤 공간안에 존재하는 음원을 해당 음원과 청취자의 상대적인 위치에 맞게 렌더링 하는 Binaural Rendering 기술을 활용하고 있습니다. 즉, 음원의 위치 뿐만 아니라 음원이 존재하고 있는 공간의 느낌까지도 함께 재현하기 위한 기술이죠.   일반적으로 Binaural Rendering 을 수행하기 위해서는 BRIRs(Binaural Room Impulse Responses), HRIRs(Head-Related Impulse Responses)과 같은 Binaural Filter를 사용합니다.   Figure 2 HRIR(좌) vs. BRIR(우)(좌) 청취룸 특성 없는 음원과 청취자와의 관계 / (우) 청취룸 특성을 고려한 음원과 청취자와의 관계   Binaural Filter의 기본 개념은 특정 ‘위치’에 있는 음원으로부터 발생한 소리가 좌/우 측 귀에 들어오는 소리의 특성 변화를 정의하는 필터입니다. 따라서, 이 Binaural Filter는 거리, 수평각, 수직각에 대한 함수로 정의할 수 있죠. Binaural 필터를 정의함에 있어서 반사음 성분들에 의한 공간적 특성을 반영하였는지(BRIR) 아니면 음원과 사용자(의 양 귀)와의 관계만을 표현한 것인지(HRIR)에 따라서 달라지게 됩니다.  BRIR의 경우 공간에서 발생하는 직접음 및 반사음까지 모두 Binaural Filter의 형태로 나타낸 것이고, HRIR은 반사음은 제외하고 직접음만을 고려한 Binaural Filter입니다. 당연히 BRIR 이 HRIR 보다 훨씬 긴 응답 길이를 갖고 있습니다.   일반적으로 Spatial audio는 HRIR보다는 BRIR을 사용하고 있어 본 글에서는 BRIR을 기준으로 설명 드립니다.   (a) (b) Figure 3 An Example of Impulse Responses of (a) HRIR and (b) BRIR   우선 두 개의 가상 음원 위치를 정할 필요가 있는데요. 이 때는 median plane(정중면; 좌우균등하게 나누는 면을 의미; 본 맥락에서는 사용자를 중심으로 좌우를 나누는 평면을 의미)을 기준으로 각각 다른 편에 속해 있는 두 개의 지점을 택하는 게 더 좋겠습니다. 이유는 이 측정 방법은 crosstalk cancellation 현상을 이용하여 측정하는 방법이기 때문입니다. (앗, Crosstalk cancellation 현상이 무엇이냐고요? 이 글을 끝까지 읽다보면 자연스레 알 수 있답니다!)   Figure 4 An example of virtual speakers positions for M2S measurement   Figure 4처럼 median plane을 중심으로 서로 다른 편에 있는 두 개의 가상 음원의 위치가 결정되면, 각 음원으로부터 양쪽 귀까지의 전달함수, 즉 BRIR 을 두 세트를 측정할 수 있습니다. 이 세트를 [BRIR_LL, BRIR_LR], [BRIR_RL, BRIR_RR] 로 표시합니다. 각 세트에서 ‘_’뒤의 첫번째 알파벳은 음원의 위치(왼쪽 또는 오른쪽), 두번째 알파벳은 귀의 위치(왼쪽 귀 또는 오른쪽 귀)를 의미합니다. 즉, BRIR_LL은 왼쪽 스피커에서 발생한 소리가 공간 내에서 전파되다가 왼쪽 귀에 도달할 때까지의 충격응답을 의미하겠죠?   이렇게 BRIR세트를 구하면 어떤 단일 주파수 신호에 대해서 한쪽 귀에 들어오는 동측 음원으로부터 전달되는 신호(Ipsilateral Ear Input Signal)와 대측 음원으로부터 전달되는 신호 (Contralateral Ear Input Signal)의 크기 차이와 위상 차이를 구할 수 있습니다. 좀 더 풀어서 얘기하면, 왼쪽 스피커에서 왼쪽 귀로 재생되는 소리와 오른쪽 스피커에서 왼쪽귀로 재생되는 소리의 크기 차이와 위상 차이를 구할 수 있다는 이야기지요.   이러한 Ipsilateral Ear Input Signal과 Contralateral Ear Input Signal의 특정 주파수에 대한 크기 차이와 위상 차이를 계산해서 역함수 형태로 활용하여 오른쪽 가상 음원의 신호를 변경하면, 왼쪽 귀에는 crosstalk으로 인해 소리가 완전히 없어지거나 오른쪽에 비해 아주 작은 소리가 재생되도록 만들 수 있습니다. 거의 안 들리는 소리가 만들어 지는 것이죠. 이 크기 차이와 위상 차이는 BRIR의 주파수 영역에서의 표현인 BRTF(Binaural Room Transfer Function)의 크기 응답과 위상 응답으로부터 계산할 수도 있고, 특정 주파수를 이용하여 측정해서 획득할 수도 있습니다.   예를 들어 크기 차이와 위상 차이가 반영되지 않은 입력 신호는 아래와 같습니다.   Figure 5 Uncontrolled input signal for left and right virtual speakers   위 Figure 5에서 위쪽이 가상 채널 중 왼쪽 채널의 입력 신호, 아래쪽이 가상 채널 중 오른쪽 채널의 입력 신호입니다. 완전히 동일한 신호입니다. 그런데 BRIR 로부터 왼쪽 채널과 오른쪽 채널로부터 왼쪽귀까지 해당 주파수의 크기차와 위상차를 구해서 최종 왼쪽 귀 입력 신호가 상쇄되도록 오른쪽 가상 채널 신호의 크기와 위상을 변경한다면? 입력 신호는 Figure 6과 같게 됩니다. Figure 6 Controlled input signal for left and right virtual speakers   그럼, Figure 6과 같은 입력으로 재생했을 때 왼쪽귀의 입력 신호는 어떻게 될까요? 결과는 아래 Figure 7과 같습니다. Figure 7 An example of left ear input signal for uncontrolled and controlled input signal   Figure 7에서 실선은 크기/위상차 조절을 하지 않고 양쪽 가상 채널에 동일한 신호를 렌더링 했을 때의 왼쪽 귀 입력 신호, 점선은 크기 위상차 조절한 신호를 오른쪽 가상 채널 신호에 반영했을 때 왼쪽 귀 입력 신호입니다. 확연하게 크기가 줄어든 것을 확인할 수 있는데요. 이러한 방법을  “crosstalk cancellation” 이라고 부릅니다. 크기/위상차를 절묘하게 변형시켜 동측에서 전달된 소리와 대측에서 전달된 소리가 상쇄되도록 만드는 방법을 의미하죠. 이 crosstalk cancellation 은 크기와 위상차가 딱 맞아떨어졌을 때 발생하고 둘 중 하나라도 조건에 맞지 않으면 오히려 출력 신호가 더 커지기도 합니다.   Figure 6과 같은 입력 신호를 렌더링 하면서 정면을 가만히 바라보고 있으면 왼쪽 귀로 들어오는 신호는 들리지 않거나 들린다고 하더라도 아주 작은 소리로 들리게 될 겁니다. BRIR에는 뒤쪽 reverb 에 해당하는 필터가 꼬리를 형성하고 있기 때문에 정확한 크기/위상차를 구했다고 하더라도 실제 오차가 다소 존재할 수 있습니다. 다만, 이 때 나는 소리가 제일 작은 크기의 소리인 것은 맞다고 말씀드릴 수 있어요.   [Measurement Method & Results]   Figure 8 Block diagram for M2S measurement   Figure 8은 M2S(Motion-to-Sound) Latency를 측정하기 위한 과정을 그림으로 나타낸 것입니다. 앞서 설명한 내용은 M2S Latency를 측정하기 위한 입력 신호를 어떻게 생성할 수 있는지에 관한 것이고 위 그림의 [input signal control stage] 부분에 해당하겠네요. 그렇게 생성한 신호가 smsr입니다. 그럼 이제 실제 M2S Latency 측정을 해 보죠.   Spatial Audio Renderer에는 우리가 생성한 입력신호  smsr 이 입력되고, TWS(True Wireless Stereo)나 그 외의 IMU가 포함되어 있는 장치에서 움직임에 대한 정보를 전달받아, 그에 맞게 spatial audio rendering을 수행합니다.   우선 우리는 여기서 TWS에서 사용자의 움직임을 감지하여 해당 정보를 전달한다고 가정합니다. 사용자 움직임이 없는 경우, 출력된 바이노럴 신호의 왼쪽 또는 오른쪽 귀의 입력 신호는 crosstalk cancellation 때문에 소리가 나지 않거나 상대적으로 매우 작은 소리를 재생하고 있는 상황입니다. t=t0 순간에 모터 등을 이용하여 TWS를 회전시키면 TWS 는 그 움직임(실제로는 사용자의 움직임)을 감지하여 그에 맞는 movement 정보를 Spatial Audio Renderer로 전송하고, Spatial Audio Renderer는 그 정보에 맞게 렌더링을 하여 출력 신호를 생성하여 TWS를 이용해 재생하게 됩니다. 이렇게 재생된 소리를 획득하면 Crosstalk cancellation 조건이 깨지면서 렌더링 된 신호의 envelope의 변화를 볼 수 있고, 그로부터 M2S Latency를 측정할 수 있죠.   다만, 환경적 제약 때문에 Spatial Audio Renderer 의 출력신호를 직접 획득할 수 없는 상황이 있을 수도 있습니다. 그런 경우, external microphone 등을 통해 신호를 녹음하여 획득하여 사용합니다. 이 때 외부 잡음 등의 영향이 있을 수 있는데, 특정 주파수를 사용한 경우 대역통과필터 (Bandpass Filter) 를 이용하여 잡음을 제거할 수 있습니다. 아래 그림을 통해 조금 더 자세히 설명해 드릴게요. Figure 9 Recorded signal before(upper) and after(lower) bandpass filtering   Figure 9의 위쪽 그림이 원래 측정 신호입니다. Figure 9의 ‘Moving Start’ 시점이 Figure 8에서 t0에 해당합니다. 즉,  ‘Moving Start’ 로 표시된 이전 구간은 정지되어 있는 상태입니다. 정지 상태에서는 Crosstalk Cancellation 덕분에 해당 방향의 Ear Input Signal은 상쇄되어 거의 들리지 않습니다. ‘Moving Start’ 순간부터 마이크로폰에는 모터가 동작하는 노이즈와 함께 실제 렌더링 되는 신호도 녹음이 될텐데요, 위쪽 그림에서는 렌더링 되는 신호는 크기가 작고 상대적으로 노이즈의 크기가 커서 언제부터 crosstalk cancellation 이 사라지는지 알 수가 없습니다. 이 실험에서 저희는 입력 신호로 500 Hz 의 pure tone 을 사용했습니다. 즉, 우리는 500Hz신호만 보면 되니, 위쪽 컬럼의 신호를 fc=500Hz 인 bandpass filter를 통과시키면 모터 구동음은 깨끗하게 없앨 수 있습니다. (윗 문단에서 언급한 대역통과필터를 이용한 잡음 제거) 그 결과가 Figure 9의 아래쪽 그림이 되는 것이고요. 움직이기 시작한 후부터 일정 시간이 지나면서부터 crosstalk cancellation 조건이 깨지면서 녹음되는 신호의 envelope이 커지는 걸 확인할 수 있습니다. 즉, crosstalk cancellation disappear 라고 표시된 시점이 Figure 8의 t1 에 해당하겠네요. 따라서, M2S Latency는 t1-t0 라고 계산할 수 있다는 것을 알 수 있습니다.   Envelope이 증가한 시점을 찾는 것은 여러가지 방법이 있겠습니다. 단순히 녹음된 신호의 샘플값이 커지는 구간을 찾을 수도 있긴 하겠습니다만, 너무 부정확한 방법이죠. 혹시나 perfect cancellation이 되지 않는다면 이 샘플값은 cancellation이 일어나고 있는 중에도 계속 변하게 될 것입니다. 그래서 개별 샘플 값을 이용하기 보다는 녹음된 신호를 일정 길이의  구간으로 나눈 후, 각 구간에 포함된  sample 값들의 variance를 구해서 사용하는 방법을 생각해볼 수 있습니다. Envelope 을 구하기 위해  variance 값을 계산한다면 각 구간의 길이를 선택하는 것이 중요합니다. 이 시간 구간을 짧게 잡으면 시간 영역에서 time precision은 높아질 수 있습니다만, 입력 신호 주파수의 주기보다는 길어야 합니다. 즉, 각 구간의 최소 길이는 입력 신호 주파수의 주기보다는 길어야 합니다. 위의 예시에서는 500Hz를 입력 신호로 사용하였고, 따라서 적어도 우리는 envelope의 변화량을 얻기 위해서는 2ms 이상의 시간 구간을 잡아야 한다는 의미죠. 즉, 500Hz 신호를 입력으로 사용한 경우 최대 precision은 2 ms 입니다. 해상도를 높이고 싶으면 더 높은 주파수의 입력 신호를 사용해도 괜찮습니다. 다만 너무 높은 주파수의 입력 신호를 사용할 경우 필터로부터 계산할 수 있는 크기/위상차의 오차 범위가 다소 높아질 수 있는 위험도 있으니 조심해야 할 필요는 있겠지요! 그 이외에 측정된 신호로부터 sparse envelope 을 추출하고 envelope의 실제 slope 를 계산해서 slope 가 급격히 변하는 지점을 기준으로 M2S Latency를 측정할 수도 있습니다. 측정 환경과 녹음 결과에 따라 이는 선택적으로 변경해서 사용할 수 있겠습니다.   결국 Figure 9에서처럼 원래 녹음된 신호와 fc=500Hz로 Bandpass filtering 된 신호를 기반으로 우리는 M2S Latency를 측정할 수 있습니다. 이 latency는 앞서 도면으로 그렸던 모든 관련된 정보가 오가는 과정에서 발생하는 latency가 포함된 값입니다. 따라서 이 latency가 실제 사용자가 경험하게 되는 latency가 됩니다.   [그래서 실제로 Latency를 측정해보니…]   요즘 출시되는 TWS 들은 공간음향 기능이 탑재되어 소리에 공간감을 더함과 동시에 사용자의 고개 움직임 등에 반응하는 렌더링 기능들을 제공하죠. 아시다시피 가우디오랩은 공간음향 기술의 원조이자 최고의 기술력을 자랑하는 회사인만큼, 각 제품들이 사용자의 움직임에 얼마나 빨리 반응해 좋은 퀄리티를 제공할 수 있을지를 파악하고자 여러 제조사의 TWS를 대상으로 M2S Latency 를 측정하였습니다. 측정치는 최소 10회의 측정을 기반으로 평균값을 구한 것이고, 따라서 그 표준 편차도 함께 기재해 봤습니다.   위에서 설명드린 측정방법을 활용해 다양한 TWS의 M2S Latency 를 측정해보았더니, 예시값은 아래 표 1과 같음을 알 수 있었습니다.   <Table 1 M2S latencies for different TWS [unit: ms]> 측정 결과는 놀라웠는데요. 가우디오랩의 기술이 (아직은 Mock-up 수준이라고 해도) 월등히 낮은 Motion-to-Sound Latency를 기록하고 있었습니다! 그 이유는 가우디오랩의 Spatial Audio Mock-up이 세계 최고의 Spatial Audio렌더링 최적화 기술로 TWS 위에서 구동되는 방식을 바탕으로 만들어졌고, 이는 기존의 다른 주요 TWS들이 채택하여 사용하고 있는 스마트폰 렌더링 방식에 반드시 필요한 Bluetooth Communication Latency를 제거할 수 있기에 얻어진 결과라고 말씀드릴 수 있겠습니다.   글을 시작하면서, Spatial Audio의 전체적인 품질은 공간과 방향의 특성을 렌더링하는 음질 뿐만 아니라 사용자의 움직임으로부터 렌더링되어 소리가 재현되는 데에 소요되는 시간 (motion-to-sound latency)에 따라 결정된다고 말씀드렸던 것을 기억하시나요?   공간음향의 품질을 높여주는 Motion-to-sound latency를 측정하는 방법을 설명 드리고자 시작한 이 글을 통해 가우디오랩의 기술력이 압도적인 뛰어난 수치들을 기록하고 있음까지 확인할 수 있었습니다.   Latency가 최고 수준인 것은 알겠는데, 그렇다면 과연 음질은 어떻게 되는지 궁금하실텐데요. 다음 글에서는 latency에 이어 놀라운 결과를 보여준 음질 평가 실험과 그 결과에 대해서 사운드 샘플과 함께 공개할 예정이니 Stay tuned~!   아! 가우디오랩이 2023년 CES에서 혁신상 2관왕을 차지했다더니, 역시 그럴만한 결과네요! ㅎㅎㅎ     ------   [1] iPhone 11과 Airpods Pro로 구성된 렌더링에 대한 측정치임. 실제 렌더링은 iPhone에서 일어나고Phone-TWS간 통신 지연에 의한 지연이 큰 구조   [2] Galaxy Flip4와 Galaxy Buds 2 Pro로 구성된 렌더링에 대한 측정치임. 실제 렌더링은 Galaxy에서 일어나고Phone-TWS간 통신 지연에 의한 지연이 큰 구조   [3] iPhone11 과 가우디오랩에서 제작한TWS Chipset 위에 구현하여, 통신 지연을 제거한 목업의 측정 결과. iPhone은 소스 기기로 사용되고 Spatial Audio Rendering은 TWS 에서 수행.    

2023.04.07
after-image
으라차차! 막내 개발자 Asher의 AI Layer 최적화 구현기

으라차차! 막내 개발자 Asher의 AI Layer 최적화 구현기 (Writer: Asher Kim)     AI가 이렇게나 가까이 우리들의 피부에 닿아있던 적이 있었을까 싶을 정도로 최근 AI의 사용이 점점 더 대중화되고 있습니다. 매일 쏟아져 나오는 뉴스만 봐도 알 수 있죠. 지난 포스팅(소리 만들어주는 AI는 없나요? : 사운드와 생성 AI)을 통해 소개해드렸듯, 가우디오랩에서도 여러 AI 제품들을 준비하고 있는데요! 저는 이번 글을 통해 가우디오랩이 AI 오디오 제품을 연산 측면에서 어떻게 최적화해나갔는지, 그 좌충우돌 과정을 간단히 소개해드리려고 합니다.   오디오에 AI 적용하기   AI는 사람이 직접 알고리즘을 작성하기 어려운 문제를 쉽게 해결해 줍니다. 소리를 듣고 악기 별로 음원을 분리하거나, 주어진 키워드에 맞는 소리를 생성하는 건, 아무래도 그 과정을 표현하기 쉽지 않아보이는데요. 가우디오랩의 AI 제품들은 이러한 어려운 문제들을 데이터에 기반해 자동으로 학습하고 패턴을 파악하여 해결합니다. 그럼 본격적인 내용에 들어가기에 앞서서, 가우디오랩의 AI가 얼마나 잘 문제들을 해결했는지, 한 번 확인해 볼까요? ▶︎▶︎▶︎ [데모 먼저 확인하고 오기]   성능은 중요합니다   가우디오랩의 오디오 제품은 크게 온라인 방식과 오프라인 방식으로 나눌 수 있습니다. 온라인은 서버에서 연산해서 사용자에게 보내는 방식이고, 오프라인은 사용자의 컴퓨터나 핸드폰, 이어폰 등에서 연산하는 방식입니다. 후자는 엣지 컴퓨팅이라고도 합니다.   온라인 방식은 주로 큰 모델을 제품화할 때 사용됩니다. 그렇기 때문에 더 저렴하면서도 안정적인 서비스를 제공하기 위해서는 최적화를 통해 서버 비용을 낮추고 수행 시간을 줄이는 것이 중요합니다. 한편, 오프라인 방식은 주로 작은 모델을 제품화할 때 사용되는데, 특히 실시간 처리가 요구되는 경우가 많습니다. 디바이스에서 수행중인 다른 작업들을 최대한 방해하지 않으면서 실시간 처리가 가능하게 하기 위해서는, 역시나 최적화를 통해 연산량 및 수행 시간을 줄여야 합니다.   결론적으로, 최적화 과정은 오디오 제품을 만들 때, 특히 AI를 사용하는 데 있어 필수적인 부분입니다. 아래에서는 가우디오랩이 세계 최고 수준의 성능을 자랑하는 AI 오디오 제품을 개발한 과정을 소개합니다.     세계 최고 성능을 자랑하는 가우디오랩의 AI 음원분리 기술!     항상 최적화가 필요한 것은 아닙니다   그러나 모든 단계에서 최적화가 중요한 것은 아닙니다. 최적화를 마쳤는데 모델이 수정될 수도 있고, 들인 시간에 비해 이득이 별로 없을 수도 있습니다. 그리고 이른 단계에서부터 최적화를 생각하다가는, 자칫 중요한 로직에 집중하지 못하게 될 수도 있죠. 그러므로 팀 (또는 회사) 내에서 최적화에 대한 합의가 이루어지는 것이 중요합니다. 언제, 얼마나 시간을 쓸지, 어떤 최적화를 수행할지 등에 대해서요.   가우디오랩은 비전에 대한 동기화만 이루어져 있다면 누구나 주도적으로 업무를 만들어서 수행할 수 있는 회사이기 때문에, 저는 최고의 제품을 만들기 위해서는 최적화가 필수적임을 팀 내에 설득했고, 모델 개발이 완료될때 쯤부터 연산 최적화 업무를 시작할 수 있게 되었습니다. 최고의 효율을 내기 위해 생각과 일정을 공유하고 협의하며 결정된 순간이었죠.   최적화를 해봅시다   AI 제품의 최적화는 크게 모델 경량화와 연산 최적화로 나눌 수 있습니다. 모델 경량화는 원본과 의미는 비슷하지만 연산의 수는 적은 모델로 갈음하는 것이고, 연산 최적화는 동일한 연산을 더 빠르게 수행하는 것입니다. 이 글에서는 GSEP-LD의 연산 최적화를 위해 저와 저희 팀이 한 삽질노력들을 설명해 보겠습니다.   측정하세요!   본격적으로 최적화를 논하기 전에, 측정의 중요성은 아무리 강조해도 모자라지 않습니다. 암달의 법칙에 따라 우리는 가장 많은 시간 비중을 차지하는 코드부터 최적화해야 합니다. 그런데 성능에는 아주 다양한 요소가 영향을 주기 때문에, 성능을 예측하는 것은 커녕, 올바르게 성능을 측정하는 것조차 무척 어렵습니다. 이에 대해서는 아래의 두 영상에 잘 설명되어 있습니다.   ·       CppCon 2015: Chandler Carruth "Tuning C++: Benchmarks, and CPUs, and Compilers! Oh My!" ·       CppCon 2015: Bryce Adelstein-Lelbach "Benchmarking C++ Code"   나아가 측정 결과를 잘 해석하는 것도 중요합니다. 평균과 중앙값을 통해 전체적인 추이를 알 수 있고, 다른 코드와 비교할 때는 Student's t-test 등의 방법을 사용해 유의미한 차이가 나고 있는지 검증할 수 있습니다. 또한 실시간 오디오 처리라면 하위 1%의 성능도 중요하게 봐야 합니다. 잠깐이라도 실시간을 맞추지 못한다면 바로 소리가 끊기기 때문입니다.   다른 프레임워크 사용하기   PyTorch는 머신러닝 모델의 연구 과정에서 주로 사용하는 프레임워크입니다. 사용이 편리하다는 장점이 있지만, 경우에 따라 Inference 성능이 다른 프레임워크에 비해 부족할 수 있습니다. GSEP-LD PyTorch 버전은 RTF 0.65 수준이었는데, 이 정도면 다른 프로그램이 동시에 실행중이거나 성능이 좋지 않은 프로세서를 사용하는 경우엔 실시간을 맞추기 어려우므로, 저희는 다른 프레임워크들을 검토했습니다.   CoreML은 Apple 기기에 머신러닝 모델을 서빙하기 위한 프레임워크입니다. Apple 기기의 하드웨어 자원을 적극적으로 활용할 수 있고, 쉽게 프로파일링할 수 있다는 장점이 있습니다. 기본적으로는 coremltools를 사용해 PyTorch 모델을 CoreML 모델로 변환하고, CoreML에서 기본적으로 지원하지 않는 레이어는 MLCustomLayer를 통해 수동으로 작성할 수 있습니다.   TFLite (TensorFlow Lite) 는 모바일 기기 등에 머신러닝 모델을 서빙하기 위한 프레임워크입니다. PyTorch 모델을 TFLite 모델로 바꾸는 데는 다음의 두 방법이 있습니다. ·       TensorFlow 2.0 부터는 PyTorch와 거의 비슷한 코드로 모델을 만들 수 있으므로 직접 재작성 ·       Torch 모델 → ONNX 모델, ONNX 모델 간소화, ONNX 모델 → OpenVINO 모델, OpenVINO 모델 → TFLite 모델의 과정을 거쳐 자동으로 변환   첫 번째 방법의 경우 많은 작업이 필요하지만 가장 확실하게 모델을 포팅할 수 있다는 강점이 있습니다. 두 번째 방법의 경우 시간은 적게 걸리지만 각각의 변환 방법들이 모든 레이어를 지원하는 것은 아니기 때문에, 몇몇 레이어는 수동으로 구현해줘야 합니다. 그 중 저는 두 번째 방법을 통해 원본 PyTorch 모델을 TFLite 모델로 변환했고, GRU 레이어를 수동으로 구현하는 어려움이 있었지만, Apple M1 및 2스레드에서 RTF 0.06 수준을 달성했습니다.   안된다면? 직접 프레임워크 구현하기!   하지만 가우디오랩에서는 이 프레임워크들을 사용할 수 없었습니다. 더 높은 성능이 필요했고, SDK 제품 측면에서는 타 라이브러리에 디펜던시가 없는 것이 유리했기 때문입니다. 그래서 저희는 직접 머신러닝 프레임워크를 개발하기로 했습니다. 이 글에서는 머신러닝 프레임워크를 구현하며 각 레이어를 최적화하기 위해 사용한 기법들 중 몇 가지를 소개하려고 합니다.   메모리에 순차적으로 접근하기   Inference Engine에서 가장 중요한 부분 중 하나는 각 레이어의 성능을 높이는 것입니다. 제가 받은 모델은 이미 상당히 경량화되어 있어서, 캐시를 적극적으로 활용할 수 있도록 하는 것이 가장 중요했습니다.   우선 메모리에 순차적으로 접근하도록 하는 것부터 시작해 봅시다. 예를 들어 메모리에 3 x 3 텐서의 각 원소는 다음과 같은 형태로 저장되어 있을 것입니다.     그리고 이 원소들의 합을 구하는 코드는 다음과 같이 작성할 수 있습니다.     이 코드가 메모리에 접근하는 순서는 다음과 같을 것입니다.     같은 기능을 하는 코드를 이렇게도 작성할 수 있습니다.      그리고 이 코드가 메모리에 접근하는 순서는 다음과 같을 것입니다.     첫 번째 코드는 메모리에 순차적으로 접근합니다. 캐시는 인접한 메모리를 한 번에 읽어오므로, 첫 번째 코드는 캐시 적중률이 높을 것입니다. 반면 두 번째 코드는 메모리에 띄엄띄엄 접근합니다. 텐서의 크기가 작을 때는 별로 차이가 나지 않을지 몰라도, 텐서의 크기가 커지게 되면 메모리에 접근할 때마다 캐시에 다시 적재해야 하므로 성능이 하락합니다. 추가로, 메모리에 순차적으로 접근하는 코드는 컴파일러가 자동 벡터화를 수행해줄 확률이 높습니다. 따라서 두 번째 코드처럼 메모리에 순차적으로 접근하지 않는 코드는 최소화하는 것이 좋습니다.   메모리 쪼개기   하지만 메모리에 순차적으로 접근한다고 해도, 이것이 반복되면 매번 캐시에 새로 적재해야 합니다.     t2는 j와 k를 통해 메모리에 순차적으로 접근하지만, 가장 바깥의 i 때문에 캐시 활용성은 좋지 않아 보입니다. 이를 해결하기 위해서는, t2를 줄대로 쪼개서 for문 순서를 바꾸는 것이 좋아보이네요.     위의 두 기법은 머신러닝에서 가장 많이 사용되는 레이어인 Conv2D과 Linear 등에도 적용할 수 있습니다.   데이터 병렬   의존성이 없는 작업이라면 데이터 병렬을 도입하는 것도 좋습니다. OpenMP를 사용하면 데이터 병렬을 손쉽게 적용할 수 있습니다.     다만, 성능이 병렬화에 크게 의존하면 같이 실행되고 있는 프로그램이나 하드웨어 등 주변 상황에 영향을 많이 받게 되므로, 병렬화는 최대 성능을 높이는 데에 의의를 두는 것이 좋겠습니다. 또한, False Sharing 등의 문제가 발생할 수 있어 메모리 측면에서의 최적화가 까다로워지니, 벤치마킹을 통해 적용 여부를 결정하는 것이 좋습니다.   루프 언롤링   루프를 사용하게 되면 중단 조건에 대한 오버헤드가 발생합니다. 이는 아무리 분기 예측과 파이프라이닝이 발전해도 어쩔수 없죠. 하지만 여러 번의 번의 루프를 한 묶음으로 처리해서 뜨문뜨문 중단 조건을 검사한다면, 이러한 비용을 아낄 수 있을 것입니다. 상황에 따라 다르지만, 경험상 4번의 루프를 한 묶음으로 처리할 때가 가장 성능 향상 폭이 큰 것 같습니다. 다만 요즘은 컴파일러가 자동으로 언롤링을 수행하는 경우도 있으니, 꼭 컴파일된 결과물을 확인해 보고 사용하세요.      SIMD 일반적으로 CPU 명령어 하나는 데이터 한 개를 처리합니다. SIMD는 명령어 하나로 데이터 여러 개를 처리해, 성능을 향상시키는 기법입니다. C++에서 SIMD를 사용하기 위해서는 인트린직 함수 또는 이를 잘 래핑한 라이브러리를 사용하게 되는데요, 여기서는 xsimd 라이브러리를 사용한 예시를 보여드리겠습니다.     이 코드에 xsimd 라이브러리를 적용하면,     물론 요즘 컴파일러는 똑똑하기 때문에, 많은 케이스에 자동으로 SIMD 명령어를 적용해 줍니다. 그러나 사람만큼 잘 적용하지는 못하기 때문에, 일단 컴파일러가 잘 auto-vectorize할 수 있도록 코드를 작성하고, 컴파일러가 vectorize하지 못하는 부분만 인트린직 함수나 라이브러리를 사용하면 좋습니다. clang의 경우, -Rpass, -Rpass-missed, -Rpass-analysis 등의 옵션을 통해 컴파일러가 적용한 최적화에 대한 레포트를 만들 수 있습니다.   마치며   좋은 제품이라면, 수행 결과뿐만 아니라 수행 성능도 좋아야 합니다. 이번 글에서는 왜 최적화가 필요한지, 가우디오랩에서는 어떠한 과정을 거쳐서 최적화가 이루어지고 있는지를 간단히 설명해드려보았습니다. 앞으로도 저는 세상의 모든 소리를 담은 제품을 만들 수 있도록 더욱 열심히 노력하려고요! 읽어주셔서 감사합니다! 😘    

2023.05.10