/* follow.c: Copyright (C) 1994, 1999 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Envelope follower by Paris Smaragdis */ /* Berklee College of Music Csound development team */ /* Copyright (c) August 1994. All rights reserve */ /* Improvements 1999 John ffitch */ #include "stdopcod.h" #include #include "follow.h" static int32_t flwset(CSOUND *csound, FOL *p) { p->wgh = p->max = FL(0.0); p->length = (int32)(*p->len * CS_ESR); if (UNLIKELY(p->length<=0L)) { /* RWD's suggestion */ csound->Warning(csound, Str("follow - zero length!")); p->length = (int32)CS_ESR; } p->count = p->length; return OK; } /* Use absolute value rather than max/min */ static int32_t follow(CSOUND *csound, FOL *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *in = p->in, *out = p->out; MYFLT max = p->max; int32 count = p->count; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n max) max = sig; if (UNLIKELY(--count == 0L)) { p->wgh = max; max = FL(0.0); count = p->length; } out[n] = p->wgh; } p->max = max; p->count = count; return OK; } /* The Jean-Marc Jot (IRCAM) envelope follower, from code by Bram.DeJong@rug.ac.be and James Maccartney posted on music-dsp; Transferred to csound by JPff, 2000 feb 12 */ static int32_t envset(CSOUND *csound, ENV *p) { /* Note - 6.90775527898 -- log(0.001) */ p->lastatt = *p->attack; if (p->lastatt<=FL(0.0)) p->ga = EXP(- FL(69.0775527898)*csound->onedsr); else p->ga = EXP(- FL(6.90775527898)/(CS_ESR* p->lastatt)); p->lastrel = *p->release; if (p->lastrel<=FL(0.0)) p->gr = EXP(- FL(69.0775527898)*csound->onedsr); else p->gr = EXP(- FL(6.90775527898)/(CS_ESR* p->lastrel)); p->envelope = FL(0.0); return OK; } static int32_t envext(CSOUND *csound, ENV *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT envelope = p->envelope; MYFLT ga, gr; MYFLT *in = p->in, *out = p->out; if (p->lastatt!=*p->attack) { p->lastatt = *p->attack; if (p->lastatt<=FL(0.0)) ga = p->ga = EXP(- FL(69.0775527898)*csound->onedsr); // EXP(-FL(10000.0)*csound->onedsr); else ga = p->ga = EXP(- FL(6.90775527898)/(CS_ESR* p->lastatt)); //EXP(-FL(1.0)/(CS_ESR* p->lastatt)); } else ga = p->ga; if (p->lastrel!=*p->release) { p->lastrel = *p->release; if (p->lastrel<=FL(0.0)) gr = p->gr = EXP(- FL(69.0775527898)*csound->onedsr); //EXP(-FL(100.0)*csound->onedsr); else gr = p->gr = EXP(- FL(6.90775527898)/(CS_ESR* p->lastrel)); //EXP(-FL(1.0)/(CS_ESR* p->lastrel)); } else gr = p->gr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nenvelope = envelope; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "follow", S(FOL), 0, 3, "a", "ai", (SUBR)flwset, (SUBR)follow }, { "follow2", S(ENV), 0, 3, "a", "akk", (SUBR)envset, (SUBR)envext } }; int32_t follow_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int32_t ) (sizeof(localops) / sizeof(OENTRY))); }