From c3c2773532d47a24bdde84dfba4b19840cd87243 Mon Sep 17 00:00:00 2001 From: zyqunix Date: Sat, 12 Apr 2025 18:18:29 +0200 Subject: [PATCH] add mic test thing --- microphone/index.html | 19 ++++++++++++ microphone/index.js | 67 +++++++++++++++++++++++++++++++++++++++++++ microphone/style.css | 25 ++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 microphone/index.html create mode 100644 microphone/index.js create mode 100644 microphone/style.css diff --git a/microphone/index.html b/microphone/index.html new file mode 100644 index 0000000..d0b7087 --- /dev/null +++ b/microphone/index.html @@ -0,0 +1,19 @@ + + + + + + Mic Test + + + + +

Microphone Test

+
+ + +
+ + + + \ No newline at end of file diff --git a/microphone/index.js b/microphone/index.js new file mode 100644 index 0000000..ae2a931 --- /dev/null +++ b/microphone/index.js @@ -0,0 +1,67 @@ +const btn = document.getElementById('btn'); +const canvas = document.getElementById('visualizer'); +const ctx = canvas.getContext('2d'); + +let audioContext; +let analyser; +let dataArray; +let micStream; +let animationId; +let isListening = false; + +async function startMic() { + audioContext = new (window.AudioContext || window.webkitAudioContext)(); + micStream = await navigator.mediaDevices.getUserMedia({ audio: true }); + const source = audioContext.createMediaStreamSource(micStream); + + analyser = audioContext.createAnalyser(); + analyser.fftSize = 512; + + const bufferLength = analyser.fftSize; + dataArray = new Uint8Array(bufferLength); + + source.connect(analyser); + draw(); +} + +function stopMic() { + micStream.getTracks().forEach(track => track.stop()); + audioContext.close(); + cancelAnimationFrame(animationId); +} + +function draw() { + animationId = requestAnimationFrame(draw); + + analyser.getByteTimeDomainData(dataArray); + + ctx.fillStyle = '#fff'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.lineWidth = 2; + ctx.strokeStyle = '#000'; + ctx.beginPath(); + + const sliceWidth = canvas.width / dataArray.length; + let x = 0; + + for (let i = 0; i < dataArray.length; i++) { + const v = dataArray[i] / 128.0; + const y = v * canvas.height / 2; + + i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y); + x += sliceWidth; + } + + ctx.lineTo(canvas.width, canvas.height / 2); + ctx.stroke(); +} + +btn.addEventListener('click', async () => { + if (!isListening) { + await startMic(); + } else { + stopMic(); + } + isListening = !isListening; +}); diff --git a/microphone/style.css b/microphone/style.css new file mode 100644 index 0000000..744e837 --- /dev/null +++ b/microphone/style.css @@ -0,0 +1,25 @@ +@import url(/global.css); + +canvas { + width: 100%; + background-color: #fff; + border-radius: 10px; + pointer-events: none; +} + +button { + cursor: pointer; + background-color: #2a2a2a; + padding: 7px; + color: #c0c0c0; + border: #2c2c2c solid 2px; + border-radius: 4px; + margin-top: 10px; + font-size: 16px; +} + +button:hover { + background-color: #2c2c2c; + color: #d0d0d0; + border: #2e2e2e solid 2px; +} \ No newline at end of file