@@ -4,6 +4,7 @@ import { NormalRange, Time } from "../../core/type/Units";
44import { optionsFromArguments } from "../../core/util/Defaults" ;
55import { isArray , isObject , isString } from "../../core/util/TypeCheck" ;
66import { connectSignal , Signal } from "../../signal/Signal" ;
7+ import { OfflineContext } from "../../core/context/OfflineContext" ;
78
89type BasicEnvelopeCurve = "linear" | "exponential" ;
910type InternalEnvelopeCurve = BasicEnvelopeCurve | number [ ] ;
@@ -438,6 +439,27 @@ export class Envelope extends ToneAudioNode<EnvelopeOptions> {
438439 return this ;
439440 }
440441
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+
441463 dispose ( ) : this {
442464 super . dispose ( ) ;
443465 this . _sig . dispose ( ) ;
0 commit comments