/* * Filename: envelope.c * * Description: * * * Version: * Created: Wed Oct 30 17:15:02 2019 * Revision: None * Author: Rachel Fae Fox (foxiepaws),fox@foxiepa.ws * */ #include "../common.h" #include #include #include typedef enum EnvState {_e_off,_e_attack, _e_attackrelease, _e_decay, _e_sustain,_e_release, _e_finished} EnvState; typedef struct Envelope { // these values are in samples. unsigned int attack; unsigned int decay; unsigned int release; float sustain_level; float max_level; float min_level; float level; bool gate; unsigned long int t; EnvState envstate; bool ar; bool sustain; float(*process)(struct Envelope *,EngineState *); } Envelope; /* if (self->ar) { float diff = (self->max_level - self->min_level) / (float) self->attack; if (self->t <= self->attack && self->gate) { self->level = self->state * diff; self->state++; } else if (self->sustain && self->gate) { self->level = self->max_level; } else if (self->state < self->attack && self->state > 0){ self->level = self->level - diff; self->state--; } else if ((self->state - self->attack) <= self->release) { self->level = self->max_level - ((self->state - self->attack) * diff); self->state++; } } return self->level; return self->gate ? self->max_level : self-> min_level; */ float envelope_process(Envelope *self, EngineState *t) { switch (self->envstate) { case _e_off: //printf("_off\n"); if (self->gate) { self->t = 0; self->envstate = _e_attack; return envelope_process(self, t); } break; case _e_attack: //printf("_attack: %i\n", self->t); if (self->gate) { if ( self->t < self->attack ) { float stepsize = (self->max_level - self->min_level) / self->attack; self->t++; return self->t * stepsize; } else { if (self->ar) { self->t = 0; self->envstate = _e_sustain; return self->max_level; } else { self->t = 0; self->envstate = _e_decay; return self->max_level; } } } else { self->envstate = _e_attackrelease; return envelope_process(self, t); } break; case _e_decay: // printf("_decay: %i\n", self->t); if (self->gate) { if (self->t < self->decay) { float stepsize = (self->max_level - self->sustain_level) / self->decay; self->t++; return (self->max_level - (self->t * stepsize)); } else { self->envstate = _e_sustain; return self->sustain_level; } } else { self->envstate = _e_attackrelease; return envelope_process(self, t); } break; case _e_sustain: //printf("_sustain\n", self->t); if (!self->sustain) { self->envstate = _e_release; self->t = 0; return envelope_process(self, t); } if (!self->gate) { self->t = 0; self->envstate = _e_release; if (self->ar) return self->max_level; return self->sustain_level; } if (self->ar) return self->max_level; return self->sustain_level; break; case _e_release: // printf("_release: %i\n", self->t); if (self->gate && self->sustain) { // reset envelope. self->envstate=_e_off; return envelope_process(self,t); } if (self->t < self->release) { float stepsize = ((self->ar ? self->max_level : self->sustain_level) - self->min_level) / self->release; self->t++; return (self->ar ? self->max_level : self->sustain_level) - (stepsize * self->t); } else { self->envstate = _e_off; return self->min_level; } break; case _e_attackrelease: if (self->gate) { //reset envelope self->envstate=_e_off; return envelope_process(self,t); } return 0.0f; break; } return 0.0f; // if this is reached, something went wrong or an unhandled function was used. } Envelope* envelope_new() { Envelope *e = malloc(sizeof(Envelope)); e->process = envelope_process; e->envstate = _e_off; e->t = 0; e->max_level = 1.0f; e->sustain_level = 1.0f; e->min_level = 0.0f; return e; }