@@ -4,6 +4,7 @@ import { NormalRange, Time } from "../../core/type/Units";
4
4
import { optionsFromArguments } from "../../core/util/Defaults" ;
5
5
import { isArray , isObject , isString } from "../../core/util/TypeCheck" ;
6
6
import { connectSignal , Signal } from "../../signal/Signal" ;
7
+ import { OfflineContext } from "../../core/context/OfflineContext" ;
7
8
8
9
type BasicEnvelopeCurve = "linear" | "exponential" ;
9
10
type InternalEnvelopeCurve = BasicEnvelopeCurve | number [ ] ;
@@ -438,6 +439,27 @@ export class Envelope extends ToneAudioNode<EnvelopeOptions> {
438
439
return this ;
439
440
}
440
441
442
+ /**
443
+ * Render the envelope curve to an array of the given length.
444
+ * Good for visualizing the envelope curve
445
+ */
446
+ async asArray ( length : number = 1024 ) : Promise < Float32Array > {
447
+ const duration = length / this . context . sampleRate ;
448
+ const context = new OfflineContext ( 1 , duration , this . context . sampleRate ) ;
449
+ // normalize the ADSR for the given duration with 20% sustain time
450
+ const totalDuration = ( this . toSeconds ( this . attack ) + this . toSeconds ( this . decay ) + this . toSeconds ( this . release ) ) * 1.2 ;
451
+ // @ts -ignore
452
+ const clone = new this . constructor ( Object . assign ( this . get ( ) , {
453
+ attack : duration * this . toSeconds ( this . attack ) / totalDuration ,
454
+ decay : duration * this . toSeconds ( this . decay ) / totalDuration ,
455
+ release : duration * this . toSeconds ( this . release ) / totalDuration ,
456
+ context
457
+ } ) ) . toDestination ( ) as Envelope ;
458
+ clone . triggerAttackRelease ( duration * 0.2 , 0 ) ;
459
+ const buffer = await context . render ( ) ;
460
+ return buffer . getChannelData ( 0 ) ;
461
+ }
462
+
441
463
dispose ( ) : this {
442
464
super . dispose ( ) ;
443
465
this . _sig . dispose ( ) ;
0 commit comments