게임 사운드
소리가 늦게 들리고, 벽 뒤에서 돌아 들리고, 적 AI가 소리를 듣는 원리다.
목차 (6)
적은 귀가 없다: 사운드 이벤트와 경로 거리
스텔스 게임에서 살금살금 걸었는데 옆방 적이 달려오고, 벽 하나 너머에서 뛰었는데 아무도 모른다. 버그가 아니라 판정이다. 적 AI는 스피커로 나가는 소리를 듣지 않는다. 플레이어가 발을 디디면 게임은 소리를 재생하는 것과 따로, AI 시스템에 “소리 났음” 이벤트를 하나 던진다. 듣는 쪽이 감지하는 것이 아니라 내는 쪽이 신고하는 구조이고, 상용 엔진의 AI 인지 기능도 이렇게 생겼다.
| 이벤트에 실리는 것 | 쓰임 |
|---|---|
| 위치 | 소리가 난 좌표. 적은 이 좌표로 조사하러 간다 |
| 반경(크기) | 얼마나 멀리까지 들리나. 웅크려 걷기는 좁게, 질주는 넓게, 총성은 아주 넓게 |
| 종류 | 발소리·유리 깨짐·총성. 적의 반응 단계(갸웃 → 조사 → 경계)를 고른다 |
가장 단순한 듣기는 거리 비교다. 반경 안에 귀가 있으면 들렸고, 밖이면 없는 소리다. 웅크렸을 때 조용해지는 것은 마이크 감도가 아니라 이 반경 숫자가 작아지는 것이다. 그런데 직선 거리만 쓰면 얇은 벽 하나를 사이에 둔 적이 코앞의 소리를 다 듣는다. 싼 보정은 소리와 귀 사이에 레이를 쏴 벽이 있으면 반경을 깎는 것인데, 이러면 문이 활짝 열려 있어도 벽 뒤는 똑같이 깎인다.
더 정직한 방법은 경로 거리(path distance)다. 소리 원점에서 이동 그래프(격자나 내비메시)를 탐색해 귀까지 가장 짧은 길의 길이를 재고, 그 값을 반경과 비교한다. 벽은 저절로 소리를 멀게 만들고 열린 문은 통로가 된다. 적을 쫓아오게 하던 길찾기(게임 AI·길찾기 노트)를 그대로 쓴다. 다만 탐색 비용이 있으니 총성처럼 큰 소리에만 쓰고 발소리는 직선 거리와 감쇠로 때우는 식으로 나눠 쓴다.
- 들었다고 들킨 게 아니다: 소리로 적이 얻는 것은 플레이어가 아니라 좌표 하나다. 적은 그 좌표로 걸어가 눈으로 확인하고, 최종 판정은 시야가 내린다.
- 물건 던지기: 적이 쫓는 것은 소리의 좌표이므로 병이 깨진 곳으로 걸어가는 동안 플레이어 위치는 시스템 어디에도 없다. 휘파람 유인은 반대로 자기 위치를 좌표로 등록하는 셈이다.
- 하나의 통로: 시각·청각·피격을 모두 “자극”이라는 같은 이벤트로 흘리고, 적은 마지막 자극의 좌표와 시각만 기억한다. 숨으면 “놓친다”는 행동이 따로 짜지 않아도 나오고, 작은 소리는 시야의 인지 게이지를 조금 올리는 식으로 눈과 귀를 합친다.
3D 오디오: 음속 지연, 감쇠, HRTF
게임은 총성을 월드 좌표에 놓지만, 헤드폰에 가는 것은 왼쪽·오른쪽 파형 두 줄뿐이다. 오디오 스레드가 음원 좌표를 리스너(카메라의 귀) 기준 거리·방위·고도로 바꾸고, 거리로는 크기·필터·지연을, 방향으로는 좌우 배분과 두 귀의 차이를 계산해 섞는다. 오디오는 게임 프레임과 따로 수 ms짜리 버퍼 단위로 돌기 때문에, 위치 값은 버퍼마다 부드럽게 보간해야 위치가 튈 때 딱딱 끊기는 잡음이 안 난다. 소리 신호와 버퍼의 기초는 오디오 노트에 있다.
지연: 지키는 물리
소리는 상온 공기에서 초속 약 343 m다. 총구 불빛은 바로 보이지만 400 m 밖의 총성은 1초 넘게 늦게 온다. 넓은 맵 슈터는 이 지연을 일부러 넣어 “번쩍, 한 박자 뒤 탕” 간격이 거리 정보가 되게 한다. 초음속 소총탄이 가까이 스치면 탄이 끄는 충격파의 날카로운 소리가 먼저 오고 총성이 뒤따른다. 반대로 좁은 맵에서는 수십 ms 지연이 정보가 아니라 렉처럼 느껴져 대부분의 게임은 넣지 않는다.
크기: 접는 물리
점음원은 거리가 두 배가 될 때마다 약 6 dB 작아진다(역제곱 법칙). 현실의 총성은 워낙 커서 1 km 밖에서도 또렷하지만, 게임은 귀를 해치지 않는 재생 크기와 방 안 소음 바닥 사이의 좁은 범위에 모든 소리를 넣어야 한다. 물리 비율을 그대로 쓰면 먼 총성은 그 바닥 아래로 꺼진다. 그래서 게임은 감쇠 곡선을 물리 공식이 아니라 디자이너가 소리 종류마다 고르는 값으로 다룬다.
- 정적으로 접기: 감쇠 곡선 자체를 완만하게 그린다. dB 축에서 기울기를 절반으로 하는 것은 압력비로 1/거리 대신 1/√거리를 쓰는 것과 같다.
- 동적으로 접기: 배틀필드 시리즈의 HDR 오디오처럼 소리마다 현실 음압에 가까운 논리적 크기를 주고, 그 위로 재생할 창을 실시간으로 옮긴다. 큰 소리가 나면 창이 따라 올라가고 창 밖으로 밀린 작은 소리는 재생하지 않는다. 파형을 누르는 컴프레서와는 다른 방식이다.
- “크다”의 번역: 코앞 총성의 크기는 볼륨 대신 저음의 펀치, 나머지 소리를 순간 낮추는 덕킹(ducking), 이명 효과, 화면 흔들림으로 전한다.
음색: 거리를 파는 진짜 수단
공기는 높은 주파수일수록 소리를 빨리 흡수한다. 그래서 가까운 총성은 날카롭고 먼 총성은 저음만 남아 둔하다. 흡수량은 온도·습도·기압에 따라 크게 달라진다(ISO 9613-1이 계산법을 정한다). 게임은 거리에 따라 로우패스 필터를 세게 걸거나, 아예 근거리·중거리·원거리용 녹음을 따로 만들어 거리에 따라 섞는다. 먼 총성이 “작아진 총소리”가 아니라 “먼 총소리”로 들리는 까닭이다.
방향: 두 귀의 차이와 몸의 필터
- 양귀 시차(ITD): 머리 폭 때문에 옆에서 온 소리는 먼 귀에 늦게 닿는다. 머리를 구로 근사하면 시차는 (r/c)(θ + sin θ)이고, 반지름 8.75 cm·옆(90°)이면 약 0.66 ms다.
- 양귀 음량차(ILD): 머리가 가려 먼 귀에는 작게, 특히 고음이 작게 닿는다. 가장 싼 구현은 좌우 음량만 나누는 패닝인데, 정전력 패닝은 완전 옆에서 반대쪽 채널을 0으로 만들어 소리가 “옆”이 아니라 “머릿속”에서 나는 듯 들리게 한다.
- HRTF(head-related transfer function): 좌우 차이만으로는 앞과 뒤, 위와 아래를 못 가린다. 귓바퀴·머리·어깨가 방향마다 특정 고음 대역을 다르게 깎는데, 이 방향별 필터를 시간 영역에서 잰 것이 HRIR, 주파수 영역으로 나타낸 것이 HRTF다. 더미 헤드로 잰 공개 데이터의 HRIR을 소리에 컨볼루션하면 시차·음량차·귓바퀴 노치가 한꺼번에 들어가 헤드폰에서도 등 뒤 소리가 난다.
앞뒤를 가르는 단서는 크기가 아니라 대략 5 kHz 위 고음 대역에 파이는 스펙트럼 골짜기(노치)의 자리다. 남의 머리로 잰 필터라 사람에 따라 앞뒤가 뒤집혀 들리기도 해서, 귀 모양에 맞춘 개인화 HRTF가 다음 과제로 꼽힌다. 게임은 물리를 다 지키지 않는다. 지연은 지키고, 크기는 재생 범위에 맞춰 접고, 음색은 공기를 흉내 내고, 방향은 귀를 속일 만큼만 계산한다.
차폐와 회절: 벽 뒤 소리는 문에서 튼다
벽 너머 소리는 먹먹하게 들리고, 옆방 소리는 열린 문 쪽에서 들려야 자연스럽다. 벽이 소리를 막는 것이 차폐(occlusion), 소리가 문이나 모서리를 돌아 들어오는 것이 회절(diffraction)이다. 실행 중에 파동 방정식을 푸는 게임은 드물고, 대부분 레이와 길찾기로 흉내 낸다.
- 레이 한 줄 차폐: 음원에서 리스너로 레이를 쏴 막혔으면 볼륨을 줄이고 로우패스 필터를 건다. 언리얼 엔진의 감쇠 설정과 Wwise 같은 오디오 미들웨어가 이 값을 받는 자리를 둔다. 싸지만 레이가 막힘·뚫림 사이를 오갈 때 소리가 갑자기 바뀌고, 가는 가로등 하나에 걸려도 콘크리트 벽처럼 깎인다.
- 레이 여러 줄: 음원 둘레 여러 점으로 쏴 막힌 비율만큼 줄이면 경계가 부드럽고 가는 기둥에 덜 민감하다.
실제 파동을 계산해 보면 회절에는 주파수 성질이 있다. 파장이 문 폭보다 긴 저음은 문을 지나며 반원으로 퍼져 문이 새 음원처럼 보이고, 파장이 짧은 고음은 곧게 나가 문 옆이 어둡다. 그래서 벽 뒤(음원이 직접 안 보이는 그늘)에서 소리는 음원 쪽이 아니라 문 쪽에서 오고, 돌아 꺾인 각도가 클수록, 대개 고음일수록 더 줄어든다. 모서리를 새로 퍼져 나오는 한 점으로 보고 로우패스 필터로 흉내 내는 것이 미들웨어의 회절 모델이다.
- 방과 포털: 공간을 방으로 나누고 문 자리에 포털을 둔다(Wwise Spatial Audio의 rooms and portals). 다른 방의 소리는 포털을 거쳐 온다.
- 길 찾기: 방·포털 그래프나 공간을 잘게 나눈 음향 그래프에서 음원부터 리스너까지 가장 짧은 길을 찾는다. 그 길이 직선보다 얼마나 돌아가는지가 감쇠 값이 된다.
- 소리 옮기기: 길의 마지막 포털 근처에 가상 음원을 두고 거기서 튼다. 방향은 문 쪽이 되고, 거리는 돌아온 길 전체로 계산한다. 리스너가 문으로 다가가면 꺾인 각도가 줄어 소리가 또렷해진다.
- 벽 투과: 벽을 뚫고 오는 소리는 벽 재질만큼 깎아 따로 계산하고, 문으로 돌아온 소리와 함께 섞는다.
이 길은 적 AI의 청각에도 그대로 쓸 수 있다. 사람에게 들리는 소리와 적이 듣는 판정이 같은 그래프에서 나오면, “나는 문 너머 소리를 들었는데 적은 못 들었다” 같은 어긋남이 줄어든다. 레인보우 식스 시즈처럼 소리로 적 위치를 읽는 게임에서 열린 문·뚫린 벽을 따라 소리가 오게 하는 것도 같은 생각이다.
보이스 제한: 한꺼번에 섞을 수 있는 소리는 정해져 있다
전투 한복판에는 총성, 탄피, 발소리, 폭발, 대사, 배경음이 동시에 수백 개 울리려 한다. 소리 하나(보이스, voice)를 섞으려면 압축된 파일을 풀고, 위치에 맞춰 필터와 패닝을 걸고, 버퍼에 더해야 한다. 오디오 스레드는 수 ms마다 버퍼를 채워야 하고 늦으면 소리가 끊기므로, 한 번에 실제로 섞을 보이스 수에 상한을 둔다. 그리고 상한을 넘을 때 무엇을 버릴지를 정하는 것이 오디오 설계의 큰 부분이 된다.
- 소리마다 개수 제한: 같은 발소리 효과가 열여섯 개 겹쳐 울려도 귀에는 여덟 개와 구별이 안 되고 크기만 부푼다. 소리 종류마다 동시 개수 상한을 두고, 넘으면 새 소리를 무시하거나 가장 오래된·가장 작은 것을 끊는다.
- 우선순위: 소리마다 중요도 값을 주고, 전체 상한에 걸리면 중요도가 낮고 작게 들리는 것부터 밀어낸다. 대사와 내 무기 소리는 거의 밀리지 않게, 먼 탄피 소리는 가장 먼저 밀리게 둔다.
- 가상 보이스(virtual voice): 너무 멀거나 작아 안 들리는 소리는 섞기를 멈추되 “재생 중이고 지금 몇 초째”라는 기록만 계속 굴린다. 플레이어가 다가가 다시 들릴 크기가 되면 그 시점부터 이어서 튼다. 처음부터 다시 틀면 폭포 소리가 다가갈 때마다 새로 시작하는 것처럼 들린다.
- 끊을 때는 짧게 줄인다: 밀려난 보이스를 그 자리에서 0으로 자르면 파형이 끊겨 딸깍 잡음이 난다. 몇 ms 동안 볼륨을 내리고 나서 멈춘다.
Wwise·FMOD 같은 오디오 미들웨어는 이 설정을 디자이너가 소리마다 고르는 값(재생 개수 제한, 우선순위, 안 들릴 때의 가상 보이스 동작)으로 내놓는다. 프로그래머가 고칠 일은 보통 “이 소리를 몇 개까지, 어떤 순서로 버릴지”가 데이터로 정해져 있는지 확인하는 것이다.
믹스 버스와 덕킹: 들려야 할 소리를 먼저
소리를 하나하나 따로 조절하면 수천 개를 맞춰야 한다. 그래서 소리를 묶음(버스, bus)으로 흘려 보낸다. 발소리·총성·폭발은 효과음 버스로, 대사는 대사 버스로, 음악은 음악 버스로 가고, 버스들이 다시 마스터 버스에 모인다. 설정 메뉴의 “효과음 볼륨” 슬라이더는 이 버스 하나의 볼륨이다. 버스에 걸린 필터와 압축기도 묶음 전체에 한 번만 계산된다.
- 덕킹(ducking): 중요한 대사가 나오면 효과음과 음악 버스를 몇 dB 낮췄다가 대사가 끝나면 되돌린다. 대사 버스의 크기를 보고 다른 버스를 누르는 사이드체인(sidechain)으로 자동으로 하기도 한다.
- 스냅숏(snapshot, mix state): 일시 정지 메뉴, 물속, 섬광탄에 귀가 멍한 순간처럼 믹스 전체의 모양이 바뀌는 장면은 버스 볼륨과 필터 값을 묶은 상태 하나로 두고, 장면이 바뀔 때 그 상태로 부드럽게 넘어간다. 물속이면 모든 효과음 버스에 로우패스가 걸리는 식이다.
- 소리마다 다른 귀: 같은 발소리라도 누구의 발소리인지에 따라 믹스를 다르게 할 수 있다. 오버워치는 GDC 2016 발표 Overwatch - The Elusive Goal: Play by Sound에서 적의 발소리를 아군 발소리보다 크게 들리게 한 설계를 소개했다. 경쟁 게임에서 소리는 분위기보다 먼저 정보다.
우선순위를 정하는 기준은 “지금 플레이어가 무엇을 알아야 하나”다. 나를 노리는 적, 등 뒤에서 다가오는 발소리, 곧 터질 폭발물은 크게 또렷하게, 이미 아는 소리와 아군 소리는 작게 둔다. 위의 HDR 오디오가 큰 소리 쪽으로 재생 창을 옮겨 작은 소리를 밀어내는 것, 보이스 제한이 중요도 낮은 소리부터 버리는 것도 모두 이 기준을 숫자로 적은 것이다.
잔향: 방이 소리에 남기는 꼬리
같은 박수 소리도 욕실, 성당, 들판에서 다르게 들린다. 귀에 직접 온 소리 뒤로 벽에 한두 번 튄 소리가 수십 ms 안에 따로따로 도착하고(초기 반사, early reflections), 그 뒤로 셀 수 없이 많이 튄 소리가 뭉쳐 서서히 사그라드는 꼬리(후기 잔향, late reverb)가 이어진다. 초기 반사는 벽까지의 거리와 방향을, 꼬리의 길이는 방의 크기와 재질을 알려 준다. 꼬리 길이는 보통 소리가 60 dB 줄어드는 데 걸리는 시간(RT60)으로 잰다.
- 잔향 구역: 가장 흔한 방식은 공간마다 잔향 설정(꼬리 길이, 고음이 빨리 죽는 정도, 원음과 섞는 비율)을 정해 두고, 리스너가 있는 구역의 설정을 쓰는 것이다. 문턱을 넘을 때 설정을 바로 바꾸면 티가 나니 경계 근처에서 두 설정을 섞는다.
- 보내기(send): 잔향 효과는 소리마다 따로 걸지 않고 잔향 버스 하나에 둔다. 각 소리는 원음은 그대로 내보내고, 일부를 잔향 버스로 보낸다. 멀리 있는 소리일수록 보내는 양을 늘리면 거리감도 함께 생긴다.
- 컨볼루션 잔향(convolution reverb): 실제 공간에서 짧은 충격음을 터뜨려 녹음한 응답(임펄스 응답)을 소리에 컨볼루션하면 그 공간의 울림이 그대로 입혀진다. 사실적이지만 계산이 비싸 중요한 공간이나 버스 한두 개에만 쓴다.
- 남의 방 울림: 옆방에서 난 소리는 옆방의 잔향을 입고 문(포털)을 지나 온다. 위의 방·포털 구조가 있으면 소리마다 음원이 있는 방의 잔향 버스로 보내고, 그 결과를 포털 위치에서 틀어 “저 방이 울린다”를 낼 수 있다.
잔향을 너무 많이 넣으면 소리가 흐려져 정보가 사라진다. 경쟁 게임일수록 잔향은 공간의 성격을 알릴 만큼만 짧게 쓰고, 방향을 가리는 초기 반사와 꼬리를 위의 덕킹·우선순위와 함께 조절한다.