1. 실시간 오디오 피치 검출(Pitch Detection)의 음향학적 과제
현악기 연주자와 음향 엔지니어에게 정확한 피치 검출(Pitch Detection)은 조율의 성패를 가르는 기본 작업입니다. 그러나 마이크를 통해 유입되는 실제 기타 사운드는 이상적인 사인파(Sine Wave)가 아닙니다. 현의 진동은 강한 배음(Harmonics / Overtone) 성분을 포함하며, 특히 어쿠스틱 기타나 일렉트릭 기타의 저음현(6번 줄 E2: 82.41Hz)의 경우 기본 주파수(Fundamental Frequency )보다 2차, 3차 배음(164.8Hz, 247.2Hz)의 음향 에너지가 물리적으로 더 큰 현상이 흔히 발생합니다.
이로 인해 단순한 푸리에 변환(FFT) 피크 탐색 기법을 적용할 경우 기본 음보다 1옥타브 높은 배음을 기본 주파수로 오인하는 ‘옥타브 오류(Octave Error)‘에 빠지게 됩니다. 이에 따라 Every-Forge 오디오 랩은 시간 도메인(Time-Domain)에서 주기성을 정밀하게 포착하는 **자기상관함수(Autocorrelation Function, ACF)**와 **포물선 보간법(Parabolic Interpolation)**을 결합하여 서브 센트(Sub-Cent) 해상도를 달성하는 인브라우저 튜너 엔진을 설계하였습니다.
악기 조율 과정에서 연주자는 현을 튕기는 순간의 과도응답(Attack)과 이후 감쇠하는 지속음(Sustain) 구간을 겪게 되는데, 튜닝 알고리즘은 타악기적 잡음이 강한 어택 구간을 피해 배음 구조가 안정화된 서스테인 구간의 주기를 신속하고 안정적으로 잠금(Phase Lock)해야 합니다.
2. 피치 검출 알고리즘별 성능 및 정확도 비교
오디오 디지털 신호 처리(DSP) 분야에서 널리 활용되는 피치 검출 알고리즘들의 성능 특성을 비교하면 다음과 같습니다.
| 알고리즘 명칭 | 분석 도메인 | 시간 복잡도 | 배음 왜곡 저항성 (옥타브 오류 방지) | 저음역(E2, 82Hz) 지연 시간 | 구현 적합성 |
|---|---|---|---|---|---|
| 영교차 검출 (Zero-Crossing) | 시간 도메인 | (초고속) | 매우 취약 (잡음/배음에 오작동) | 매우 빠름 | 단순 사인파 전용 |
| FFT 피크 매칭 (HPS) | 주파수 도메인 | 보통 (주파수 분해능 한계 존재) | 버퍼 크기 증가로 지연 큼 | 스펙트럼 분석 적합 | |
| 자기상관함수 (ACF) (Every-Forge) | 시간 도메인 | 또는 FFT 가속 | 매우 우수 (파형 주기성 직접 포착) | ~25ms 이내 (실시간 반응) | 악기 튜너 최적 |
| YIN 알고리즘 | 시간 (누적 차분) | 최고 수준 | ~30ms | 고급 음성 분석 |
3. 시간 영역 자기상관함수(ACF)와 포물선 보간법 수학
이산 음향 신호 의 길이가 일 때, 지연 시간(Lag) 에 대한 자기상관함수 는 신호와 그 신호를 만큼 이동시킨 신호 간의 내적으로 정의됩니다:
기본 주파수 주기에 해당하는 지연 에서 는 가장 뚜렷한 극대 피크(Local Maximum)를 형성합니다.
3.1. 서브-샘플 해상도를 위한 포물선 보간법(Parabolic Interpolation)
이산 샘플링 레이트 환경에서 샘플 인덱스는 정수 값만을 가집니다. 따라서 피크가 정수 격자 사이에 위치할 때 발생하는 양자화 오차를 보정하기 위해, 극대 피크 과 그 좌우 인접 샘플 을 통과하는 2차 포물선 곡선을 적합합니다:
최종 보정된 기본 주파수 는 다음과 같이 도출됩니다:
3.2. 센트(Cent) 오차와 표준 기타 조율 기준 주파수
기타의 6개 개방현 표준 조율 주파수는 평균율(Equal Temperament) 를 기준으로 다음과 같이 정의됩니다:
- 6번 줄 (E2):
- 5번 줄 (A2):
- 4번 줄 (D3):
- 3번 줄 (G3):
- 2번 줄 (B3):
- 1번 줄 (E4):
검출된 주파수 와 가장 가까운 타깃 음계 주파수 사이의 음악적 편차는 센트(Cent) 단위로 환산되며, 100센트는 반음(Semitone) 1개에 해당합니다:
4. 고역 통과 필터링과 노이즈 게이트(Noise Gate) 임계치
마이크 주변의 환경 저주파 소음(교류 60Hz 험 노이즈, 에어컨 진동음)이 E2 음계로 오인되는 현상을 차단하기 위해, 차단 주파수를 갖는 2차 버터워스 하이패스 필터(Biquad IIR)를 선행 적용합니다. 또한 신호의 제곱평균제곱근(RMS) 에너지가 노이즈 임계치 이하인 침묵 상태에서는 피치 연산을 즉각 우회합니다.
5. Web Audio API 실시간 피치 검출 엔진 구현체
아래 TypeScript 코드는 브라우저의 AudioContext와 AnalyserNode를 연결하여 시간 영역 시간 버퍼를 획득하고, ACF 피크 탐색 및 포물선 보간을 통해 정밀 음정과 센트 편차를 계산하는 완전한 튜너 엔진 구현체입니다.
// Every-Forge Audio Lab: In-Browser Real-Time ACF Pitch Detector
export interface PitchResult {
frequency: number;
noteName: string;
targetFreq: number;
centDiff: number;
confidence: number;
}
export class AcfPitchEngine {
private static readonly GUITAR_STRINGS = [
{ name: "E2", freq: 82.41 },
{ name: "A2", freq: 110.0 },
{ name: "D3", freq: 146.83 },
{ name: "G3", freq: 196.0 },
{ name: "B3", freq: 246.94 },
{ name: "E4", freq: 329.63 },
];
static detectPitch(buffer: Float32Array, sampleRate: number): PitchResult | null {
const size = buffer.length;
let sumSquares = 0;
for (let i = 0; i < size; i++) sumSquares += buffer[i] * buffer[i];
const rms = Math.sqrt(sumSquares / size);
if (rms < 0.015) return null;
const minPeriod = Math.floor(sampleRate / 400);
const maxPeriod = Math.floor(sampleRate / 75);
let bestCorrelation = -1;
let bestPeriod = -1;
for (let tau = minPeriod; tau <= maxPeriod; tau++) {
let correlation = 0;
for (let i = 0; i < size - tau; i++) {
correlation += buffer[i] * buffer[i + tau];
}
if (correlation > bestCorrelation) {
bestCorrelation = correlation;
bestPeriod = tau;
}
}
if (bestPeriod === -1 || bestCorrelation <= 0) return null;
const y0 = bestPeriod > minPeriod ? this.getCorrAt(buffer, size, bestPeriod - 1) : bestCorrelation;
const y1 = bestCorrelation;
const y2 = bestPeriod < maxPeriod ? this.getCorrAt(buffer, size, bestPeriod + 1) : bestCorrelation;
const denom = 2 * (2 * y1 - y0 - y2);
const delta = denom === 0 ? 0 : (y2 - y0) / denom;
const exactPeriod = bestPeriod + delta;
const detectedFreq = sampleRate / exactPeriod;
let closestString = this.GUITAR_STRINGS[0];
let minDiff = Infinity;
for (const str of this.GUITAR_STRINGS) {
const diff = Math.abs(detectedFreq - str.freq);
if (diff < minDiff) {
minDiff = diff;
closestString = str;
}
}
const centDiff = 1200 * Math.log2(detectedFreq / closestString.freq);
return {
frequency: Number(detectedFreq.toFixed(2)),
noteName: closestString.name,
targetFreq: closestString.freq,
centDiff: Number(centDiff.toFixed(1)),
confidence: Number((rms * 10).toFixed(2)),
};
}
private static getCorrAt(buf: Float32Array, size: number, tau: number): number {
let corr = 0;
for (let i = 0; i < size - tau; i++) corr += buf[i] * buf[i + tau];
return corr;
}
}
6. AudioWorklet과 메인 스레드 간 SharedArrayBuffer 링 버퍼(Ring Buffer) 아키텍처
브라우저의 메인 스레드가 무거운 가상 DOM 연산이나 CSS 레이아웃 리플로우(Reflow)를 수행할 때, onaudioprocess 같은 구식 Web Audio API 이벤트는 오디오 콜백이 지연되어 음향 버퍼 결손(Buffer Underrun)과 오디오 팝 노이즈를 유발합니다.
Every-Forge 튜너는 오디오 처리 전용 백그라운드 스레드인 AudioWorkletProcessor를 활용합니다. 128샘플 단위의 미세한 오디오 렌더 퀀텀(Render Quantum)을 원자적(Atomic)으로 조작하기 위해 SharedArrayBuffer와 락프리 링 버퍼(Lock-Free Ring Buffer)를 구현하여, 메인 스레드의 UI 연산 부하와 완벽히 격리된 44.1kHz 무결 오디오 캡처 파이프라인을 유지합니다.
또한 하이엔드 하드웨어 스트로보 튜너(Strobe Tuner)의 시각적 인터페이스를 모사하기 위해, 목표 주파수 와 검출 주파수 간의 위상 회전 각도 를 60FPS 캔버스 회전 각속도로 사상합니다:
음정이 완벽히 일치할 때() 스트로보 패턴의 회전 속도는 정지()하며, 피치가 높으면 시계방향, 낮으면 반시계방향으로 회전함으로써 연주자에게 직관적이고 즉각적인 시각적 피드백을 제공합니다.
7. 결론 및 Every-Forge 악기 튜너 도구 연동
웹 오디오 기술과 디지털 신호 처리 수학의 융합은 값비싼 하드웨어 튜너 못지않은 정확도를 스마트폰이나 노트북의 브라우저에서 바로 실현할 수 있게 해줍니다.
실제 마이크를 켜고 자신의 일렉트릭/어쿠스틱 기타를 연결하여 실시간 센트 게이지와 시각적 튜닝 피드백을 체험해 보시려면 Every-Forge 인브라우저 정밀 튜너 바로가기를 이용해 보시기 바랍니다.
Web Audio API 기반 자기상관함수(ACF) 실시간 음고 검출 및 샘플 단위 정밀 메트로놈
Every-Forge Engine Lab
Verified AuthorPrincipal Audio DSP & Computer Vision Systems Architect
Every-Forge 엔진 랩은 브라우저 샌드박스 메모리 내에서 100% 동작하는 제로-서버(Zero-Server) 고성능 웹 엔지니어링을 연구합니다. WebGPU 셰이더 기반 연산, WebAssembly(WASM) 저지연 바이너리 파이프라인, W3C Web Crypto 표준의 영지식(Zero-Knowledge) 암호학 아키텍처, 그리고 통계적 확률론과 복리 수식 기반의 퀀트 금융 모델링을 직접 구현하고 오픈소스로 검증합니다.