@@ -81,43 +81,85 @@ class AudioStreamProcessor extends AudioWorkletProcessor {
8181 switch ( e . data ?. type ) {
8282 case 'audio' :
8383 this . _bq . push ( new Float32Array ( e . data . data ) ) ;
84+ if ( this . _fadeOutActive ) {
85+ this . _fadeOutActive = false ;
86+ this . _fadeOutCounter = 0 ;
87+ }
8488 break ;
8589 case 'end' :
8690 this . _shouldStop = true ;
8791 break ;
92+ case 'fadeAndClear' :
93+ this . _fadeOutActive = true ;
94+ this . _fadeOutCounter = 0 ;
95+ break ;
8896 case 'clear' :
8997 this . _bq . clear ( ) ;
9098 this . _shouldStop = false ;
9199 break ;
92100 }
93101 } ;
94102 this . _shouldStop = false ;
103+
104+ this . _fadeOutDurationMs = 30 ;
105+ // sampleRate is part of AudioWorkletGlobalScope
106+ // eslint-disable-next-line no-undef
107+ this . _sampleRate = sampleRate ;
108+ this . _fadeOutSamplesCount = Math . floor (
109+ ( this . _fadeOutDurationMs * this . _sampleRate ) / 1000 ,
110+ ) ;
111+ this . _fadeOutActive = false ;
112+ this . _fadeOutCounter = 0 ;
95113 }
96114
97115 process ( inputs , outputs ) {
98116 const output = outputs [ 0 ] ;
99117 const frames = output [ 0 ] . length ;
100- const chans = output . length ;
118+ const channels = output . length ;
101119
102120 const block = this . _bq . read ( ) ;
103121
104122 if ( block ) {
105- for ( let ch = 0 ; ch < chans ; ch ++ ) {
123+ for ( let ch = 0 ; ch < channels ; ch ++ ) {
106124 const out = output [ ch ] ;
107125 for ( let i = 0 ; i < frames ; i ++ ) {
108- out [ i ] = block [ i * chans + ch ] ;
126+ let sample = block [ i * channels + ch ] ?? 0 ;
127+
128+ // Apply fade out if active
129+ if ( this . _fadeOutActive ) {
130+ const fadeProgress =
131+ this . _fadeOutCounter / this . _fadeOutSamplesCount ;
132+ const gain = 1 - Math . min ( fadeProgress , 1 ) ;
133+ sample *= gain ;
134+ }
135+
136+ out [ i ] = sample ;
109137 }
110138 }
111- } else {
112- if ( this . _shouldStop ) {
113- // Stop worklet once we've finished playback
114- this . port . postMessage ( { type : 'ended' } ) ;
115- return false ;
116- }
117139
118- for ( let ch = 0 ; ch < chans ; ch ++ ) {
119- output [ ch ] . fill ( 0 ) ;
140+ // If we're currently fading out,
141+ // increment the counter and end if complete
142+ if ( this . _fadeOutActive ) {
143+ this . _fadeOutCounter += frames ;
144+
145+ if ( this . _fadeOutCounter >= this . _fadeOutSamplesCount ) {
146+ this . _fadeOutActive = false ;
147+ this . _fadeOutCounter = 0 ;
148+ this . _bq . clear ( ) ;
149+ this . port . postMessage ( { type : 'ended' } ) ;
150+ }
120151 }
152+
153+ return true ;
154+ }
155+
156+ if ( this . _shouldStop ) {
157+ this . port . postMessage ( { type : 'ended' } ) ;
158+ return false ;
159+ }
160+
161+ for ( let ch = 0 ; ch < channels ; ch ++ ) {
162+ output [ ch ] . fill ( 0 ) ;
121163 }
122164
123165 return true ;
0 commit comments