
목소리 높낮이로 새를 조종하는 게임을 만들었습니다 (Voice Bird)
음이 높으면 새가 올라가고 낮추면 내려옵니다. 피치 추정은 라이브러리 없이 직접 구현했어요.
자랑 포인트
- 외부 피치 라이브러리 없이 자기상관(autocorrelation) + 포물선 보간으로 매 프레임 f0를 직접 추정합니다.
- 피치 소스를 PitchSource 인터페이스로 분리해, 마이크 없는 헤드리스 환경에서도 게임 로직을 자동 검증할 수 있어요.
- 음성은 서버로 전송되지 않고 기기를 떠나지 않는 완전 로컬 처리 — 프라이버시 걱정 없이 마음껏 소리 질러도 돼요.
Flappy Bird를 목소리로 조종하면 어떨까, 에서 시작한 게임입니다. 마이크에 소리를 내면 음이 높을수록 새가 날아오르고 낮추면 내려와요. "아~~~" 하면서 음정을 올렸다 내렸다 하며 장애물을 피하는 겁니다. 글로 쓰니 이상한데 해보면 더 이상합니다. 그리고 재밌습니다. HTTPS에서 마이크 권한만 허용하면 데스크톱이든 폰이든 바로 됩니다.

기술적으로 재밌었던 부분부터 얘기할게요. 핵심은 실시간 피치(음높이) 추정인데, 이걸 외부 라이브러리 없이 직접 구현했습니다. Web Audio API로 마이크 신호를 받아서 자기상관(autocorrelation)으로 주기를 찾고, 포물선 보간으로 정밀도를 올리고, 노이즈 게이트로 무음을 걸러냅니다. 게임 만들려고 신호처리를 공부하게 될 줄은 몰랐는데, 목적이 있으니까 머리에 잘 들어오더라고요.
사람 목소리는 생각보다 떨립니다. 그대로 매핑하면 새가 경련하듯 움직여서, 지수이동평균(EMA)으로 스무딩하고 옥타브 오검출도 억제했습니다. 음역은 로그 스케일로 화면 높이에 매핑했고요. 시작할 때 "아~" 소리로 내 음역을 재는 캘리브레이션도 있습니다(건너뛰기 가능). 이거 하면 저음인 사람도 고음인 사람도 자기 음역 안에서 편하게 조종돼요.
HUD에는 지금 내는 음이 음이름(C#3 같은)이랑 Hz로 실시간 표시됩니다. 게임하다 보면 부수적으로 자기 음역대를 알게 돼요. 노래방 선곡에 참고하세요.

점수는 캔버스로 그린 카드로 저장하거나 클립보드에 복사해서 자랑할 수 있고, 음성은 서버로 전송 안 됩니다. 전부 기기 안에서만 처리돼요.
개발 얘기 하나 더 하자면, 게임 엔진(물리·장애물·충돌·점수·난이도)을 DOM에 의존하지 않는 순수 모듈로 분리하고 피치 입력도 인터페이스로 추상화했습니다. 그래서 마이크 없는 테스트 환경에서 가짜 음정을 주입해서 자동 검증이 돼요. 게임에 테스트를 짤 수 있다는 걸 이번에 처음 해봤습니다. 렌더링은 React 19 + Vite + Tailwind 위에 Canvas 2D를 얹었고, UI는 React가 게임 화면은 Canvas가 나눠 맡아서 프레임이 안정적입니다.
사무실에서 열기 부담스러운 게임인 건 인정합니다. 근데 이어폰 끼고 소심하게 흥얼거려도 캘리브레이션만 맞으면 새는 잘 납니다. 집에서 하면 가족들이 쳐다보는 것만 견디면 됩니다. 저는 이제 그 시선에 익숙해졌어요. 🐤
난이도 피드백은 언제든 환영입니다. 제 목소리에 맞춰 밸런스를 잡아서, 노래 좀 하시는 분들한테는 쉬울 수도 있거든요. 최고 점수 스샷과 함께 댓글 남겨주시면 다음 패치에 반영하겠습니다.