Audio Meter

Basic usage

Requests microphone access and feeds the live level into bars, line, and ring variants.

<script setup lang="ts"> import { onBeforeUnmount, ref } from "vue"; import { NmorphAudioMeter, NmorphButton, NmorphSpace, } from "@nmorph/nmorph-ui-kit"; const level = ref(0); const listening = ref(false); const errorMessage = ref(""); let stream: MediaStream | null = null; let audioContext: AudioContext | null = null; let animationId = 0; const createAudioContext = () => { const AudioContextConstructor = window.AudioContext || (window as "undefined" & { webkitAudioContext?: typeof AudioContext }) .webkitAudioContext; if (!AudioContextConstructor) throw new Error("AudioContext is unavailable."); return new AudioContextConstructor(); }; const stopMeter = () => { listening.value = false; level.value = 0; if (animationId) cancelAnimationFrame(animationId); animationId = 0; stream?.getTracks().forEach((track) => track.stop()); stream = null; if (audioContext) void audioContext.close(); audioContext = null; }; const startMeter = async () => { if (listening.value) return; errorMessage.value = ""; try { if (!navigator.mediaDevices?.getUserMedia) throw new Error("Media devices are unavailable."); stream = await navigator.mediaDevices.getUserMedia({ audio: true }); audioContext = createAudioContext(); const source = audioContext.createMediaStreamSource(stream); const analyser = audioContext.createAnalyser(); analyser.fftSize = 256; source.connect(analyser); const samples = new Uint8Array(analyser.frequencyBinCount); listening.value = true; const updateLevel = () => { analyser.getByteTimeDomainData(samples); let sum = 0; samples.forEach((sample) => { const centered = (sample - 128) / 128; sum += centered * centered; }); level.value = Math.min(Math.sqrt(sum / samples.length) * 2.8, 1); animationId = requestAnimationFrame(updateLevel); }; updateLevel(); } catch { errorMessage.value = "Microphone access is unavailable."; stopMeter(); } }; onBeforeUnmount(stopMeter); </script><template> <div class="audio-meter-basic-usage"> <NmorphSpace align="center" :wrap="true"> <NmorphButton design="nmorph" thickness="basic" @click="listening ? stopMeter() : startMeter()" > {{ listening ? "Stop microphone" : "Start microphone" }} </NmorphButton> <span v-if="errorMessage" class="audio-meter-basic-usage__error"> {{ errorMessage }} </span> </NmorphSpace> <div class="audio-meter-basic-usage__meters"> <NmorphAudioMeter :value="level" label="Microphone level" /> <NmorphAudioMeter :value="level" variant="line" label="Line level" /> <NmorphAudioMeter :value="level" variant="ring" label="Ring level" /> </div> </div> </template>

NmorphAudioMeter Api

Attributes

Resolution is not supported

Open the documentation on a device with a screen size of at least 375px by 640px.