[React] 사용자 음성 받아 주파수 계산하기

SeonDal·2023년 11월 24일

최대한 심플하게 구성하고자 했다

AudioContext.ts

음성 미디어를 활용하기 위해 기본 내장 API인 AudioContext를 사용해야한다.
편하게 사용하기 위해 정의해놓자

App.tsx

const audioCtx = AudioContext.getAudioContext();
const analyser = AudioContext.getAnalyser();
const buf = new Float32Array(2048);

시작 버튼을 누르면 input을 받는다.
navigator.mediaDevices.getUserMedia() 를 이용하여 기기에 내장된 미디어에 접근한다

오디오를 한번이 아닌 지속적으로 받아야하므로 suspended되었을 때 자동으로 재개하는 코드를 추가하고

아래 useEffect의 인자로 관리하기 위해 state를 바꿔준다
source는 오디오 컨텍스트를 이용하여 mediaStreamSource로 만들어준다

const [source, setSource] = useState<MediaStreamAudioSourceNode>();
const [started, setStart] = useState(false);

...

useEffect(() => {
    if (source != null) {
      source.connect(analyser);
    }
}, [source]);

source가 들어가면 (값이 변하면) 자동으로 analyser에 연결된다

  setInterval(updatePitch, 100);

updtePitch 함수에서는 오디오컨텍스트의 analyser를 이용해 데이터를 받아오고 correlate함수를 이용하여 주파수를 계산한다

그렇게 나온 결과값에 따라 음정(note)을 계산하고 계이름(sym)과 옥타브(scl)를 알아내서 상태로 넣어주면

화면에 표현된다! 끝

correlate() 함수는 수학적 개념을 포함하고 있어서 많이 길고 복잡하기에 같은 시리즈 다른 글로 남길 예정이다

utils.ts

const noteFromPitch = (frequency: number) => {
  var noteNum = 12 * (Math.log(frequency / 440) / Math.log(2));
  return Math.round(noteNum) + 69;
};

export { noteFromPitch };

NoteFromPitch는 주파수로부터 음정을 계산하는 함수다
고등학교 음악 수업에서 배웠던 내용만으로는 턱없이 부족하여 구글링이 필요하다



REF

profile
김선달 개발블로그

0개의 댓글