@@ -7,6 +7,7 @@ import { useAiState } from '@/context/ai-state-context';
77import { useSubtitle } from '@/context/subtitle-context' ;
88import { useChatHistory } from '@/context/chat-history-context' ;
99import { audioTaskQueue } from '@/utils/task-queue' ;
10+ import { audioManager } from '@/utils/audio-manager' ;
1011import { toaster } from '@/components/ui/toaster' ;
1112import { useWebSocket } from '@/context/websocket-context' ;
1213import { DisplayText } from '@/services/websocket-service' ;
@@ -45,9 +46,7 @@ export const useAudioTask = () => {
4546 appendAIMessage,
4647 } ) ;
4748
48- // Track current audio and model
49- const currentAudioRef = useRef < HTMLAudioElement | null > ( null ) ;
50- const currentModelRef = useRef < Live2DModel | null > ( null ) ;
49+ // Note: currentAudioRef and currentModelRef are now managed by the global audioManager
5150
5251 stateRef . current = {
5352 aiState,
@@ -57,42 +56,10 @@ export const useAudioTask = () => {
5756 } ;
5857
5958 /**
60- * Stop current audio playback and lip sync
59+ * Stop current audio playback and lip sync (delegates to global audioManager)
6160 */
6261 const stopCurrentAudioAndLipSync = useCallback ( ( ) => {
63- if ( currentAudioRef . current ) {
64- console . log ( 'Stopping current audio and lip sync' ) ;
65- const audio = currentAudioRef . current ;
66- audio . pause ( ) ;
67- audio . src = '' ;
68- audio . load ( ) ;
69-
70- const model = currentModelRef . current ;
71- if ( model && model . _wavFileHandler ) {
72- try {
73- // Release PCM data to stop lip sync calculation in update()
74- model . _wavFileHandler . releasePcmData ( ) ;
75- console . log ( 'Called _wavFileHandler.releasePcmData()' ) ;
76-
77- // Additional reset of state variables as fallback
78- model . _wavFileHandler . _lastRms = 0.0 ;
79- model . _wavFileHandler . _sampleOffset = 0 ;
80- model . _wavFileHandler . _userTimeSeconds = 0.0 ;
81- console . log ( 'Also reset _lastRms, _sampleOffset, _userTimeSeconds as fallback' ) ;
82- } catch ( e ) {
83- console . error ( 'Error stopping/resetting wavFileHandler:' , e ) ;
84- }
85- } else if ( model ) {
86- console . warn ( 'Current model does not have _wavFileHandler to stop/reset.' ) ;
87- } else {
88- console . log ( 'No associated model found to stop lip sync.' ) ;
89- }
90-
91- currentAudioRef . current = null ;
92- currentModelRef . current = null ;
93- } else {
94- console . log ( 'No current audio playing to stop.' ) ;
95- }
62+ audioManager . stopCurrentAudioAndLipSync ( ) ;
9663 } , [ ] ) ;
9764
9865 /**
@@ -151,7 +118,6 @@ export const useAudioTask = () => {
151118 return ;
152119 }
153120 console . log ( 'Found model for audio playback' ) ;
154- currentModelRef . current = model ;
155121
156122 if ( ! model . _wavFileHandler ) {
157123 console . warn ( 'Model does not have _wavFileHandler for lip sync' ) ;
@@ -182,14 +148,13 @@ export const useAudioTask = () => {
182148
183149 // Setup audio element
184150 const audio = new Audio ( audioDataUrl ) ;
185- currentAudioRef . current = audio ;
151+
152+ // Register with global audio manager IMMEDIATELY after creating audio
153+ audioManager . setCurrentAudio ( audio , model ) ;
186154 let isFinished = false ;
187155
188156 const cleanup = ( ) => {
189- if ( currentAudioRef . current === audio ) {
190- currentAudioRef . current = null ;
191- currentModelRef . current = null ;
192- }
157+ audioManager . clearCurrentAudio ( audio ) ;
193158 if ( ! isFinished ) {
194159 isFinished = true ;
195160 resolve ( ) ;
@@ -201,8 +166,8 @@ export const useAudioTask = () => {
201166
202167 audio . addEventListener ( 'canplaythrough' , ( ) => {
203168 // Check for interruption before playback
204- if ( stateRef . current . aiState === 'interrupted' || currentAudioRef . current !== audio ) {
205- console . warn ( 'Audio playback cancelled due to interruption or new audio' ) ;
169+ if ( stateRef . current . aiState === 'interrupted' || ! audioManager . hasCurrentAudio ( ) ) {
170+ console . warn ( 'Audio playback cancelled due to interruption or audio was stopped ' ) ;
206171 cleanup ( ) ;
207172 return ;
208173 }
@@ -228,7 +193,7 @@ export const useAudioTask = () => {
228193 } ;
229194 }
230195
231- if ( currentAudioRef . current === audio ) {
196+ if ( audioManager . hasCurrentAudio ( ) ) {
232197 model . _wavFileHandler . start ( audioDataUrl ) ;
233198 } else {
234199 console . warn ( 'WavFileHandler start skipped - audio was stopped' ) ;
@@ -257,8 +222,6 @@ export const useAudioTask = () => {
257222 type : "error" ,
258223 duration : 2000 ,
259224 } ) ;
260- currentAudioRef . current = null ;
261- currentModelRef . current = null ;
262225 resolve ( ) ;
263226 }
264227 } ) ;
0 commit comments