11import { EventDispatcher } from "@createjs/core" ;
22import Sound from "./Sound" ;
3+ import Declicker from "./utils/Declicker"
34
45
56export default class AbstractAudioWrapper extends EventDispatcher {
@@ -28,7 +29,7 @@ export default class AbstractAudioWrapper extends EventDispatcher{
2829 }
2930
3031 get muted ( ) {
31- return this . _muted ;
32+ return this . _muted || this . _muting ;
3233 }
3334
3435 constructor ( ) {
@@ -40,12 +41,19 @@ export default class AbstractAudioWrapper extends EventDispatcher{
4041 this . panNode = this . postFxNode = ctx . createPanner ( ) ;
4142 this . panNode . connect ( this . outputNode ) ;
4243
44+ this . declickerNode = ctx . createGain ( ) ;
45+ this . declicker = new Declicker ( this . declickerNode ) ;
46+ this . declicker . on ( "fadeOutComplete" , this . handleDeclickFadeoutComplete , this ) ;
47+
4348 this . muterNode = ctx . createGain ( ) ;
44- this . muterNode . gain . value = 0 ;
4549 this . muterNode . connect ( this . outputNode ) ;
50+ this . _muted = false ;
51+ this . _muting = false ;
4652
4753 this . fxBus = ctx . createGain ( ) ;
48- this . fxBus . connect ( this . panNode ) ;
54+ this . fxBus . connect ( this . declickerNode ) ;
55+ this . declickerNode . connect ( this . muterNode ) ;
56+ this . muterNode . connect ( this . outputNode ) ;
4957
5058 this . _effects = [ ] ;
5159 this . muted = false ;
@@ -55,18 +63,37 @@ export default class AbstractAudioWrapper extends EventDispatcher{
5563 if ( this . _muted ) {
5664 return ;
5765 }
58- this . panNode . disconnect ( this . outputNode ) ;
59- this . panNode . connect ( this . muterNode ) ;
66+ this . declicker . fadeOut ( ) ;
67+ this . _muting = true ;
68+ }
69+
70+ _muteCore ( ) {
6071 this . _muted = true ;
72+ this . _muting = false ;
73+ this . muterNode . gain . value = 0 ;
6174 }
6275
6376 unmute ( ) {
64- if ( ! this . _muted ) {
77+ if ( this . _muting ) {
78+ this . declicker . cancelFade ( ) ;
79+ this . _muting = false ;
80+ } else if ( ! this . _muted ) {
81+ // Not muted or muting, do nothing.
6582 return ;
6683 }
67- this . panNode . disconnect ( this . muterNode ) ;
68- this . panNode . connect ( this . outputNode ) ;
84+
85+ // TODO: If relevant, check to see if any other declick fades are happening. At time of writing, there are no
86+ // other causes for a declick in the abstract audio wrapper, but subclasses that use the declicker might need to
87+ // prevent an unmute from controlling the declicker depending on state.
6988 this . _muted = false ;
89+ this . muterNode . gain . value = 1 ;
90+ this . declicker . fadeIn ( ) ;
91+ }
92+
93+ handleDeclickFadeoutComplete ( e ) {
94+ if ( this . _muting ) {
95+ this . _muteCore ( ) ;
96+ }
7097 }
7198
7299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0 commit comments