Skip to content

Commit 17a885f

Browse files
committed
mic-tester: use toasting service from naive-ui, and also lint it all up
1 parent db63103 commit 17a885f

File tree

2 files changed

+59
-52
lines changed

2 files changed

+59
-52
lines changed
Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { ref, onBeforeUnmount } from 'vue';
1+
import { onBeforeUnmount, ref } from 'vue';
22

3-
export function useMicrophoneService() {
3+
// messageSender has to support error(text) method for notifying the user of errors
4+
export function useMicrophoneService(messageSender) {
45
let audioContext: AudioContext | null = null;
56
let delayNode: DelayNode | null = null;
67
let sourceNode: MediaStreamAudioSourceNode | null = null;
@@ -10,48 +11,8 @@ export function useMicrophoneService() {
1011
const isPlaying = ref(false);
1112
const loudnessLevel = ref(0); // Observable for loudness
1213

13-
const startMicReplay = async () => {
14-
if (!audioContext) {
15-
audioContext = new (window.AudioContext || window.webkitAudioContext)();
16-
}
17-
18-
try {
19-
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
20-
} catch (err) {
21-
console.error('Microphone access denied:', err);
22-
alert('Microphone access denied (the error is also in the console):', err);
23-
return;
24-
}
25-
26-
sourceNode = audioContext.createMediaStreamSource(stream);
27-
delayNode = audioContext.createDelay(1.0);
28-
delayNode.delayTime.value = 1.0;
29-
30-
analyserNode = audioContext.createAnalyser();
31-
analyserNode.fftSize = 256;
32-
33-
// Connect nodes: mic -> delay -> speakers
34-
sourceNode.connect(delayNode);
35-
delayNode.connect(audioContext.destination);
36-
sourceNode.connect(analyserNode);
37-
38-
isPlaying.value = true;
39-
measureLoudness();
40-
};
41-
42-
const stopMicReplay = () => {
43-
if (audioContext && stream) {
44-
const tracks = stream.getTracks();
45-
tracks.forEach(track => track.stop());
46-
audioContext.close();
47-
audioContext = null;
48-
isPlaying.value = false;
49-
loudnessLevel.value = 0;
50-
}
51-
};
52-
5314
// Measure loudness and update loudness bar
54-
const measureLoudness = () => {
15+
function measureLoudness() {
5516
const dataArray = new Uint8Array(analyserNode!.frequencyBinCount);
5617

5718
const updateLoudness = () => {
@@ -69,10 +30,50 @@ export function useMicrophoneService() {
6930
requestAnimationFrame(updateLoudness);
7031
}
7132
};
72-
7333
updateLoudness();
7434
};
7535

36+
const startMicReplay = async () => {
37+
if (!audioContext) {
38+
audioContext = new (window.AudioContext || window.webkitAudioContext)();
39+
}
40+
41+
try {
42+
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
43+
}
44+
catch (err) {
45+
console.error('Microphone access denied:', err);
46+
messageSender.error('Microphone access denied (the error is also in the console):', err);
47+
return;
48+
}
49+
50+
sourceNode = audioContext.createMediaStreamSource(stream);
51+
delayNode = audioContext.createDelay(1.0);
52+
delayNode.delayTime.value = 1.0;
53+
54+
analyserNode = audioContext.createAnalyser();
55+
analyserNode.fftSize = 256;
56+
57+
// Connect nodes: mic -> delay -> speakers
58+
sourceNode.connect(delayNode);
59+
delayNode.connect(audioContext.destination);
60+
sourceNode.connect(analyserNode);
61+
62+
isPlaying.value = true;
63+
measureLoudness();
64+
};
65+
66+
function stopMicReplay() {
67+
if (audioContext && stream) {
68+
const tracks = stream.getTracks();
69+
tracks.forEach(track => track.stop());
70+
audioContext.close();
71+
audioContext = null;
72+
isPlaying.value = false;
73+
loudnessLevel.value = 0;
74+
}
75+
};
76+
7677
// Cleanup on service destruction
7778
onBeforeUnmount(() => {
7879
stopMicReplay();
@@ -82,6 +83,6 @@ export function useMicrophoneService() {
8283
startMicReplay,
8384
stopMicReplay,
8485
loudnessLevel,
85-
isPlaying
86+
isPlaying,
8687
};
8788
}

src/tools/mic-tester/mic-tester.vue

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
<script setup lang="ts">
2-
import { useMicrophoneService } from './mic-tester.service';
32
import { useI18n } from 'vue-i18n';
3+
import { useMessage } from 'naive-ui';
4+
import { useMicrophoneService } from './mic-tester.service';
5+
6+
const message = useMessage();
47
58
const { t } = useI18n();
6-
const { startMicReplay, stopMicReplay, loudnessLevel, isPlaying } = useMicrophoneService();
9+
const { startMicReplay, stopMicReplay, loudnessLevel, isPlaying } = useMicrophoneService(message);
710
</script>
811

912
<template>
1013
<div>
1114
<c-card>
1215
<div class="control-buttons">
13-
<c-button @click="startMicReplay" :disabled="isPlaying">{{ t('tools.mic-tester.start-button-text') }}</c-button>
14-
<c-button @click="stopMicReplay" :disabled="!isPlaying">{{ t('tools.mic-tester.stop-button-text') }}</c-button>
16+
<c-button :disabled="isPlaying" @click="startMicReplay">
17+
{{ t('tools.mic-tester.start-button-text') }}
18+
</c-button>
19+
<c-button :disabled="!isPlaying" @click="stopMicReplay">
20+
{{ t('tools.mic-tester.stop-button-text') }}
21+
</c-button>
1522
</div>
1623

1724
<!-- Loudness Meter -->
18-
<div id="loudnessMeter">
19-
<div id="loudnessBar" :style="{ width: loudnessLevel + '%' }">
20-
</div>
25+
<div id="loudnessMeter">
26+
<div id="loudnessBar" :style="{ width: `${loudnessLevel}%` }" />
2127
</div>
2228
</c-card>
2329
</div>

0 commit comments

Comments
 (0)