1- import { AudioBuffer , AudioBufferSourceNode , ConstantSourceNode , DynamicsCompressorNode , GainNode } from '../../../src/module' ;
1+ import {
2+ AudioBuffer ,
3+ AudioBufferSourceNode ,
4+ AudioWorkletNode ,
5+ ConstantSourceNode ,
6+ DynamicsCompressorNode ,
7+ GainNode ,
8+ addAudioWorkletModule
9+ } from '../../../src/module' ;
210import { createAudioContext } from '../../helper/create-audio-context' ;
311import { createMinimalAudioContext } from '../../helper/create-minimal-audio-context' ;
412import { createMinimalOfflineAudioContext } from '../../helper/create-minimal-offline-audio-context' ;
@@ -557,13 +565,9 @@ if (typeof window !== 'undefined') {
557565 } ) ;
558566
559567 describe ( 'ratio' , ( ) => {
560- let dynamicsCompressorNode ;
561-
562- beforeEach ( ( ) => {
563- dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
564- } ) ;
565-
566568 it ( 'should return an implementation of the AudioParam interface' , ( ) => {
569+ const dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
570+
567571 expect ( dynamicsCompressorNode . ratio . cancelAndHoldAtTime ) . to . be . a ( 'function' ) ;
568572 expect ( dynamicsCompressorNode . ratio . cancelScheduledValues ) . to . be . a ( 'function' ) ;
569573 expect ( dynamicsCompressorNode . ratio . defaultValue ) . to . equal ( 12 ) ;
@@ -578,24 +582,44 @@ if (typeof window !== 'undefined') {
578582 } ) ;
579583
580584 it ( 'should be readonly' , ( ) => {
585+ const dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
586+
581587 expect ( ( ) => {
582588 dynamicsCompressorNode . ratio = 'anything' ;
583589 } ) . to . throw ( TypeError ) ;
584590 } ) ;
585591
586592 describe ( 'cancelAndHoldAtTime()' , ( ) => {
593+ let dynamicsCompressorNode ;
594+
595+ beforeEach ( ( ) => {
596+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
597+ } ) ;
598+
587599 it ( 'should be chainable' , ( ) => {
588600 expect ( dynamicsCompressorNode . ratio . cancelAndHoldAtTime ( 0 ) ) . to . equal ( dynamicsCompressorNode . ratio ) ;
589601 } ) ;
590602 } ) ;
591603
592604 describe ( 'cancelScheduledValues()' , ( ) => {
605+ let dynamicsCompressorNode ;
606+
607+ beforeEach ( ( ) => {
608+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
609+ } ) ;
610+
593611 it ( 'should be chainable' , ( ) => {
594612 expect ( dynamicsCompressorNode . ratio . cancelScheduledValues ( 0 ) ) . to . equal ( dynamicsCompressorNode . ratio ) ;
595613 } ) ;
596614 } ) ;
597615
598616 describe ( 'exponentialRampToValueAtTime()' , ( ) => {
617+ let dynamicsCompressorNode ;
618+
619+ beforeEach ( ( ) => {
620+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
621+ } ) ;
622+
599623 it ( 'should be chainable' , ( ) => {
600624 expect ( dynamicsCompressorNode . ratio . exponentialRampToValueAtTime ( 1 , 0 ) ) . to . equal ( dynamicsCompressorNode . ratio ) ;
601625 } ) ;
@@ -614,24 +638,48 @@ if (typeof window !== 'undefined') {
614638 } ) ;
615639
616640 describe ( 'linearRampToValueAtTime()' , ( ) => {
641+ let dynamicsCompressorNode ;
642+
643+ beforeEach ( ( ) => {
644+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
645+ } ) ;
646+
617647 it ( 'should be chainable' , ( ) => {
618648 expect ( dynamicsCompressorNode . ratio . linearRampToValueAtTime ( 1 , 0 ) ) . to . equal ( dynamicsCompressorNode . ratio ) ;
619649 } ) ;
620650 } ) ;
621651
622652 describe ( 'setTargetAtTime()' , ( ) => {
653+ let dynamicsCompressorNode ;
654+
655+ beforeEach ( ( ) => {
656+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
657+ } ) ;
658+
623659 it ( 'should be chainable' , ( ) => {
624660 expect ( dynamicsCompressorNode . ratio . setTargetAtTime ( 1 , 0 , 0.1 ) ) . to . equal ( dynamicsCompressorNode . ratio ) ;
625661 } ) ;
626662 } ) ;
627663
628664 describe ( 'setValueAtTime()' , ( ) => {
665+ let dynamicsCompressorNode ;
666+
667+ beforeEach ( ( ) => {
668+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
669+ } ) ;
670+
629671 it ( 'should be chainable' , ( ) => {
630672 expect ( dynamicsCompressorNode . ratio . setValueAtTime ( 1 , 0 ) ) . to . equal ( dynamicsCompressorNode . ratio ) ;
631673 } ) ;
632674 } ) ;
633675
634676 describe ( 'setValueCurveAtTime()' , ( ) => {
677+ let dynamicsCompressorNode ;
678+
679+ beforeEach ( ( ) => {
680+ dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
681+ } ) ;
682+
635683 for ( const [ arrayType , values ] of [
636684 [ 'regular Array' , [ 1 , 0 ] ] ,
637685 [ 'Float32Array' , new Float32Array ( [ 1 , 0 ] ) ]
@@ -646,7 +694,89 @@ if (typeof window !== 'undefined') {
646694 }
647695 } ) ;
648696
649- // @todo automation
697+ describe ( 'automation' , ( ) => {
698+ for ( const [ withADirectConnection , withAnAppendedAudioWorklet ] of description . includes ( 'Offline' )
699+ ? [
700+ [ true , true ] ,
701+ [ true , false ] ,
702+ [ false , true ]
703+ ]
704+ : [ [ true , false ] ] ) {
705+ describe ( `${ withADirectConnection ? 'with' : 'without' } a direct connection and ${
706+ withAnAppendedAudioWorklet ? 'with' : 'without'
707+ } an appended AudioWorklet`, ( ) => {
708+ let renderer ;
709+ let values ;
710+
711+ beforeEach ( async function ( ) {
712+ this . timeout ( 10000 ) ;
713+
714+ values = [ 1 , 0.5 , 0 , - 0.5 , - 1 ] ;
715+
716+ if ( withAnAppendedAudioWorklet ) {
717+ await addAudioWorkletModule ( context , 'base/test/fixtures/gain-processor.js' ) ;
718+ }
719+
720+ renderer = createRenderer ( {
721+ context,
722+ length : context . length === undefined ? lookAhead + 5 : undefined ,
723+ setup ( destination ) {
724+ // Bug #112: Firefox pauses the DynamicsCompressorNode without waiting for the tail time.
725+ const audioBuffer = new AudioBuffer ( { length : lookAhead + 5 , sampleRate : context . sampleRate } ) ;
726+ const audioBufferSourceNode = new AudioBufferSourceNode ( context ) ;
727+ const audioWorkletNode = withAnAppendedAudioWorklet
728+ ? new AudioWorkletNode ( context , 'gain-processor' , { channelCount : 1 } )
729+ : null ;
730+ const dynamicsCompressorNode = createDynamicsCompressorNode ( context ) ;
731+ const masterGainNode = new GainNode ( context , {
732+ gain : withADirectConnection && withAnAppendedAudioWorklet ? 0.5 : 1
733+ } ) ;
734+
735+ audioBuffer . copyToChannel ( new Float32Array ( values ) , 0 ) ;
736+
737+ audioBufferSourceNode . buffer = audioBuffer ;
738+
739+ audioBufferSourceNode . connect ( dynamicsCompressorNode ) ;
740+
741+ if ( withADirectConnection ) {
742+ dynamicsCompressorNode . connect ( masterGainNode ) ;
743+ }
744+
745+ if ( withAnAppendedAudioWorklet ) {
746+ dynamicsCompressorNode . connect ( audioWorkletNode ) . connect ( masterGainNode ) ;
747+ }
748+
749+ masterGainNode . connect ( destination ) ;
750+
751+ return { audioBufferSourceNode } ;
752+ }
753+ } ) ;
754+ } ) ;
755+
756+ describe ( 'without any automation' , ( ) => {
757+ it ( 'should not modify the signal' , function ( ) {
758+ this . timeout ( 10000 ) ;
759+
760+ return renderer ( {
761+ start ( startTime , { audioBufferSourceNode } ) {
762+ audioBufferSourceNode . start ( startTime ) ;
763+ }
764+ } ) . then ( ( channelData ) => {
765+ for ( let i = 0 ; i < lookAhead ; i += 1 ) {
766+ expect ( channelData [ i ] ) . to . equal ( 0 ) ;
767+ }
768+
769+ expect ( channelData [ lookAhead ] ) . to . be . closeTo ( 0.304 , 0.004 ) ;
770+ expect ( channelData [ lookAhead + 1 ] ) . to . be . closeTo ( 0.152 , 0.003 ) ;
771+ expect ( channelData [ lookAhead + 2 ] ) . to . be . closeTo ( 0 , 0.0001 ) ;
772+ expect ( channelData [ lookAhead + 3 ] ) . to . be . closeTo ( - 0.152 , 0.003 ) ;
773+ expect ( channelData [ lookAhead + 4 ] ) . to . be . closeTo ( - 0.304 , 0.004 ) ;
774+ } ) ;
775+ } ) ;
776+ } ) ;
777+ } ) ;
778+ }
779+ } ) ;
650780 } ) ;
651781
652782 // @todo reduction
0 commit comments