All pastes #884687 Raw Edit

Someone

public cpp v1 · immutable
#884687 ·published 2008-01-30 15:11 UTC
rendered paste body
#ifndef ENVELOPE_H#define ENVELOPE_H#include "arke.h"#include "IModule.h"#include <vector>class Envelope : public IModule{public:	Envelope();	~Envelope();	void noteOn();	void noteOff();	void reset();	bool update();	void process(float* buffer, uint sampleFrames);	float run(uint samplesSince);	void setAdsr(float att, float dec, float sus, float rel);private:	struct Stage	{		float speed;		float target;		float threshold;	};	bool active;	bool gate;	uint stage;	float position;	uint loopStart;	uint loopEnd;	Stage stages[4];};#endif //ENVELOPE_H#include "Envelope.h"#include "arke.h"#include <cmath>const float kThreshold = 0.001;Envelope::Envelope(){	position = 0.0f;	stage = 0;	setAdsr(1.0f, 1.0f, 1.0f, 1.0f);}Envelope::~Envelope(){}void Envelope::setAdsr(float att, float dec, float sus, float rel){	stages[0].target = 1.25f;	stages[0].threshold = 1.0f;	stages[0].speed = att;	stages[1].target = sus;	stages[1].threshold = sus;	stages[1].speed = dec;	stages[2].target = sus;	stages[2].threshold = sus;	stages[2].speed = dec;	stages[3].target = 0.0f;	stages[3].threshold = 0.0f;	stages[3].speed = rel;}void Envelope::noteOff(){	gate = false;}void Envelope::noteOn(){	gate = true;	active = true;	position = 0.0f;	stage = 0;}void Envelope::reset(){	active = false;	gate = false;}bool Envelope::update(){	if(!gate) {		stage = 3;	}		if(fabs(position - stages[stage].threshold) < kThreshold) {		position = stages[stage].threshold;		stage++;		if(stage == 4) {			reset();		}		if((stage == 3) && gate) {			stage = 2;		}	}	return active;}void Envelope::process(float *buffer, uint sampleFrames){	// linear interpolation between envelope updates (user won't notice or care)	float target = run(sampleFrames);	float inc = (target - position) / (float) sampleFrames;	while(sampleFrames--) {		*buffer *= position;		position += inc;		buffer++;	}}float Envelope::run(uint samplesSince){	/* The envelope is produced by an RC filter receiving different	 * coefficients depending on stage, receiving the stage target	 * as input. This would usually mean processing for samplesSince	 * samples, but I'm a cheap bastard so the filter is processed at 	 * samplerate/samplesSince for one iteration. Slower for one or 	 * two samples, faster for anything more since this function now	 * becomes an O(1) operation. Yay!	 */	// number of samples at sampleRate 	float timeConstant = stages[stage].speed * sampleRate / 1000.0f;	// adjusted rate	timeConstant = timeConstant / (float) samplesSince;	// coefficient, adjusted to the new sampleRate	float coeff = powf(1000.0f, -1.0f / timeConstant);	// one "iteration"	position = coeff * position + (1.0f - coeff) * stages[stage].target;	// clip the value	if(position > 1.0f) {		position = 1.0f;	} else if(position < 0.0f) {		position = 0.0f;	}	// return	return position;}