23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
소리를 내고 소리를 듣는 건 모두 떨림이 있기 때문이다. 공기를 떨리게 함으로서 진동이 생기고 우리는 그 진동을 듣고 정보를 해석한다.
이러한 소리 진동을 반복해서 발생시키기 위해 기록하고 재생하는 장치가 필요해졌고 이것이 축음기이다.
가정에서 쉽게 만들어볼 수 있는 축음기는 아래와 같이 만들어볼 수 있다.
결국 아날로그는 녹음을 어떤 판에 직접적으로 기록한다. LP레코드판을 재미삼아 살펴보면 다음과 같이 생겼다.
이러한 아날로그 방식은 홈의 깊이에 따라 스피커에 붙은 자석을 떨리는 양을 정하는 전압으로 보내 스피커를 떨리게 하여 진동을 발생시켜 소리를 만든다.
How Speaker Works, animation by OcS (www.octavesim.com)
여기까지 아날로그 세상에서 녹음부터 출력까지를 간단하게 훑어보았다. 입력된 값은 그대로 출력이 되는 것이며,
더 간단히는 패트병만으로도 이런 상황을 만들어볼 수 있다는 게 아날로그의 장점이나, 기록양이 많아질수록 저장매체의 양이 계속해서 늘어나야만 한다.
디지털 세상에 넘어오면 저장매체가 메모리로 바뀌었다. HDD, SSD 등등. 이렇게 변경되면서 저장할 수 있는 내용이 매우 커졌다. 큰 장점이다.
오디오 데이터를 이러한 저장매체에 위 녹음하는 방법처럼 더 이상 핀으로 긁어서 기록해두지 않으며, 숫자(digit)로 기록한다.
소리의 진폭을 어떻게 숫자로 바꾸어 저장장치에 기록하고, 저장된 숫자를 어떻게 스피커의 떨림의 전압으로 보낼 수 있으려면 다음 회로의 도움이 필요하다.
DAC(Digital Analog Converter), ADC(Analog Digital Converter).
이 회로가 아날로그인 소리를 숫자로 바꿔주고, 소리 값을 다시 아날로그 파형으로 만들어준다.
아날로그를 디지털로 바꿀 때 다음의 과정을 거친다.
아날로그는 연속적인 파형인데 디지털은 숫자들의 집합임으로 계획적으로 원래의 연속적인 파형을 각 시점의 숫자들의 집합으로 바꾸는 과정이 필요해진다.
가장 먼저 얼마만큼의 간격으로 숫자를 추출할 것인가이다.
시간에 따른 파형에 따라 일정 시간별로 디지털화 할 지점을 정하게 된다.
이 값을 sample rate라고 부른다. Hz 단위를 사용하며 초당 sampling 수에 따라 16000hz, 48000hz 등을 목적에 따라 사용하게 된다.
다음은 각각의 현재 파동의 값을 얼마나 촘촘한 간격의 값으로 표현할 것인가의 문제이다.
각 값의 간격이 촘촘할수록 원래의 파형과 비슷한 디지털 파형이 만들어 질 수 있게 된다.
이 값을 bitrate라고 한다. 2byte의 총 16bit 를 보통 사용하며 -32,768 ~ 32,767 범위의 값을 사용하게 된다.
결론적으로 원래의 아날로그 신호를 더 높은 sample rate, 더 높은 bitrate로 잘라내면 낼수록 원래의 analog 파형과 비슷한 디지털 숫자들이 나온다는 걸 볼 수 있다.
SKT 전처리를 위해서 선택한 sample rate는 초당 16000을 처리하고 16bit bitrate를 갖도록 하였다.
각각의 값들이 많아지면 음질은 좋아지지만 실시간으로 처리해야 하는 양이 매우 많아져서 처리속도가 느려질 수 있고,
적어지면 원래의 파형이 디지털화 되면서 깎여나가 원래의 소리가 왜곡되게 들리기 때문에
현재의 기준점이 음성 처리를 하는 데 적절하다고 생각된다.
음성인식 device 용으로 리눅스 과제가 셋업이 되었다. 해야하는 일은 마이크를 통해 들어오는 소리를 이 소리를 사용하는 에이닷의 음성 인식기에 잘 전달해야 한다.
잘 전달한다는 뜻은 마이크로 들어온 소리 중에서 나에게 말하는 사람의 목소리만 깨끗하게 받아들여 에이닷에게 Audio data를 전달한다는 의미이다.
가장 좋은 상황은 무음실에 있고 말하는 사람이 혼자만 있는 상황일 것 같다.
그러나 현실에서 내가 어떤 사람과 대화하고 있는데 나도 말하고 있고 주변에서도 말하고 있고, 옆에 차가 지나가고 있는 상황에서
나와 대화하고 있는 사람의 말을 듣고 무슨 말을 하는 지 이해할 수 있어야 한다.
사람은 이런 상황에서 주변이 너무 시끄럽지만 않으면 앞에서 말하는 사람의 말을 잘 이해할 수있지만,
디지털 장치에서의 소리란 위에서 설명한 방법에 의해 단순히 지금 순간의 파동이 얼마나 큰지만 알 수 있을 뿐이다.
그렇기 때문에 SKT 음성인식팀에서는 전처리 라이브러리를 개발하고 있고
이 라이브러리는 주변의 노이즈는 작게 줄이고(Noise Reduction, NR), 말하는 사람의 소리만 집중되게 만든다.
또한 사람이 아닌 기계가 소리를 처리하기 때문에 기계 자체에서 출력한 소리가 마이크로 들어오는 경우
이 부분을 확실히 제거해야 외부에서 발생하는 소리만 추출해 낼 수 있다(EC, Echo Cancellation).
단말 SW 관점에서 살펴보면 라이브러리가 여러 동작 환경에서
위 전처리기 라이브러리가 정상적으로 동작하게 하는 Software 환경을 평가하고 Target OS에 Porting을 하게 한다.
좀 더 정확히는 HW Mic를 통해 들어오는 소리가 깨끗하게 보장하고
각각의 OS에 따라 장치에서 발생한 소리를 Recording 하고 단말에서 출력되는 소리를
전처리기에서 processing 하게 한 후 그 결과를 application 인 에이닷에게 전달하게 된다.
소리의 입출력 PATH, 즉 MIC와 SPK가 준비되고,
단말에서 출력되는 소리(echo cancellation에 사용될 참조 sample의 의미로 reference data 라고 표현한다)가 준비되면
단말의 OS의 어느 부분에서 전처리 라이브러리를 동작하게 할 지 결정해야 한다.
그러기 위해서 OS의 대략적인 architecture를 알면 도움이 된다.
OS는 단말의 각각의 H/W, S/W 를 서로 사용하려는 점유 문제를 완만히 중재하며 모든 기능이 잘 동작하게 하는 것이다.
많이 들어본 OS는 Windows, Linux, MacOS, Android, ios가 있다.
Audio 측면에서 각각의 OS는 Audioserver 역할의 process 또는 daemon 또는 layer를 가진다.
Android의 audioserver
AudioServer의 역할은 다음과 같다.
디바이스 드라이버는 SW Audio Data를 HW Device(speaker, mic)를 거쳐 아날로그로 변경하여 공중에 뿌리고 받게끔 한다.
디바이스 드라이버가 SW의 가장 말단 같은 존재이다.
그런데 이 말단인 SW는 한번에 하나의 일만 할 수 있다.
OS와 AudioServer가 없다면 동시에 여러 프로그램이 돌아가는 App들이 모두 소리를 내고자 할때, 녹음을 하고자 할 때
하나의 Application에서만 Audio Device를 사용할 수 있게 된다.
이를 해결하기 위해 AudioServer가 중간자 역할을 해서 Audio 관련 처리를 관리해준다.
또한 사람의 청각은 매우 민감해서 16000hz 중 1 sample만 원래 흐름에서 다른 소리가 있거나 음이 없으면 이상함을 알아채게 된다.
그래서 음이 끊어지지 않도록 중간에 미리 buffer을 이용해서 미리 재생할 것을 담아둔다.
다음으로 볼륨을 어떻게 조절해야 할까?
여러가지 Application에서 각각의 역할에 따라 사용자의 기호에 따라 볼륨을 설정하면 수월할 것이다.
알람은 키우고, 게임 소리는 줄이고, 벨소리는 적당하게 등등. 이러한 것도 Audioserver가 관리할 수 있다.
이런 사유로 대부분의 OS에서는 AudioServer라는 것을 두고 Audio 처리를 원활히 수행하도록 한다.
(이것이 Audioserver가 하는 모든 일은 아니다. 더 많고 새로운 기술들이 계속 적용되고 발전되고 있다.)
우리의 과제는 buildroot로 각각의 필요한 모듈을 모아 만든 custom linux 이고 Audioserver 역할을 하는 것은 없는 상태였다.
위 전처리를 위한 filter 작업이 수월할 것, 각각의 기능별 volume 조절이 수월할 것,
gstreamer의 지원 등 media 와 관련된 부분과의 연동 작업이 수월한 부분,
SKT AI SDK와 결합이 수월한 것 등을 고려하여 Pulseaudio로 결정되게 되었다.
(참고로 ubuntu는 Pulseaudio를 Audioserver로 이미 사용하고 있다.)
Pulseaudio는 다음의 특징을 가지고 있다.
Audio 시스템을 위한 추상화
자동으로 sound device setup
여러 다양한 모듈, sound card 등에 대한 넓은 호환성 확보
확장의 용이
다양한 네트워크 protocol을 지원함
sound processing
바로 재생할 용도의 sample cache
Time management
Power saving
Automatic routing
대략적인 Pulseaudio의 구조는 다음과 같다.
Pulseaudio는 다음과 같은 구조로 recording, playback을 수행하는데,
sink-input, source-output으로 표기된 모듈을 새로 작성하여 필요에 따라 filter를 넣기 용이하다.
(소스를 설명하기보다는 대략적인 작업 방향을 말씀드림에 너른 양해를 부탁드린다.)
우선 SKT 전처리 라이브러리를 target architecture와 OS에서 사용 가능하도록 wrapping 작업을 수행했다.
Wrapping library
Architecture에 SKT 전처리 라이브러리 포팅
Input, output resample 기능 포함(48000hz -> 16000hz 혹은 그 반대)
Input, output buffer 처리 기능
Input, reference, output의 dump 기능
Etc
그 후 Pulseaudio 에서 전처리가 동작하며 audio filter 로 적용되기 위한 Pulseaudio module을 작성하였다.
Module-skt-preprocessor
위 Pulseaudio 소개 dialog 중 source output에 추가 적용되는 모듈
Pulseaudio의 callback 중 source_output_push_cb 부분에 위 Wrapping library를 적절히 삽입.
Channel, buffer 작업
Debugging을 위한 log 및 dump 코드 추가
아래 그림과 같은 Pulseaudio의 echo cancellation 구조를 유지하려고 하였다.
추가 요구 사항으로 A application은 위 전처리가 동작한 이후의 audio를 원하였고, B application은 전처리가 동작하지 않은 audio를 원하여서
alsa의 plugin 중 dsnoop를 다음과 같이 pcm control을 추가하였다.
Asounds.conf
pcm.skt_dsnoop {
type dsnoop
ipc_key 1024
slave {
pcm "hw:0,2"
channels 8
rate 48000
}
}
pcm.pulse {
type pulse
}
pcm.skt_linkplay_record {
type pulse
device alsa_input.skt_dsnoop
}위 작성된 모든 모듈들은 단말이 부팅되어 Pulseaudio가 시작되는 시점에 모듈 로딩이 되어 바로 사용 가능한 상태가 된다.
Default.pa
load-module module-alsa-sink name=SKT_device_playback device=hw:0,0 rate=48000 channels=2
load-module module-alsa-source name=SKT_device device=skt_dsnoop rate=48000 channels=8
load-module module-alsa-source name=skt_dsnoop device=skt_dsnoop rate=48000 channels=8
…
load-module module-skt-preprocessor source_name="skt-preprocessor"
set-default-sink alsa_output.SKT_device_playback
set-default-source skt-preprocessor또한 각각의 목적에 따라 볼륨을 일괄적으로 제어할 수 있도록 role을 부여하는 pcm control을 작성하였다.
이에 따라 alsa-plugin 코드에서 config 읽는 부분에 media_role에 따라 Pulseaudio의 role을 부여하는 코드도 추가되었다.
pcm.pulse_linkplay_playback_MUSIC {
type pulse
device alsa_output.SKT_device_playback
media_role MUSIC
}
… alarm, system, etc…디지털 세계에서 오디오는 사람의 감각에 직접적으로 연결되는 부분이어서 대부분 실시간으로 동작하게 된다.
이런 실시간으로 돌아가는 특성으로 인해 개발 및 디버깅에 많은 제약사항이 생기게 된다.
그러나 과거부터 지금까지 많은 개발자, 연구자들이 성과를 이루어냈고,
지금도 어딘가에서 더 좋은 품질의 오디오를 사용자에게 제공하기 위해
새로운 기술을 개발하고 계신 여러 개발자들을 생각하면
항상 대단하다고 느끼고 존경하는 마음이 든다.
AI가 사람의 삶으로 더욱 깊이 들어가려면 눈으로 소리로 피부로 결국 닿아야 한다고 생각하며
관련 업무를 하고 있음에 보람을 느끼며 업무를 하여 다행이라고 생각한다.
감사합니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.