Skip to content

Commit 79721f4

Browse files
Implemented a more reliable, stable mute with declicking on the abstract audio wrapper (parent class of sample, group, and playback)
1 parent 54db4c0 commit 79721f4

1 file changed

Lines changed: 35 additions & 8 deletions

File tree

src/AbstractAudioWrapper.js

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { EventDispatcher } from "@createjs/core";
22
import Sound from "./Sound";
3+
import Declicker from "./utils/Declicker"
34

45

56
export 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

Comments
 (0)