1
- import { ref , onBeforeUnmount } from 'vue' ;
1
+ import { onBeforeUnmount , ref } from 'vue' ;
2
2
3
- export function useMicrophoneService ( ) {
3
+ // messageSender has to support error(text) method for notifying the user of errors
4
+ export function useMicrophoneService ( messageSender ) {
4
5
let audioContext : AudioContext | null = null ;
5
6
let delayNode : DelayNode | null = null ;
6
7
let sourceNode : MediaStreamAudioSourceNode | null = null ;
@@ -10,48 +11,8 @@ export function useMicrophoneService() {
10
11
const isPlaying = ref ( false ) ;
11
12
const loudnessLevel = ref ( 0 ) ; // Observable for loudness
12
13
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
-
53
14
// Measure loudness and update loudness bar
54
- const measureLoudness = ( ) => {
15
+ function measureLoudness ( ) {
55
16
const dataArray = new Uint8Array ( analyserNode ! . frequencyBinCount ) ;
56
17
57
18
const updateLoudness = ( ) => {
@@ -69,10 +30,50 @@ export function useMicrophoneService() {
69
30
requestAnimationFrame ( updateLoudness ) ;
70
31
}
71
32
} ;
72
-
73
33
updateLoudness ( ) ;
74
34
} ;
75
35
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
+
76
77
// Cleanup on service destruction
77
78
onBeforeUnmount ( ( ) => {
78
79
stopMicReplay ( ) ;
@@ -82,6 +83,6 @@ export function useMicrophoneService() {
82
83
startMicReplay,
83
84
stopMicReplay,
84
85
loudnessLevel,
85
- isPlaying
86
+ isPlaying,
86
87
} ;
87
88
}
0 commit comments