flash on 2011-7-9
♥0 |
Line 158 |
Modified 2011-07-09 05:54:35 |
MIT License
archived:2017-03-20 04:14:37
ActionScript3 source code
/**
* Copyright ersin ( http://wonderfl.net/user/ersin )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9pfA
*/
package Hyperion.Modules.Envelope {
import Hyperion.*;
import Hyperion.GUI.*;
import Hyperion.Modules.*;
import flash.utils.*;
public class Envelope extends Module {
public var outSock_mc:Socket;
public var lenSock_mc:Socket;
private var outputPin:OutputPin;
private var lenPin:InputPin;
private var _length:uint;
internal var points:Vector.<EnvelopePoint>;
internal var sustainPointIndex:uint;
private var progress:uint;
private var currentPointIndex:uint;
public var leadInEatsTime:Boolean=true;
public var leadOutEatsTime:Boolean=true;
internal var adsrData:Object;
static var count:uint=0;
var id:uint;
public function Envelope(s:Synth) {
super(s);
id=count++;
lenPin=new InputPin(this);
lenPin.dataType=Pin.Length | Pin.Time | Pin.Pushed;
lenPin.socket=lenSock_mc;
lenPin.addEventListener(PinEvent.Pushed,lenPush);
inputPins.push(lenPin);
outputPin=new OutputPin(this,rend,outputPinReady);
outputPin.dataType=Pin.SoundWave | Pin.Mono | Pin.FreqWave;
outputPin.socket=outSock_mc;
outputPins.push(outputPin);
points=new Vector.<EnvelopePoint>();
initADSR(1200,1,1200,0.6,1200);
}
public override function get configDialogClass():Class {
return EnvelopeConfig;
}
private function lenPush(e:PinEvent):void {
length=lenPin.value;
}
public function set length (s:uint) {
_length=s;
scalePoints(s);
}
public function get length ():uint {
return _length;
}
public override function reset():void {
trace("reset",id);
progress=0;
currentPointIndex=0;
if(lenPin.con && lenPin.con.readyToPlay() && !Boolean(lenPin.con.type & Pin.Pushed)) {
lenPin.con.pullValue();
}
scalePoints(_length);
super.reset();
}
public override function get saveData():* {
if(adsrData) {
return { mode: "adsr", adsrData: adsrData };
} else {
var pointsArray:Array=new Array(points.length);
for(var i:uint=0;i<points.length;++i) {
pointsArray[i]={ value: points[i].value, length: points[i].length };
}
return { mode: "points", points: pointsArray };
}
}
public override function set saveData(d:*):void {
if(d.mode=="adsr") {
initADSR(
d.adsrData.attackTime,
d.adsrData.attackValue,
d.adsrData.decayTime,
d.adsrData.holdValue,
d.adsrData.releaseTime
);
}
}
public function initADSR(attackTime:uint,attackValue:Number,decayTime:uint,holdValue:Number,releaseTime:uint):void {
points=new Vector.<EnvelopePoint>(5);
points[0]=new EnvelopePoint(0,0);
points[1]=new EnvelopePoint(attackValue,attackTime);
points[2]=new EnvelopePoint(holdValue,decayTime);
points[3]=new EnvelopePoint(holdValue,42);
points[4]=new EnvelopePoint(0,releaseTime);
points.fixed=true;
sustainPointIndex=3;
adsrData={ attackTime: attackTime, attackValue: attackValue, decayTime: decayTime, holdValue: holdValue, releaseTime: releaseTime };
}
internal function scalePoints(timeForSustain:int):void {
var scaledPosition:uint=0;
var point:EnvelopePoint;
var lengthToSustainPoint:uint;
var lengthFromSustainPoint:uint;
trace("scaling",timeForSustain,id);
for(var i:uint=0;i<points.length;++i) {
point=points[i];
if(i<sustainPointIndex) {
lengthToSustainPoint+=point.length;
}
if(i>sustainPointIndex) {
lengthFromSustainPoint+=point.length;
}
}
if(leadInEatsTime) {
timeForSustain-=lengthToSustainPoint;
}
if(leadOutEatsTime) {
timeForSustain-=lengthFromSustainPoint;
}
if(timeForSustain<0) timeForSustain=0;
var scaledPosition:uint=0;
for(i=0;i<points.length;++i) {
point=points[i];
if(i==sustainPointIndex) {
point.length=timeForSustain;
}
point.scaledPosition=scaledPosition;
scaledPosition+=point.length;
}
}
private function rend(b:ByteArray,s:uint):uint {
trace("process:",progress,id);
rendloop: for(var i:uint=0;i<s;++i) {
var currentPoint:EnvelopePoint;
var localProgress:uint;
for(;;) {
currentPoint=points[currentPointIndex];
localProgress=progress-currentPoint.scaledPosition;
if(localProgress<currentPoint.length) break;
++currentPointIndex;
trace("next point is:",currentPointIndex,progress,id);
if(currentPointIndex>=points.length) break rendloop;
}
var ratio:Number=Number(localProgress)/currentPoint.length;
var prevPoint:EnvelopePoint=points[currentPointIndex-1];
var sample:Number=prevPoint.value*(1-ratio)+currentPoint.value*ratio;
b.writeFloat(sample);
++progress;
}
return i;
}
private function outputPinReady() {
return points.length>1;
}
public override function destroy():void {
outputPin.destroy();
outputPin=null;
lenPin.removeEventListener(PinEvent.Pushed,lenPush);
lenPin.destroy();
lenPin=null;
points=null;
super.destroy();
}
}
}