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

음성 미디어를 활용하기 위해 기본 내장 API인 AudioContext를 사용해야한다.
편하게 사용하기 위해 정의해놓자
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() 함수는 수학적 개념을 포함하고 있어서 많이 길고 복잡하기에 같은 시리즈 다른 글로 남길 예정이다
const noteFromPitch = (frequency: number) => {
var noteNum = 12 * (Math.log(frequency / 440) / Math.log(2));
return Math.round(noteNum) + 69;
};
export { noteFromPitch };
NoteFromPitch는 주파수로부터 음정을 계산하는 함수다
고등학교 음악 수업에서 배웠던 내용만으로는 턱없이 부족하여 구글링이 필요하다