Closed gringrape closed 3 years ago
See https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API
https://mdn.github.io/voice-change-o-matic/ 위의 예제를 보면 이해가 쏙쏙된다. sine wave 는 뭐하는지 모르겠고 frequency bar 를 보면 x 축 진동수에 y 축 진폭인데, 모든 진동수에 대해서 평균값을 구하면 볼륨 메터로 쓰기에 딱 좋을 것 같다.
웨이브폼은 그냥 데이터를 파형으로 중첩시킨거아닐까?
WebRTC media stream source -> Analyzer node -> frequency array -> average -> visualize
참고 - https://github.com/mdn/voice-change-o-matic/blob/gh-pages/scripts/app.js 오래되었지만 여전히 잘동작하는 예제가 있다.
마이크 소스를 스트림으로 얻어서 애널라이저를 연결해주고 애널라이저에서 진동수 진폭 데이터를 setInterval 로 주기적으로 꺼내주면 간단하게 해결된다.
구글의 autoplay 정책 때문에, 버튼을 하나만들어서 다음코드가 버튼이 클릭되면 실행되도록 해야 정상적으로 작동한다.
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
function handleClick() {
const constraints = {
audio: true,
}
const context = new AudioContext();
const analyser = context.createAnalyser();
analyser.fftSize = 2048;
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
const source = context.createMediaStreamSource(stream);
source.connect(analyser);
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength); // 결과물
setInterval(() => {
analyser.getByteFrequencyData(dataArray);
const sum = dataArray.reduce((acc, curr) => acc + curr, 0);
document.getElementById('volume').innerText = `mic volume: ${sum}`;
}, 100);
});
}
function handleClick() {
const constraints = {
audio: true,
}
const context = new AudioContext();
const analyser = context.createAnalyser();
analyser.fftSize = 2048;
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
const source = context.createMediaStreamSource(stream);
source.connect(analyser);
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength); // 결과물
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
function draw() {
let color = 'green';
analyser.getByteFrequencyData(dataArray);
const sum = dataArray.reduce((acc, curr) => acc + curr, 0);
console.log(sum);
if (sum > 30000) {
color = 'red';
}
else if (sum > 20000) {
color = 'yellow';
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = color;
ctx.fillRect(10, 10, sum / 100, 100);
requestAnimationFrame(draw);
}
draw();
});
}
온몸 비틀기는 효과적이다...
Sound data 의 이해
기본 아이디어
Analogue, Digital
Mimic?
불연속적 시간 -> Sample rate
초당 몇개의 데이터가 있어야 할 것 인가? 초당 많은 데이터가 존재할 수록 불연속적인 것이 연속적인 것에 가까워 지므로 sample rate 가 클수록 정확한 음성이 된다.
불연속적 진폭 -> Bit depth
진폭을 값으로 나타낼때, 몇 bit 를 사용할지. 많은 bit 를 사용할 수록 값 사이의 차이가 작아지므로, 연속적인 것에 가까워져서 정확한 모사
결론
내가 보게되는 데이터
배열 데이터를 보게된다. 44100Hz sample rate 라면, 1초의 재생분량에 44100개의 원소를 가진 배열일 것이다. 거기다가 각 원소인 진폭은 bit depth 가 16 bit 라면 65536 개의 서로 다른 값을 가질 수 있을 것이다.