/*
delayst.c:
Copyright (C) 2011 Casey Mongoven
This plugin is used in order to simulate using delay (and phase) the interaural difference between a signal originating
within a 60 degree span using stereo speakers placed at 60 degrees. -30 is hard left, 0 in the middle and 30 represents
hard right. It could also be used to similar purposes with headphones. The opcode is designed to simulate the type of delay
which occurs if events occur successively temporally in an arc but which are naturally "bent" by the distance between our
ears so that if one examines the first arrival of a sound to the ears the events are not exactly successive but revolve
around an axis. The minimum distance to a listeners ear from a speaker is subtracted from the delay in this opcode in
order to cut off less of the signal. In normal circumstances, the maximum delay which will occur is less than 1/4
milliseconds.
*/
#include "delayst.h"
int delaystset(CSOUND *csound, DELAYST *p)
{
int32 npts, npts1, npts2;
char *auxp;
MYFLT iazim, irad, ihwid, isos, delmin, del1, del2;
/* based on 60 degree speaker placement, define azimuth from -30 to 30 degrees in radians, radius, head width, speed of sound */
iazim = ((90.0-*p->iazim)/180.0)*PI;
irad = *p->irad;
if ((ihwid = *p->ihwid) == 0.0) ihwid = 0.165;
if ((isos = *p->isos) == 0.0) isos = 344.514;
/* delmin is the minimum distance in seconds to an ear from a speaker or source based on variables */
delmin = sqrt(pow(cos((1.0/3.0)*PI)*irad-ihwid/2.0, 2.0)+pow(sin((1.0/3.0)*PI)*irad, 2.0))/isos;
del1 = sqrt(pow(cos(iazim)*irad+ihwid/2.0, 2.0)+pow(sin(iazim)*irad, 2.0))/isos-delmin;
del2 = sqrt(pow(cos(iazim)*irad-ihwid/2.0, 2.0)+pow(sin(iazim)*irad, 2.0))/isos-delmin;
/* define number of points in delays, npts is the size of largest delay plus 1 to support 0 sample delays */
npts1 = (int32) (FL(0.5) + del1 * csound->esr);
npts2 = (int32) (FL(0.5) + del2 * csound->esr);
npts = (npts1 >= npts2) ? npts1+1 : npts2+1;
if ((auxp = p->auxch.auxp) == NULL || npts != p->npts) {
csound->AuxAlloc(csound, (int32)npts*sizeof(MYFLT), &p->auxch);
auxp = p->auxch.auxp;
p->npts = npts;
}
else {
memset(auxp, 0, npts*sizeof(MYFLT));
}
/* if delay is equal to 0 for a speaker, set it to beginning of aux array, where asig begins writing, else set according to delay */
p->curp = (MYFLT *) auxp;
p->curp1 = (UNLIKELY(npts1 == 0)) ? (MYFLT *) p->auxch.auxp : (MYFLT *) p->auxch.endp - npts1;
p->curp2 = (UNLIKELY(npts2 == 0)) ? (MYFLT *) p->auxch.auxp : (MYFLT *) p->auxch.endp - npts2;
return OK;
}
int delayst(CSOUND *csound, DELAYST *p)
{
MYFLT *a1, *a2, *asig, *curp, *curp1, *curp2, *endp;
int n, nsmps = csound->ksmps;
if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;
a1 = p->a1;
a2 = p->a2;
asig = p->asig;
curp = p->curp;
curp1 = p->curp1;
curp2 = p->curp2;
endp = (MYFLT *) p->auxch.endp;
for (n=0; nauxch.auxp;
if (UNLIKELY(++curp1 == endp)) curp1 = (MYFLT *) p->auxch.auxp;
if (UNLIKELY(++curp2 == endp)) curp2 = (MYFLT *) p->auxch.auxp;
}
p->curp = curp;
p->curp1 = curp1;
p->curp2 = curp2;
return OK;
err1:
return csound->PerfError(csound, Str("delay: not initialised"));
}
#define S sizeof
static OENTRY localops[] = {
{ "delayst", S(DELAYST), 5, "aa", "aiioo", (SUBR)delaystset, NULL, (SUBR)delayst }
};
LINKAGE