@@ -12,9 +12,11 @@ import {VirtualAudioNode} from './VirtualAudioNode.mjs';
1212const CHANNEL_NAMES = [ 'Left' , 'Right' , 'Center' , 'Bass (LFE)' , 'Left Surround' , 'Right Surround' ] ;
1313
1414export class AudioChannelMixer extends AbstractAudioModule {
15- constructor ( ) {
15+ constructor ( configManager ) {
1616 super ( 'AudioChannelMixer' ) ;
1717
18+ this . configManager = configManager ;
19+
1820 this . channelConfigs = null ;
1921 this . masterConfig = null ;
2022
@@ -27,8 +29,8 @@ export class AudioChannelMixer extends AbstractAudioModule {
2729 this . masterElements = null ;
2830 }
2931
30- needsUpscaler ( ) {
31- return this . channelSplitter !== null ;
32+ async getChannelCount ( ) {
33+ return this . configManager . getChannelCount ( ) ;
3234 }
3335
3436 getElement ( ) {
@@ -468,8 +470,6 @@ export class AudioChannelMixer extends AbstractAudioModule {
468470 return ;
469471 }
470472
471- this . updateNodes ( ) ;
472-
473473 this . channelNodes . forEach ( ( nodes ) => {
474474 const analyser = this . audioContext . createAnalyser ( ) ;
475475 analyser . fftSize = 256 ;
@@ -481,6 +481,7 @@ export class AudioChannelMixer extends AbstractAudioModule {
481481 masterAnalyzer . fftSize = 256 ;
482482 this . getOutputNode ( ) . connect ( masterAnalyzer ) ;
483483 this . masterNodes . analyzer = masterAnalyzer ;
484+ this . updateNodes ( ) ;
484485 }
485486
486487 destroyAnalyzers ( skipDisconnect = false ) {
@@ -504,7 +505,6 @@ export class AudioChannelMixer extends AbstractAudioModule {
504505 this . masterNodes . analyzer . disconnect ( ) ;
505506 }
506507 this . masterNodes . analyzer = null ;
507-
508508 this . updateNodes ( ) ;
509509 }
510510
@@ -539,7 +539,7 @@ export class AudioChannelMixer extends AbstractAudioModule {
539539 preGain : new VirtualAudioNode ( `AudioChannelMixer preGain ${ i } ` ) ,
540540 preMerge : new VirtualAudioNode ( `AudioChannelMixer preMerge ${ i } ` ) ,
541541 equalizer : new AudioEqualizer ( `${ CHANNEL_NAMES [ i ] } ` ) ,
542- compressor : new AudioCompressor ( true , `${ CHANNEL_NAMES [ i ] } ` ) ,
542+ compressor : new AudioCompressor ( `${ CHANNEL_NAMES [ i ] } ` ) ,
543543 } ;
544544
545545 nodes . compressor . setupNodes ( audioContext ) ;
@@ -554,6 +554,7 @@ export class AudioChannelMixer extends AbstractAudioModule {
554554 nodes . postSplit . connect ( nodes . equalizer . getInputNode ( ) ) ;
555555 nodes . equalizer . getOutputNode ( ) . connect ( nodes . compressor . getInputNode ( ) ) ;
556556 nodes . compressor . getOutputNode ( ) . connect ( nodes . preGain ) ;
557+ nodes . preGain . connect ( nodes . preMerge ) ;
557558
558559 let oldEqualizerState = nodes . equalizer . hasNodes ( ) ;
559560 let oldCompressorState = nodes . compressor . isEnabled ( ) ;
@@ -584,7 +585,7 @@ export class AudioChannelMixer extends AbstractAudioModule {
584585 analyzer : null ,
585586 postMerge : new VirtualAudioNode ( 'AudioChannelMixer postMerge master' ) ,
586587 equalizer : new AudioEqualizer ( 'Master ' ) ,
587- compressor : new AudioCompressor ( false , 'Master ' ) ,
588+ compressor : new AudioCompressor ( 'Master ' , this . getChannelCount . bind ( this ) ) ,
588589 preGain : new VirtualAudioNode ( `AudioChannelMixer preGain master` ) ,
589590 } ;
590591 this . masterNodes . compressor . setupNodes ( audioContext ) ;
@@ -624,18 +625,39 @@ export class AudioChannelMixer extends AbstractAudioModule {
624625 els . dynButton . classList . toggle ( 'configured' , isEqActive || isCompActive ) ;
625626 }
626627
627- updateNodes ( ) {
628+ async updateNodes ( ) {
628629 if ( ! this . audioContext ) return ;
629630
630631 const gains = this . getChannelGainsFromConfig ( ) ;
631632 if ( ! gains ) {
632633 return ;
633634 }
634635
636+ const numberOfChannels = await this . getChannelCount ( ) . catch ( ( ) => 0 ) ;
637+ if ( numberOfChannels === 0 ) {
638+ return ;
639+ }
640+
635641 const hasNonUnityMasterGain = this . masterConfig . gain !== 1 ;
636642 const isMono = this . masterConfig . mono ;
643+ const needsMasterGain = hasNonUnityMasterGain || isMono ;
644+ const needsAnalyzer = this . needsAnalyzer ( ) ;
645+
646+
647+ const activeChannels = AudioUtils . getActiveChannelsForChannelCount ( Math . min ( numberOfChannels , 6 ) ) ;
648+ if ( numberOfChannels === 1 ) {
649+ activeChannels . push ( 1 ) ; // mono sources are always stereo internally
650+ }
637651
638- if ( hasNonUnityMasterGain || isMono ) {
652+ const hasNonUnityChannelGains = activeChannels . some ( ( i ) => gains [ i ] !== 1 ) ;
653+ const hasActiveNodes = activeChannels . some ( ( i ) => {
654+ const nodes = this . channelNodes [ i ] ;
655+ return nodes . equalizer . hasNodes ( ) || nodes . compressor . isEnabled ( ) ;
656+ } ) ;
657+
658+ const needsMerger = numberOfChannels > 6 || hasNonUnityChannelGains || hasActiveNodes || needsAnalyzer ;
659+ const needsSplitter = needsMerger ; // numberOfChannels > 1 && needsMerger;
660+ if ( needsMasterGain ) {
639661 if ( ! this . masterNodes . gain ) {
640662 this . masterNodes . gain = this . audioContext . createGain ( ) ;
641663 this . masterNodes . preGain . disconnect ( this . getOutputNode ( ) ) ;
@@ -659,73 +681,92 @@ export class AudioChannelMixer extends AbstractAudioModule {
659681 }
660682 }
661683
662- const hasNonUnityChannelGains = gains . some ( ( gain ) => gain !== 1 ) ;
663- const hasActiveNodes = this . channelNodes . some ( ( nodes ) => {
664- return nodes . equalizer . hasNodes ( ) || nodes . compressor . isEnabled ( ) ;
665- } ) ;
666- const needsAnalyzer = this . needsAnalyzer ( ) ;
667- if ( hasActiveNodes || hasNonUnityChannelGains || needsAnalyzer ) {
668- if ( ! this . channelSplitter ) {
669- this . channelSplitter = this . audioContext . createChannelSplitter ( ) ;
670- this . channelMerger = this . audioContext . createChannelMerger ( ) ;
671- this . getInputNode ( ) . disconnect ( this . masterNodes . postMerge ) ;
672- this . getInputNode ( ) . connect ( this . channelSplitter ) ;
673- this . masterNodes . postMerge . connectFrom ( this . channelMerger ) ;
674-
675- this . channelNodes . forEach ( ( nodes , i ) => {
676- nodes . postSplit . connectFrom ( this . channelSplitter , i , 0 ) ;
677- nodes . preGain . connect ( nodes . preMerge ) ;
678- nodes . preMerge . connect ( this . channelMerger , 0 , i ) ;
679- } ) ;
684+ const shouldDestroySplitter = this . channelSplitter && ( ! needsSplitter || activeChannels . length !== this . channelSplitter . numberOfOutputs ) ;
685+ const shouldDestroyMerger = this . channelMerger && ( ! needsMerger || activeChannels . length !== this . channelMerger . numberOfInputs ) ;
686+
687+ // if (!this.channelSplitter && this.channelMerger && (needsSplitter || shouldDestroyMerger)) {
688+ // const mergerActiveChannels = AudioUtils.getActiveChannelsForChannelCount(this.channelMerger.numberOfInputs);
689+ // mergerActiveChannels.forEach((idx, i) => {
690+ // const nodes = this.channelNodes[idx];
691+ // nodes.postSplit.disconnectFrom(this.getInputNode(), 0, 0);
692+ // });
693+ // }
694+
695+ if ( shouldDestroySplitter ) {
696+ const splitterActiveChannels = AudioUtils . getActiveChannelsForChannelCount ( this . channelSplitter . numberOfOutputs ) ;
697+ splitterActiveChannels . forEach ( ( idx , i ) => {
698+ const nodes = this . channelNodes [ idx ] ;
699+ nodes . postSplit . disconnectFrom ( this . channelSplitter , i , 0 ) ;
700+ } ) ;
680701
681- this . emit ( 'upscale' ) ;
682- }
702+ this . channelSplitter . disconnect ( ) ;
703+ this . channelSplitter = null ;
704+ }
683705
684- this . channelNodes . forEach ( ( nodes , i ) => {
685- const gain = gains [ i ] ;
686- if ( gain === 1 ) {
687- if ( nodes . gain ) {
688- nodes . preGain . disconnect ( nodes . gain ) ;
689- nodes . preMerge . disconnectFrom ( nodes . gain ) ;
690- nodes . preGain . connect ( nodes . preMerge ) ;
691- nodes . gain = null ;
692- }
693- } else {
694- if ( ! nodes . gain ) {
695- nodes . gain = this . audioContext . createGain ( ) ;
696- nodes . preGain . disconnect ( nodes . preMerge ) ;
697- nodes . preGain . connect ( nodes . gain ) ;
698- nodes . preMerge . connectFrom ( nodes . gain ) ;
699- }
700-
701- nodes . gain . gain . value = gains [ i ] ;
702- }
706+ if ( shouldDestroyMerger ) {
707+ const mergerActiveChannels = AudioUtils . getActiveChannelsForChannelCount ( this . channelMerger . numberOfInputs ) ;
708+ mergerActiveChannels . forEach ( ( idx , i ) => {
709+ const nodes = this . channelNodes [ idx ] ;
710+ nodes . preMerge . disconnect ( this . channelMerger , 0 , i ) ;
703711 } ) ;
704- } else {
705- if ( this . channelSplitter ) {
706- this . getInputNode ( ) . disconnect ( this . channelSplitter ) ;
707- this . masterNodes . postMerge . disconnectFrom ( this . channelMerger ) ;
708- this . getInputNode ( ) . connect ( this . masterNodes . postMerge ) ;
709-
710- this . channelNodes . forEach ( ( nodes , i ) => {
711- nodes . postSplit . disconnectFrom ( this . channelSplitter , i , 0 ) ;
712- if ( nodes . gain ) {
713- nodes . preGain . disconnect ( nodes . gain ) ;
714- nodes . preMerge . disconnectFrom ( nodes . gain ) ;
715- nodes . gain = null ;
716- } else {
717- nodes . preGain . disconnect ( nodes . preMerge ) ;
718- }
719- nodes . preMerge . disconnect ( this . channelMerger , 0 , i ) ;
720- } ) ;
721712
722- this . channelSplitter . disconnect ( ) ;
723- this . channelMerger . disconnect ( ) ;
713+ this . masterNodes . postMerge . disconnectFrom ( this . channelMerger ) ;
714+ this . getInputNode ( ) . connect ( this . masterNodes . postMerge ) ;
715+ this . channelMerger . disconnect ( ) ;
716+ this . channelMerger = null ;
717+ }
724718
725- this . channelSplitter = null ;
726- this . channelMerger = null ;
727- this . emit ( 'upscale' ) ;
728- }
719+ const shouldCreateSplitter = ! this . channelSplitter && needsSplitter ;
720+ const shouldCreateMerger = ! this . channelMerger && needsMerger ;
721+
722+ if ( shouldCreateSplitter ) {
723+ this . channelSplitter = this . audioContext . createChannelSplitter ( activeChannels . length ) ;
724+ this . getInputNode ( ) . disconnect ( this . masterNodes . postMerge ) ;
725+ this . getInputNode ( ) . connect ( this . channelSplitter ) ;
726+
727+ activeChannels . forEach ( ( idx , i ) => {
728+ const nodes = this . channelNodes [ idx ] ;
729+ nodes . postSplit . connectFrom ( this . channelSplitter , i , 0 ) ;
730+ } ) ;
731+ }
732+
733+ if ( shouldCreateMerger ) {
734+ this . channelMerger = this . audioContext . createChannelMerger ( activeChannels . length ) ;
735+ this . masterNodes . postMerge . connectFrom ( this . channelMerger ) ;
736+
737+ activeChannels . forEach ( ( idx , i ) => {
738+ const nodes = this . channelNodes [ idx ] ;
739+ nodes . preMerge . connect ( this . channelMerger , 0 , i ) ;
740+ } ) ;
729741 }
742+
743+ // if (!needsSplitter && needsMerger && (shouldCreateMerger || shouldDestroySplitter)) {
744+ // activeChannels.forEach((idx, i) => {
745+ // const nodes = this.channelNodes[idx];
746+ // nodes.postSplit.connectFrom(this.getInputNode(), 0, 0);
747+ // });
748+ // }
749+
750+ this . channelNodes . forEach ( ( nodes , i ) => {
751+ const gain = gains [ i ] ;
752+ const neededGainNode = gain !== 1 && needsMerger && activeChannels . includes ( i ) ;
753+ if ( ! neededGainNode ) {
754+ if ( nodes . gain ) {
755+ nodes . preGain . disconnect ( nodes . gain ) ;
756+ nodes . preMerge . disconnectFrom ( nodes . gain ) ;
757+ nodes . preGain . connect ( nodes . preMerge ) ;
758+ nodes . gain = null ;
759+ }
760+ } else {
761+ if ( ! nodes . gain ) {
762+ nodes . gain = this . audioContext . createGain ( ) ;
763+ nodes . preGain . disconnect ( nodes . preMerge ) ;
764+ nodes . preGain . connect ( nodes . gain ) ;
765+ nodes . preMerge . connectFrom ( nodes . gain ) ;
766+ }
767+
768+ nodes . gain . gain . value = gain ;
769+ }
770+ } ) ;
730771 }
731772}
0 commit comments