@@ -460,7 +460,11 @@ class SampleNode {
460460 const sampleNodeBus = this . getSampleNodeBus ( bus ) ;
461461 sampleNodeBus . setVolume ( options . volume ) ;
462462
463- this . connectPositionWorklet ( options . start ) ;
463+ this . connectPositionWorklet ( options . start ) . catch ( ( err ) => {
464+ const newErr = new Error ( 'Failed to create PositionWorklet.' ) ;
465+ newErr . cause = err ;
466+ GodotRuntime . error ( newErr ) ;
467+ } ) ;
464468 }
465469
466470 /**
@@ -612,44 +616,34 @@ class SampleNode {
612616 * Sets up and connects the source to the GodotPositionReportingProcessor
613617 * If the worklet module is not loaded in, it will be added
614618 */
615- connectPositionWorklet ( start ) {
616- try {
617- this . _positionWorklet = this . createPositionWorklet ( ) ;
618- this . _source . connect ( this . _positionWorklet ) ;
619- if ( start ) {
620- this . start ( ) ;
621- }
622- } catch ( error ) {
623- if ( error ?. name !== 'InvalidStateError' ) {
624- throw error ;
625- }
626- const path = GodotConfig . locate_file ( 'godot.audio.position.worklet.js' ) ;
627- GodotAudio . ctx . audioWorklet
628- . addModule ( path )
629- . then ( ( ) => {
630- if ( ! this . isCanceled ) {
631- this . _positionWorklet = this . createPositionWorklet ( ) ;
632- this . _source . connect ( this . _positionWorklet ) ;
633- if ( start ) {
634- this . start ( ) ;
635- }
636- }
637- } ) . catch ( ( addModuleError ) => {
638- GodotRuntime . error ( 'Failed to create PositionWorklet.' , addModuleError ) ;
639- } ) ;
619+ async connectPositionWorklet ( start ) {
620+ await GodotAudio . audioPositionWorkletPromise ;
621+ if ( this . isCanceled ) {
622+ return ;
623+ }
624+ this . getPositionWorklet ( ) ;
625+ this . _source . connect ( this . _positionWorklet ) ;
626+ if ( start ) {
627+ this . start ( ) ;
640628 }
641629 }
642630
643631 /**
644- * Creates the AudioWorkletProcessor used to track playback position.
645- * @returns {AudioWorkletNode }
632+ * Get a AudioWorkletProcessor from the pool, or create one if no processor is available.
646633 */
647- createPositionWorklet ( ) {
648- const worklet = new AudioWorkletNode (
649- GodotAudio . ctx ,
650- 'godot-position-reporting-processor'
651- ) ;
652- worklet . port . onmessage = ( event ) => {
634+ getPositionWorklet ( ) {
635+ if ( this . _positionWorklet != null ) {
636+ return ;
637+ }
638+ if ( GodotAudio . audioPositionWorkletPool . length == 0 ) {
639+ this . _positionWorklet = new AudioWorkletNode (
640+ GodotAudio . ctx ,
641+ 'godot-position-reporting-processor'
642+ ) ;
643+ } else {
644+ this . _positionWorklet = GodotAudio . audioPositionWorkletPool . pop ( ) ;
645+ }
646+ this . _positionWorklet . port . onmessage = ( event ) => {
653647 switch ( event . data [ 'type' ] ) {
654648 case 'position' :
655649 this . _playbackPosition = ( parseInt ( event . data . data , 10 ) / this . getSample ( ) . sampleRate ) + this . offset ;
@@ -658,7 +652,6 @@ class SampleNode {
658652 // Do nothing.
659653 }
660654 } ;
661- return worklet ;
662655 }
663656
664657 /**
@@ -688,6 +681,8 @@ class SampleNode {
688681 if ( this . _positionWorklet ) {
689682 this . _positionWorklet . disconnect ( ) ;
690683 this . _positionWorklet . port . onmessage = null ;
684+ this . _positionWorklet . port . postMessage ( { type : 'clear' } ) ;
685+ GodotAudio . audioPositionWorkletPool . push ( this . _positionWorklet ) ;
691686 this . _positionWorklet = null ;
692687 }
693688
@@ -731,7 +726,10 @@ class SampleNode {
731726 const pauseTime = this . isPaused
732727 ? this . pauseTime
733728 : 0 ;
734- this . connectPositionWorklet ( ) ;
729+ if ( this . _positionWorklet != null ) {
730+ this . _positionWorklet . port . postMessage ( { type : 'clear' } ) ;
731+ this . _source . connect ( this . _positionWorklet ) ;
732+ }
735733 this . _source . start ( this . startTime , this . offset + pauseTime ) ;
736734 this . isStarted = true ;
737735 }
@@ -1199,6 +1197,10 @@ const _GodotAudio = {
11991197 driver : null ,
12001198 interval : 0 ,
12011199
1200+ /** @type {Promise } */
1201+ audioPositionWorkletPromise : null ,
1202+ audioPositionWorkletPool : [ ] ,
1203+
12021204 /**
12031205 * Converts linear volume to Db.
12041206 * @param {number } linear Linear value to convert.
@@ -1265,6 +1267,10 @@ const _GodotAudio = {
12651267 onlatencyupdate ( computed_latency ) ;
12661268 } , 1000 ) ;
12671269 GodotOS . atexit ( GodotAudio . close_async ) ;
1270+
1271+ const path = GodotConfig . locate_file ( 'godot.audio.position.worklet.js' ) ;
1272+ GodotAudio . audioPositionWorkletPromise = ctx . audioWorklet . addModule ( path ) ;
1273+
12681274 return ctx . destination . channelCount ;
12691275 } ,
12701276
0 commit comments