Math::SegmentedEnvelope - create/manage/evaluate segmented (curved) envelope
my $e = Math::SegmentedEnvelope->new; # creates random envelope with total duration = 1 $e->segments; # number of segments $e->levels(map $_ * 3, $e->levels); # alter levels $e->durs(map $_ * (rand(0.5) + 0.5), $e->durs); # alter segments durations $e->curves(map $_ + 1, $e->curves); # alter curves $e->level( # alter start level of first segment and set it value to end level of last segment $self->segments, $e->level(0, $self->level(0) - 1) ); $e->curve(0, 3); # set curvative for first segment $e->dur(0, 0.2); # set duration of first segment, so overall duration will changed $e->duration; # get it $e->normalize_duration; # scale segment durs so envelope duration will be 1
or
my $e = Math::SegmentedEnvelope->new( # creates custom adsr envelope # def => [ [0,1,0.8,0.7,0], # levels [0.1,0.2,0.4,0.3], # segment duration [1,2,1,-3] # segment curvative, 0 for flat, 1 for linear and other for curved ], is_morph => 1, # default is 0, smooth envelope with default value morpher inside segment # morpher => sub { ... } # provide custom morpher which will recieve values from 0 to 1, and should return values from 0 to 1 for non-breaking envelope is_hold => 0, # default is 0, will return boundary levels for positions out of envelope duration is_fold_over => 1, # default is 0, will fold envelope instead of wraping for positions out of envelope duration is_wrap_neg => 1, # default is 0, will wrap envelope insted of fold for negative positions ); $e->at(rand); # outputs value at random position $e->table(1024); # returns list of values(lookup table) for current envelope with specified size my $s = $e->static; # creates static evaluator with current envelope parameters (coderef) $s->(rand); # outputs value at random position, but ~ 50% faster
This module gives abstraction of segmeneted envelope. You can create, modify and make static evaluators, which is faster than object method at calling.
at
$definition is a 3 element arrayref of arrayrefs - [[@levels], [@durations], [@curves]]
%params can provide additional params such is_hold,is_morph,morpher,is_fold_over,is_wrap_neg
is_hold
is_morph
morpher
is_fold_over
is_wrap_neg
if nothing specified, than random normalized envelope will be created, but you can provide border_level param to define levels at begin/end
border_level
get value at specified position, position can be out of envelope duration, so it will hold or wrap or fold according configuration [arameters is_hold, is_fold_over and is_wrap_neg
returns static evaluator (i.e. coderef) with current envelope object settings
returns lookup table (i.e. list of values) of specified size(default = 1024) which represents current form of the envelope
get/set flag which turns on value morphing inside segment before applying curving and scaling. default = 0
get/set morpher, default morpher is a sub { sin(PI/2*$_[0]) ** 2 } which smoothes envelope, morpher recieves value from 0 to 1 and should also has same output range
sub { sin(PI/2*$_[0]) ** 2 }
when this flag is turned on than at method and static evaluator with out-of-duration argument will return boundary levels. default = 0
when this flag is turned on and is_hold is turned off than at argument greater than envelope duration will be folded around envelope duration insted of wraping. default = 0
when this flag is turned on and is_hold is turned off than at argument < 0 will be wraped around envelope insted of folding. default = 0
returns number of segments
returns total envelope duration
scale segment durations, so total duration becomes 1
returns current envelope definition (see new method)
new
get/set envelope levels, if setting than provided list must have equal length to levels specified in initial definition (i.e. segments + 1)
segments + 1
get/set level at position
same as levels, but get/sets durations for segments
levels
get/set dur at position
same as durs, but for curves
get/set curvative at position
should be in range [0,1], can be array ref or single value for equal levels at begin/end of envelope
this will work only when passed to constructor to create random envelope, e.g.
Math::SegmentedEnvelope->new(border_level => [0.5,0.2])
handy function which will construct object from passed params, e.g.
use Math::SegmentedEnvelope 'env'; my @arr = map { env } 0..9; # @arr now contains 10 random envelope objects
alternatively you can use modules such as aliased, as
use PDL::Graphics::Prima::Simple; use Math::SegmentedEnvelope; my $e = Math::SegmentedEnvelope->new(is_morph => 1); my $t = $e->table(4096); line_plot($t);
use PDL; interpolate(rand(4095), sequence(4096), pdl($t)); # interpolate at random position
use AnyEvent; # and/or Coro my $e = Math::SegmentedEnvelope->new(is_morph => 1); my $v = 0; # some property my $w = AE::timer(0, 1/60, sub { # refresh $v with 60Hz rate state $s = $e->static; # get static evaluator state $started = AE::now; $v = $s->(AE::now - $started); # or $e->at(..) if $e can be altered somewhere }); my $k = AE::timer(10, 0, sub { undef $w }); # kill previous timer after 10secs my $i = AE::idle(sub { ... }); # animate $v using OpenGL, SDL and etc.. AE::cv->recv;
Math::SegmentedEnvelope->new([[0,1,0.5,0],[0.5,0.5,1],[-3,1/3,4]], is_morph => 1)
GitHub
http://github.com/vividsnow/Math-SegmentedEnvelope
Search MetaCPAN
https://metacpan.org/module/Math::SegmentedEnvelope
SuperCollider, Moo
Yegor Korablev <egor@cpan.org>
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
PDL, Math::Fractal::Noisemaker, Math::NumSeq, Math::PlanePath, OpenGL, SDL, AnyEvent
blending,stacking,duration scaling,delaying,inverting and some common predefined envelopes more docs,tests and examples
To install Math::SegmentedEnvelope, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Math::SegmentedEnvelope
CPAN shell
perl -MCPAN -e shell install Math::SegmentedEnvelope
For more information on module installation, please visit the detailed CPAN module installation guide.