[ HTML 및 JavaScript ] 웹에서 마이크 엑세스후 FFT 푸리에 변환 방법 - Whitmem
[ HTML 및 JavaScript ] 웹에서 마이크 엑세스후 FFT 푸리에 변환 방법
웹 개발
2025-06-12 22:29 게시 1c16d85717e958753be9

0
0
18
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
예전과 다르게 크롬 및 엣지 기반 브라우저와 같은 HTML 5 기반 환경에서 Javascript 로 마이크 엑세스 등의 기능을 제공한다. 특히 마이크 엑세스 뿐만이 아니라, 이에 관련된 다양한 비주얼라이징 도구, 분석 도구를 클래스 형태로 제공하기 때문에 주파수를 쉽게 계산하고 처리할 수도 있다. 이 게시글에서는 필자가 공부한 내용을 정리한다.
마이크 엑세스
마이크에 엑세스를 요청하고 스트림을 가져오기 위해서 navigator.mediaDevices.getUserMedia를 사용할 수 있다. 이 요청은 비동기 요청이기 때문에 async 비동기 함수에서 await 하여 실행하거나 then 을 사용해서 콜백 형태로 작업을 수행해야 한다. 이 게시글에서는 콜백 형태로 사용을 하고자 한다.
navigator.mediaDevices.getUserMedia({ audio: true }).then( (stream)=>{ } ) .catch( (error)=>{ } );
이 요청에서 엑세스에 성공하면 then 내의 콜백이 실행되고, 실패하면 error catch 절이 실행된다. 엑세스가 허용되었을 때 이 stream 을 활용해서 FFT 분석을 진행할 수 있다.
이 스트림 콜백은 브라우저에서 사용자가 엑세스를 허가한 경우에 실행되는 콜백 영역이다. 아무튼 콜백 엑세스가 허가 된 경우 제공된 stream 정보를 바탕으로 AudioSource 객체를 생성한다. 즉 이 AudioSource 객체는 웹 브라우저에서 다양한 형태에 연결해서 사용할 수 있는 형태로 제공한다.
const audioContext = new window.AudioContext(); const audioSource = audioContext.createMediaStreamSource(stream);
위와 같이 오디오 소스를 생성했으면, 해당 오디오 소스를 통해서 외부 노드에 connect할 수 있다. 대표적으로 존재하는 노드가 Analyser 라는 노드가 있는데, 이 노드는 오디오 스트림을 읽어 푸리에 변환 등의 작업을 제공한다.
주파수 처리를 하기 위해서는 푸리에 변환이 반드시 필요하다. 푸리에 변환은 수학자 푸리에가 만들어낸 계산 공식으로 보통은 DFT 방법이 사용된다. 하지만 DFT 방법은 연산 시간이 매우 오래 걸리기에 일반적인 실시간 오디오 프로세스에는 적합하지 않다. 따라서 FFT 라는 고속 푸리에 변환 기법이 사용되는데 이 푸리에 변환은 일반적인 DFT 와는 연산 방법이 많이 다르고 결과도 규칙적으로 나오기에 조건 사항이 제법 존재한다.
하지만 여기서는 FFT 특징에 대해서는 건너뛰고 호출해서 사용하는 방법만 언급한다.
const audioAnalyser = audioContext.createAnalyser();
아무튼 스트림 소스를 생성한 뒤 Analyser 객체를 생성하여 연결해주면 된다. 그러면 내부적인 푸리에 변환은 모두 처리되어 결과를 계산할 수 있다. 이 audioAnalyser 객체에 대해서 FFT Size를 지정할 수 있는데 그 방법은 아래와 같다.
audioAnalyser.fftSize = 2048;
FFT 사이즈는 반드시 2의 거듭제곱이어야 하는데, 이는 고속 푸리에 변환의 특징이다.
일반 DFT 는 원하는 범위로 계산할 수 있지만, FFT는 그렇지 않다. 고속으로 계산할 수 있는 대신 2의 거듭제곱으로 계산해야하고 그 결과의 반쪽만 사용할 수 있다는 특이점이 존재한다. (계산 결과는 복소수 값으로 절반 영역은 허수 영역이기 때문에 실제 사용하는 영역은 아니다.)
audioSource.connect(audioAnalyser);
AudioSource 의 connect 메서드를 통해 AudioAnalyser 에 연결하면 기본적인 세팅은 모두 끝난다.
const fftBufferLength = audioAnalyser.frequencyBinCount;
이제 실제 푸리에 변환된 바이트 버퍼를 가져와야하는데 웹 브라우저에서 계산하는 FFT 결과는 FFT 사이즈의 절반 값이 실제 데이터 버퍼에 담기기 때문에 (FFT의 특징상 전체 버퍼의 절반이 실제 유효한 데이터이다.) audioAnalyser.frequencyBinCount 로 값을 가져와보면 FFT Size의 절반 값임을 알 수 있다.
const buffer = new Uint8Array(fftBufferLength); audioAnalyser.getByteFrequencyData(buffer);
즉 Uint8Array 의 바이트 공간을 만들 때 위 frequencyBinCount 에서 반환된 FFT Size 의 절반 값으로 할당한 뒤 해당 공간에 Analyser의 getByteFrequencyData 메서드를 통해 실제 유효한 마이크 스트림 버퍼 데이터를 담아주면 된다.
이 작업은 동기 작업이기 때문에 setInterval 등을 통해 반복해주며 값을 가져와준 뒤 원하는 작업을 수행하면 된다.
이제 해당 데이터 버퍼의 각 index 가 고유한 범위의 hz 주파수 값을 의미하며, 값이 진폭 세기를 의미한다. 다만 수치 계산 변환은 필요하다.
댓글 0개
댓글을 작성하는 경우 댓글 처리 방침에 동의하는 것으로 간주됩니다. 댓글을 작성하면 일회용 인증키가 발급되며, 해당 키를 분실하는 경우 댓글을 제거할 수 없습니다. 댓글을 작성하면 사용자 IP가 영구적으로 기록 및 부분 공개됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.