Cog/Frameworks/Syntrax-c/Syntrax-c/jaytrax.c

1779 lines
61 KiB
C

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "jaytrax.h"
#include "mixcore.h"
#ifndef M_PI
#define M_PI (3.14159265359)
#endif
int32_t frequencyTable[SE_NROFFINETUNESTEPS][128];
int16_t sineTab[256];
uint8_t isStaticInit = 0;
//void SoundEngine::DeAllocate()
static void handleEffects(JT1Player* SELF, int32_t channr) {
int32_t f;
for (f=0; f<SE_EFF_INST; f++) {
JT1Voice* vc; JT1VoiceEffect* vfx; JT1Inst* ins; JT1Effect* fx;
int16_t s;
vc = &SELF->voices[channr];
ins = SELF->song->instruments[vc->instrument];
fx = &ins->fx[f];
vfx = &vc->fx[f];
// increase oscilator
s = (int16_t) fx->oscspd;
vfx->osccnt += s;
vfx->osccnt &= 255;
switch (fx->effecttype) {
case 0: //none
break;
case 1: { //negate
int32_t dest;
int16_t *dw;
int16_t i,s,c;
dest = fx->dsteffect;
s = (int16_t)fx->effectspd;
c = (int16_t)vfx->fxcnt1;
dw = &vc->waves[256*dest];
for (i=0; i<s;i++) {
c++;
c&=255;
dw[c] = 0-dw[c];
}
vfx->fxcnt1 = (int32_t)c;
}
break;
case 2: { // warp
int32_t dest;
int16_t *dw;
int16_t i,s,c;
dest = fx->dsteffect;
s = (int16_t) fx->effectspd;
dw = &vc->waves[256*dest];
c = 0;
for (i=0; i<256; i++) {
dw[i] += c;
c+=s;
}
}
break;
case 3: { // Filter
int32_t dest, src;
int16_t *dw, *sw;
int16_t i, s, t;
dest = fx->dsteffect;
src = fx->srceffect1;
dw = &vc->waves[256*dest];
sw = &vc->waves[256*src];
s = (int16_t) fx->effectspd;
if(s>12) s=12; //not more than 12 times...it slowes down too much
for (t=0; t<s; t++) {
dw[0] = (sw[255] +sw[1])>>1;
for (i=1; i<255; i++) {
dw[i] = (sw[i-1] +sw[i+1])>>1;
}
dw[255] = (sw[254] +sw[0])>>1;
}
}
break;
case 4: { // Wavemix
int32_t dest, src1, src2;
int16_t *dw, *sw1, *sw2;
int16_t i, s, c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->srceffect2;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
s = (int16_t) fx->effectspd;
vfx->fxcnt1 += s;
vfx->fxcnt1 &= 255;
c = (int16_t)vfx->fxcnt1;
for (i=0; i<256; i++) {
dw[i] = (sw1[i] +sw2[c])>>1;
c++;
c&=255;
}
}
break;
case 5: { // Resonance
int32_t dest, src1, src2;
int16_t *dw, *sw1, *sw2;
int16_t i, c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
c = (int16_t)vfx->osccnt;
// init
double centerFreq, bandwidth;
if(fx->osceffect==0) {
centerFreq = (double)(fx->effectvar1*20);
bandwidth = (double)(fx->effectvar2*16);
} else {
if(fx->oscflg) {
centerFreq = (double)(fx->effectvar1*20);
bandwidth = (double)(sw2[c]+32768)/16;
} else {
centerFreq = (double)(sw2[c]+32768)/13;
bandwidth = (double)(fx->effectvar2*16);
}
}
vfx->b2 = exp(-(2 * M_PI) * (bandwidth / 22000));
vfx->b1 = (-4.0 * vfx->b2) / (1.0 + vfx->b2) * cos(2 * M_PI * (centerFreq / 22000));
vfx->a0 = (1.0 - vfx->b2) * sqrt(1.0 - (vfx->b1 * vfx->b1) / (4.0 * vfx->b2));
for (i=0; i<256; i++) {
double o;
o = vfx->a0 * ((double)(sw1[i])/32768) - vfx->b1 * vfx->y1 - vfx->b2 * vfx->y2;
vfx->y2 = vfx->y1;
vfx->y1 = o;
if(o>.9999)o=.9999;
if(o<-.9999)o=-.9999;
dw[i] = (int16_t)(o*32768);
}
}
break;
case 6: { // Reso Whistle
int32_t dest,src1,src2;
int16_t *dw,*sw1,*sw2;
int16_t i,c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
c = (int16_t)vfx->osccnt;
// init
double centerFreq, bandwidth;
if(fx->osceffect==0) {
centerFreq = (double)(fx->effectvar1*20);
bandwidth = (double)(fx->effectvar2*16);
} else {
if(fx->oscflg) {
centerFreq = (double)(fx->effectvar1*20);
bandwidth = (double)(sw2[c]+32768)/16;
} else {
centerFreq = (double)(sw2[c]+32768)/13;
bandwidth = (double)(fx->effectvar2*16);
}
}
vfx->b2 = exp(-(2 * M_PI) * (bandwidth / 22000));
vfx->b1 = (-4.0 * vfx->b2) / (1.0 + vfx->b2) * cos(2 * M_PI * (centerFreq / 22000));
vfx->a0 = (1.0 - vfx->b2) * sqrt(1.0 - (vfx->b1 * vfx->b1) / (4.0 * vfx->b2));
vfx->b2*=1.2; // do the reso whistle
for (i=0; i<256; i++) {
double o;
o = vfx->a0 * ((double)(sw1[i])/32768) - vfx->b1 * vfx->y1 - vfx->b2 * vfx->y2;
vfx->y2 = vfx->y1;
vfx->y1 = o;
if(o>.9999)o=.9999;
if(o<-.9999)o=-.9999;
dw[i] = (int16_t)(o*32768);
}
}
break;
case 7: { // Morphing
int32_t dest,src1,src2,osc;
int16_t *dw,*sw1,*sw2,*ow;
int16_t i,c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->srceffect2;
osc = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
ow = &vc->waves[256*osc];
c = (int16_t)vfx->osccnt;
// init
int16_t m1,m2;
if(fx->osceffect==0) {
m1 = fx->effectvar1;
} else {
if(fx->oscflg) {
m1 = fx->effectvar1;
} else {
m1 = (ow[c]+32768)/256;
}
}
m2 = 255-m1;
for (i=0; i<256; i++) {
int32_t a;
a=(((int32_t)sw1[i]*m1)/256)+(((int32_t)sw2[i]*m2)/256);
dw[i] = (int16_t)(a);
}
}
break;
case 8: { // Dyna-Morphing
int32_t dest,src1,src2,osc;
int16_t *dw,*sw1,*sw2,*ow,*si;
int16_t i,c;
si = &sineTab[0];
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->srceffect2;
osc = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
ow = &vc->waves[256*osc];
c = (int16_t)vfx->osccnt;
// init
int16_t m1,m2,sc; //sc is sincnt
if(fx->osceffect==0) {
sc = fx->effectvar1;
} else {
if(fx->oscflg)
{
sc = fx->effectvar1;
}
else
{
sc = (ow[c]+32768)/256;
}
}
for (i=0; i<256; i++) {
int32_t a;
m1=(si[sc]>>8)+128;
m2 = 255-m1;
a=(((int32_t)sw1[i]*m1)/256)+(((int32_t)sw2[i]*m2)/256);
dw[i] = (int16_t)(a);
sc++;
sc&=255;
}
}
break;
case 9: { // Distortion
int32_t dest,src1,osc;
int16_t *dw,*sw1,*ow;
int16_t i,c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
osc = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
ow = &vc->waves[256*osc];
c = (int16_t)vfx->osccnt;
// init
int16_t m1;
if(fx->osceffect==0) {
m1 = fx->effectvar1;
} else {
if(fx->oscflg) {
m1 = fx->effectvar1;
} else {
m1 = (ow[c]+32768)/256;
}
}
for (i=0; i<256; i++) {
int32_t a;
a=((int32_t)sw1[i]*m1)/16;
a+=32768;
if(a<0)a=-a;
a%=131072;
if(a>65535) a = 131071-a;
a-=32768;
dw[i] = (int16_t)(a);
}
}
break;
case 10: { // Scroll left
int32_t dest;
int16_t *dw;
int16_t i,t;
dest = fx->dsteffect;
dw = &vc->waves[256*dest];
t=dw[0];
for (i=0; i<255; i++) {
dw[i] = dw[i+1];
}
dw[255]=t;
}
break;
case 11: { // Upsample
int32_t dest;
int16_t *dw;
int16_t i,c;
c = (int16_t)vfx->fxcnt1;
if(c != 0) { // timeout ended?
vfx->fxcnt1--;
break;
}
vfx->fxcnt1 = fx->effectvar1;
dest = fx->dsteffect;
dw = &vc->waves[256*dest];
for (i=0; i<128; i++) {
dw[i]=dw[i*2];
}
memcpy(&dw[128], &dw[0], 256);
}
break;
case 12: { // Clipper
int32_t dest,src1,osc;
int16_t *dw,*sw1,*ow;
int16_t i,c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
osc = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
ow = &vc->waves[256*osc];
c = (int16_t)vfx->osccnt;
// init
int16_t m1;
if(fx->osceffect==0) {
m1 = fx->effectvar1;
} else {
if(fx->oscflg) {
m1 = fx->effectvar1;
} else {
m1 = (ow[c]+32768)/256;
}
}
for (i=0; i<256; i++) {
int32_t a;
a=((int32_t)sw1[i]*m1)/16;
if(a<-32767)a=-32767;
if(a>32767)a=32767;
dw[i] = (int16_t)(a);
}
}
break;
case 13: { // bandpass
int32_t dest,src1,src2;
int16_t *dw,*sw1,*sw2;
int16_t i,c;
int32_t _2_pi_w0;
int32_t _1000_Q;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
c = (int16_t)vfx->osccnt;
// init
int32_t freq,reso;
if(fx->osceffect==0) {
freq = fx->effectvar1;
reso = fx->effectvar2;
freq*=16; //(freq 0 - 16000hz)
} else {
if(fx->oscflg) {
freq = fx->effectvar1;
reso = (sw2[c]+32768)>>8;
freq*=16; //(freq 0 - 16000hz)
} else {
freq = (sw2[c]+32768)/16;
reso = fx->effectvar2;
}
}
//calc freq;
//double x = freq - 920.0;
//double w0 = 228 + 3900/2*(1 + tanh(_copysign(pow(fabs(x), 0.85)/95, x)));
double w0 = 228+freq;
_2_pi_w0 = (int32_t)(2*M_PI*w0);
//calc Q
_1000_Q = 707 + 1000*reso/128;
int32_t _2_pi_w0_delta_t;
int32_t Vhp_next;
int32_t Vbp_next;
int32_t Vlp_next;
int32_t Vbp;
int32_t Vlp;
int32_t Vhp;
int32_t Vi;
int32_t s;
int32_t delta_t;
Vbp = vfx->Vbp;
Vlp = vfx->Vlp;
Vhp = vfx->Vhp;
delta_t=8;
// now let's throw our waveform through the resonator!
for (i=0; i<256; i++) {
// delta_t is converted to seconds given a 1MHz clock by dividing
// with 1 000 000. This is done in three operations to avoid integer
// multiplication overflow.
_2_pi_w0_delta_t = _2_pi_w0*delta_t/100;
// Calculate filter outputs.
Vi=sw1[i];
Vhp_next = Vbp*1000/_1000_Q - Vlp + Vi;
Vbp_next = Vbp - _2_pi_w0_delta_t*(Vhp/100)/100;
Vlp_next = Vlp - _2_pi_w0_delta_t*(Vbp/100)/100;
Vhp = Vhp_next;
Vbp = Vbp_next;
Vlp = Vlp_next;
s = Vlp;
if(s>32767)s=32767;
if(s<-32767)s=-32767;
dw[i] = (int16_t)(s);
}
vfx->Vbp = Vbp;
vfx->Vlp = Vlp;
vfx->Vhp = Vhp;
}
break;
case 14: { // highpass
int32_t dest,src1,src2;
int16_t *dw,*sw1,*sw2;
int16_t i,c;
int32_t _2_pi_w0;
int32_t _1000_Q;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
c = (int16_t)vfx->osccnt;
// init
int32_t freq, reso;
if(fx->osceffect==0) {
freq = fx->effectvar1;
reso = fx->effectvar2;
freq*=32; //(freq 0 - 16000hz)
} else {
if(fx->oscflg) {
freq = fx->effectvar1;
reso = (sw2[c]+32768)>>8;
freq*=32; //(freq 0 - 16000hz)
} else {
freq = (sw2[c]+32768)/8;
reso = fx->effectvar2;
}
}
//calc freq;
//double x = freq - 920.0;
//double w0 = 228 + 3900/2*(1 + tanh(_copysign(pow(fabs(x), 0.85)/95, x)));
double w0 = 228+freq;
_2_pi_w0 = (int32_t)(2*M_PI*w0);
//calc Q
_1000_Q = 707 + 1000*reso/128;
int32_t _2_pi_w0_delta_t;
int32_t Vhp_next;
int32_t Vbp_next;
int32_t Vlp_next;
int32_t Vbp;
int32_t Vlp;
int32_t Vhp;
int32_t Vi;
int32_t s;
int32_t delta_t;
Vbp = vfx->Vbp;
Vlp = vfx->Vlp;
Vhp = vfx->Vhp;
delta_t=8;
// now let's throw our waveform through the resonator!
for (i=0; i<256; i++) {
// delta_t is converted to seconds given a 1MHz clock by dividing
// with 1 000 000. This is done in three operations to avoid integer
// multiplication overflow.
_2_pi_w0_delta_t = _2_pi_w0*delta_t/100;
// Calculate filter outputs.
Vi=sw1[i];
Vhp_next = Vbp*1000/_1000_Q - Vlp + Vi;
Vbp_next = Vbp - _2_pi_w0_delta_t*(Vhp/100)/100;
Vlp_next = Vlp - _2_pi_w0_delta_t*(Vbp/100)/100;
Vhp = Vhp_next;
Vbp = Vbp_next;
Vlp = Vlp_next;
s = Vhp;
if(s>32767)s=32767;
if(s<-32767)s=-32767;
dw[i] = (int16_t)(s);
}
vfx->Vbp = Vbp;
vfx->Vlp = Vlp;
vfx->Vhp = Vhp;
}
break;
case 15: { // bandpass
int32_t dest,src1,src2;
int16_t *dw,*sw1,*sw2;
int16_t i,c;
int32_t _2_pi_w0;
int32_t _1000_Q;
dest = fx->dsteffect;
src1 = fx->srceffect1;
src2 = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
sw2 = &vc->waves[256*src2];
c = (int16_t)vfx->osccnt;
// init
int32_t freq,reso;
if(fx->osceffect==0) {
freq = fx->effectvar1;
reso = fx->effectvar2;
freq*=16; //(freq 0 - 16000hz)
} else {
if(fx->oscflg) {
freq = fx->effectvar1;
reso = (sw2[c]+32768)>>8;
freq*=16; //(freq 0 - 16000hz)
} else {
freq = (sw2[c]+32768)/16;
reso = fx->effectvar2;
}
}
//calc freq;
//double x = freq - 920.0;
//double w0 = 228 + 3900/2*(1 + tanh(_copysign(pow(fabs(x), 0.85)/95, x)));
double w0 = 228+freq;
_2_pi_w0 = (int32_t)(2*M_PI*w0);
//calc Q
_1000_Q = 707 + 1000*reso/128;
int32_t _2_pi_w0_delta_t;
int32_t Vhp_next;
int32_t Vbp_next;
int32_t Vlp_next;
int32_t Vbp;
int32_t Vlp;
int32_t Vhp;
int32_t Vi;
int32_t s;
int32_t delta_t;
Vbp = vfx->Vbp;
Vlp = vfx->Vlp;
Vhp = vfx->Vhp;
delta_t=8;
// now let's throw our waveform through the resonator!
for (i=0; i<256; i++) {
// delta_t is converted to seconds given a 1MHz clock by dividing
// with 1 000 000. This is done in three operations to avoid integer
// multiplication overflow.
_2_pi_w0_delta_t = _2_pi_w0*delta_t/100;
// Calculate filter outputs.
Vi=sw1[i];
Vhp_next = Vbp*1000/_1000_Q - Vlp + Vi;
Vbp_next = Vbp - _2_pi_w0_delta_t*(Vhp/100)/100;
Vlp_next = Vlp - _2_pi_w0_delta_t*(Vbp/100)/100;
Vhp = Vhp_next;
Vbp = Vbp_next;
Vlp = Vlp_next;
s = Vbp;
if(s>32767)s=32767;
if(s<-32767)s=-32767;
dw[i] = (int16_t)(s);
}
vfx->Vbp = Vbp;
vfx->Vlp = Vlp;
vfx->Vhp = Vhp;
}
break;
case 16: { // Noise
int32_t dest;
int16_t *dw;
int16_t i;
dest = fx->dsteffect;
dw = &vc->waves[256*dest];
for (i=0; i<256; i++) {
//TODO: LCG or twin LSFR noise
dw[i]=(rand()*2)-32768;
}
}
break;
case 17: { // Squash
int32_t dest,src1,osc;
int16_t *dw,*sw1,*ow;
int16_t i,c;
dest = fx->dsteffect;
src1 = fx->srceffect1;
osc = fx->osceffect-1;
dw = &vc->waves[256*dest];
sw1 = &vc->waves[256*src1];
ow = &vc->waves[256*osc];
c = (int16_t)vfx->osccnt;
// init
uint16_t m1a, m1b, m2;
if(fx->osceffect==0) {
m1a = fx->effectvar1;
m1b = fx->effectvar2;
} else {
if(fx->oscflg) {
m1a = fx->effectvar1;
m1b = (ow[c]+32768)/256;
} else {
m1a = (ow[c]+32768)/256;
m1b = fx->effectvar2;
}
}
m1b<<=8;
m1a+=m1b; //m1 is now the counter for the squash
m2=0; //m2 is the actual counter which is 256 times too large (fixed point)
for (i=0; i<256; i++) {
int32_t a,b;
b=sw1[m2>>8];
a=sw1[(m2>>8)+1];
a*=(m2&255);
b*=(255-(m2&255));
a=(a>>8)+(b>>8);
dw[i] = a;
m2+=m1a;
}
}
break;
}
}
}
static void handleInstrument(JT1Player* SELF, int32_t channr) {
JT1Voice* vc; JT1Inst* ins;
int32_t vol, freq, pan;
vc = &SELF->voices[channr];
ins = SELF->song->instruments[vc->instrument];
//vol
if (ins->amwave == 0) { //volume wave?
vol = 0;
} else {
vc->volcnt += ins->amspd;
if (vc->volcnt >= 256) {
vc->volcnt -= 256;
vc->volcnt += ins->amlooppoint;
if(vc->volcnt >= 256) {
vc->volcnt = ins->amlooppoint;
}
}
vol = vc->waves[(256*(ins->amwave-1))+vc->volcnt];
vol = vol+32768;
vol /= 6;
vol = -vol; //10930;
if (vol <-10000) vol = -10000;
}
//last but not least, the master volume
vol += 10000;
vol *= ins->mastervol;
vol >>=8;
vol *= SELF->masterVolume; //and the replayers master master volume
vol >>=8;
vol -= 10000;
vc->curvol = vol;
//if(vc->buf) vc->buf->SetVolume(vol);
//update panning
if(ins->panwave == 0) { //panning wave?
pan = 0;
} else {
vc->pancnt += ins->panspd;
if (vc->pancnt >= 256) {
vc->pancnt -= 256;
vc->pancnt += ins->panlooppoint;
if(vc->pancnt >= 256) {
vc->pancnt = ins->panlooppoint;
}
}
pan = vc->waves[(256*(ins->panwave-1))+vc->pancnt];
pan >>=7;
}
//if(vc->buf) vc->buf->SetPan(pan);
vc->curpan = pan;
//update freq
int32_t k;
k = 0;
k = SELF->song->arpTable[(ins->arpeggio*16)+vc->arpcnt];
vc->arpcnt++;
vc->arpcnt&=15;
freq = frequencyTable[ins->finetune][k+vc->curnote];
if(vc->freqdel) {
vc->freqdel--;
} else {
if(ins->fmwave != 0) { //frequency wave?
vc->freqcnt += ins->fmspd;
if (vc->freqcnt >= 256) {
vc->freqcnt -= 256;
vc->freqcnt += ins->fmlooppoint;
if(vc->freqcnt >= 256) {
vc->freqcnt = ins->fmlooppoint;
}
}
freq -= vc->waves[(256*(ins->fmwave-1))+vc->freqcnt];
}
}
freq += vc->bendadd;
vc->curfreq = freq;
//update pitchbend
if(vc->bendspd != 0) {
if(vc->bendspd >0) {
if(vc->bendadd < vc->destfreq) {
vc->bendadd += vc->bendspd;
if(vc->bendadd > vc->destfreq) {
vc->bendadd = vc->destfreq;
}
}
} else {
if(vc->bendadd > vc->destfreq) {
vc->bendadd += vc->bendspd;
if(vc->bendadd < vc->destfreq) {
vc->bendadd = vc->destfreq;
}
}
}
}
}
static void playInstrument(JT1Player* SELF, int32_t channr, int32_t instNum, int32_t note) {
JT1Voice* vc; JT1Inst* ins;
int32_t f;
// instruments init
if(instNum > SELF->song->nrofinst) return; // not allowed!
vc = &SELF->voices[channr];
if(vc->instrument == -1 && instNum == 0) return; //geen instrument 0 op een gemute channel...er was namelijk geen previous instrument
ins = SELF->song->instruments[instNum-1];
vc->arpcnt = 0;
vc->volcnt = 0;
vc->pancnt = 0;
vc->freqcnt = 0;
vc->curnote = note;
vc->curfreq = 0;
vc->bendtonote = note;
vc->bendadd = 0;
vc->destfreq = 0;
vc->bendspd = 0;
if(instNum) { // do not copy if 0
int32_t i;
//TODO: check sample usage
if(!ins->sharing) { // no sample sharing
vc->sampledata = SELF->song->samples[instNum-1];
} else {
vc->sampledata = SELF->song->samples[ins->sharing-1];
}
vc->samplepos = ins->startpoint<<8;
vc->looppoint = ins->looppoint<<8;
vc->endpoint = ins->endpoint<<8;
vc->loopflg = ins->loopflg;
vc->bidirecflg = ins->bidirecflg;
vc->freqdel = ins->fmdelay;
for (i=0; i<SE_WAVES_INST; i++) {
if (ins->resetwave[i]) memcpy(&vc->waves[i*256], &ins->waves[i*256], 256 * sizeof(int16_t));
}
vc->instrument = instNum-1;
}
// effects init
for (f=0; f<SE_EFF_INST; f++) {
JT1Effect* fx; JT1VoiceEffect* vfx;
fx = &SELF->song->instruments[vc->instrument]->fx[f];
vfx = &vc->fx[f];
if (fx->effecttype && fx->reseteffect) {
vfx->osccnt = 0;
vfx->fxcnt1 = 0;
vfx->fxcnt2 = 0;
vfx->y2 = 0;
vfx->y1 = 0;
vfx->Vhp = 0;
vfx->Vbp = 0;
vfx->Vlp = 0;
}
}
}
static void handleSong(JT1Player* SELF) {
int16_t i;
int32_t step;
if (!SELF->playFlg) return;
if (SELF->pauseFlg) return;
SELF->patternDelay--;
if (SELF->patternDelay==0) {
step = SELF->playMode == SE_PM_SONG ? SELF->playStep : SELF->patternOffset;
if ((step&1) == 0) { // change the groove
SELF->playSpeed = 8 - SELF->subsong->groove;
} else {
SELF->playSpeed = 8 + SELF->subsong->groove;
}
SELF->patternDelay = SELF->playSpeed;
if (SELF->playMode == SE_PM_PATTERN) {
SELF->patternOffset++;
SELF->patternOffset %= SELF->patternLength;
} else {
for (i=0; i < SELF->subsong->nrofchans; i++) {
JT1Voice* vc = &SELF->voices[i];
vc->patpos++;
//the ==-1 part is that the song counter always is 1 before the start...so if the song starts at the beginning, the pos is -1
if (vc->patpos == SELF->subsong->orders[i][vc->songpos].patlen || vc->songpos == -1) {
vc->patpos = 0;
vc->songpos++;
}
}
SELF->playStep++;
if (SELF->playStep==64) {
SELF->playStep=0;
SELF->playPosition++;
}
//has endpos been reached?
if (SELF->playPosition == SELF->subsong->endpos && SELF->playStep == SELF->subsong->endstep) {
if (SELF->subsong->songloop) { //does song loop?
int32_t maat, pos, t;
uint8_t isSkipLoop = 0;
// now me must reset all the playpointers to the loop positions
for (t=0; t<SE_NROFCHANS; t++) {
JT1Order* orders = SELF->subsong->orders[t];
JT1Voice* vc = &SELF->voices[t];
int32_t endpos;
int32_t lastmaat;
maat = 0;
pos = 0;
lastmaat=0;
endpos = (SELF->subsong->looppos * 64) + SELF->subsong->loopstep;
while (pos<256) {
if (maat > endpos) {
if (pos != endpos) pos--;
break;
}
lastmaat=maat;
maat+=orders[pos].patlen;
pos++;
}
//oops! starting position too far!
if (pos == 256) { //!WARN: >= 256?
SELF->playFlg = 0;
isSkipLoop = 1;
break;
}
endpos -= lastmaat;
endpos &= 63;
vc->songpos = pos;
vc->patpos = endpos;
}
if (!isSkipLoop) {
SELF->playPosition = SELF->subsong->looppos;
SELF->playStep = SELF->subsong->loopstep;
}
SELF->loopCnt ++;
} else { // stop song
SELF->playFlg = 0;
SELF->pauseFlg = 0;
SELF->playMode = SE_PM_SONG;
SELF->playPosition = SELF->subsong->songpos;
SELF->playStep = SELF->subsong->songstep;
}
}
}
}
}
static void handleScript(JT1Player* SELF, int32_t f,int32_t s, int32_t d, int32_t p, int32_t channr) { //note, script,dstnote,param,channr
JT1Voice* vc; JT1Inst* ins;
int32_t a;
vc = &SELF->voices[channr];
if(vc->instrument==-1) return; //no change
ins = SELF->song->instruments[vc->instrument];
switch(s) {
default:
case 0:
return;
case 1: //pitch bend
if (vc->bendtonote) { //hebben we al eens gebend?
a = frequencyTable[ins->finetune][vc->bendtonote]; // begin frequentie
vc->curnote = vc->bendtonote;
} else {
a = frequencyTable[ins->finetune][f]; // begin freqeuntie
}
vc->bendadd = 0;
vc->destfreq = frequencyTable[ins->finetune][d] - a;
vc->bendspd = p*20;
vc->bendtonote = d;
break;
case 2: //waveform
if (d>15) d = 15;
ins->waveform = d;
break;
case 3: //wavelength
d = (d>192 ? 256 : (d>96 ? 128 : (d>48 ? 64 : 32)));
ins->wavelength = d;
break;
case 4: //mastervol
ins->mastervol = d;
break;
case 5: //amwaveform
if (d>15) d = 15;
ins->amwave = d;
break;
case 6: //amspd
ins->amspd = d;
break;
case 7: //amlooppoint
ins->amlooppoint = d;
break;
case 8: //finetune
if (d>15) d = 15;
ins->finetune = d;
break;
case 9: //fmwaveform
if (d>15) d = 15;
ins->fmwave = d;
break;
case 10: //fmspd
ins->fmspd = d;
break;
case 11: //fmlooppoint
ins->fmlooppoint = d;
break;
case 12: //fmdelay
ins->fmdelay = d;
break;
case 13: //arpeggio
if (d>15) d = 15;
ins->arpeggio = d;
break;
case 14: //fx 0 fxdstwave
if (d>15) d = 15;
ins->fx[0].dsteffect = d;
break;
case 15: //fx 0 fxsrcwave1
if (d>15) d = 15;
ins->fx[0].srceffect1 = d;
break;
case 16: //fx 0 fxsrcwave2
if (d>15) d = 15;
ins->fx[0].srceffect2 = d;
break;
case 17: //fx 0 fxoscwave
if (d>15) d = 15;
ins->fx[0].osceffect = d;
break;
case 18: //fx 0 effectvar1
ins->fx[0].effectvar1 = d;
break;
case 19: //fx 0 effectvar2
ins->fx[0].effectvar2 = d;
break;
case 20: //fx 0 effectspd
ins->fx[0].effectspd = d;
break;
case 21: //fx 0 oscspd
ins->fx[0].oscspd = d;
break;
case 22: //fx 0 oscflg
if (d>1) d=1;
ins->fx[0].oscflg = d;
break;
case 23: //fx 0 effecttype
if (d>=SE_NROFEFFECTS) d=SE_NROFEFFECTS-1;
ins->fx[0].effecttype = d;
break;
case 24: //fx 0 reseteffect
if (d>1) d=1;
ins->fx[0].reseteffect = d;
break;
case 25: //fx 1 fxdstwave
if (d>15) d = 15;
ins->fx[1].dsteffect = d;
break;
case 26: //fx 1 fxsrcwave1
if (d>15) d = 15;
ins->fx[1].srceffect1 = d;
break;
case 27: //fx 1 fxsrcwave2
if (d>15) d = 15;
ins->fx[1].srceffect2 = d;
break;
case 28: //fx 1 fxoscwave
if (d>15) d = 15;
ins->fx[1].osceffect = d;
break;
case 29: //fx 1 effectvar1
ins->fx[1].effectvar1 = d;
break;
case 30: //fx 1 effectvar2
ins->fx[1].effectvar2 = d;
break;
case 31: //fx 1 effectspd
ins->fx[1].effectspd = d;
break;
case 32: //fx 1 oscspd
ins->fx[1].oscspd = d;
break;
case 33: //fx 1 oscflg
if (d>1) d=1;
ins->fx[1].oscflg = d;
break;
case 34: //fx 1 effecttype
if (d>=SE_NROFEFFECTS) d=SE_NROFEFFECTS-1;
ins->fx[1].effecttype = d;
break;
case 35: //fx 1 reseteffect
if (d>1) d=1;
ins->fx[1].reseteffect = d;
break;
case 36: //fx 2 fxdstwave
if (d>15) d = 15;
ins->fx[2].dsteffect = d;
break;
case 37: //fx 2 fxsrcwave1
if (d>15) d = 15;
ins->fx[2].srceffect1 = d;
break;
case 38: //fx 2 fxsrcwave2
if (d>15) d = 15;
ins->fx[2].srceffect2 = d;
break;
case 39: //fx 2 fxoscwave
if (d>15) d = 15;
ins->fx[2].osceffect = d;
break;
case 40: //fx 2 effectvar1
ins->fx[2].effectvar1 = d;
break;
case 41: //fx 2 effectvar2
ins->fx[2].effectvar2 = d;
break;
case 42: //fx 2 effectspd
ins->fx[2].effectspd = d;
break;
case 43: //fx 2 oscspd
ins->fx[2].oscspd = d;
break;
case 44: //fx 2 oscflg
if (d>1) d=1;
ins->fx[2].oscflg = d;
break;
case 45: //fx 2 effecttype
if (d>=SE_NROFEFFECTS) d=SE_NROFEFFECTS-1;
ins->fx[2].effecttype = d;
break;
case 46: //fx 2 reseteffect
if (d>1) d=1;
ins->fx[2].reseteffect = d;
break;
case 47: //fx 3 fxdstwave
if (d>15) d = 15;
ins->fx[3].dsteffect = d;
break;
case 48: //fx 3 fxsrcwave1
if (d>15) d = 15;
ins->fx[3].srceffect1 = d;
break;
case 49: //fx 3 fxsrcwave2
if (d>15) d = 15;
ins->fx[3].srceffect2 = d;
break;
case 50: //fx 3 fxoscwave
if (d>15) d = 15;
ins->fx[3].osceffect = d;
break;
case 51: //fx 3 effectvar1
ins->fx[3].effectvar1 = d;
break;
case 52: //fx 3 effectvar2
ins->fx[3].effectvar2 = d;
break;
case 53: //fx 3 effectspd
ins->fx[3].effectspd = d;
break;
case 54: //fx 3 oscspd
ins->fx[3].oscspd = d;
break;
case 55: //fx 3 oscflg
if (d>1) d=1;
ins->fx[3].oscflg = d;
break;
case 56: //fx 3 effecttype
if (d>=SE_NROFEFFECTS) d=SE_NROFEFFECTS-1;
ins->fx[3].effecttype = d;
break;
case 57: //fx 3 reseteffect
if (d>1) d=1;
ins->fx[3].reseteffect = d;
break;
case 58: //resetwave 00
if (d>1) d=1;
ins->resetwave[0] = d;
break;
case 59: //resetwave 01
if (d>1) d=1;
ins->resetwave[1] = d;
break;
case 60: //resetwave 02
if (d>1) d=1;
ins->resetwave[2] = d;
break;
case 61: //resetwave 03
if (d>1) d=1;
ins->resetwave[3] = d;
break;
case 62: //resetwave 04
if (d>1) d=1;
ins->resetwave[4] = d;
break;
case 63: //resetwave 05
if (d>1) d=1;
ins->resetwave[5] = d;
break;
case 64: //resetwave 06
if (d>1) d=1;
ins->resetwave[6] = d;
break;
case 65: //resetwave 07
if (d>1) d=1;
ins->resetwave[7] = d;
break;
case 66: //resetwave 08
if (d>1) d=1;
ins->resetwave[8] = d;
break;
case 67: //resetwave 09
if (d>1) d=1;
ins->resetwave[9] = d;
break;
case 68: //resetwave 10
if (d>1) d=1;
ins->resetwave[10] = d;
break;
case 69: //resetwave 11
if (d>1) d=1;
ins->resetwave[11] = d;
break;
case 70: //resetwave 12
if (d>1) d=1;
ins->resetwave[12] = d;
break;
case 71: //resetwave 13
if (d>1) d=1;
ins->resetwave[13] = d;
break;
case 72: //resetwave 14
if (d>1) d=1;
ins->resetwave[14] = d;
break;
case 73: //resetwave 15
if (d>1) d=1;
ins->resetwave[15] = d;
break;
case 74: //Change bpm
if (d<=10) d=10;
if (d>220) d=220;
SELF->subsong->songspd = d;
float t;
t = (float)SELF->subsong->songspd; //bpm
t /=60.0; //bps
t *=32.0;
SELF->timeSpd = (int32_t)(44100.0/t);
break;
case 75: //Change Groove
if (d>3) d=3;
SELF->subsong->groove = d;
break;
case 76: //Fire External Event
//TODO: add this effect
break;
}
}
static void handlePattern(JT1Player* SELF, int32_t channr) {
JT1Voice* vc; JT1Row* row;
int32_t pat,off;
int32_t f,d,s,p;
if (SELF->pauseFlg) return;
if (!SELF->playFlg) return;
if (SELF->patternDelay != SELF->playSpeed) return;
vc = &SELF->voices[channr];
if (SELF->playMode == SE_PM_PATTERN) {
if (channr > 0) return; // just play channel 0
pat = SELF->currentPattern;
off = SELF->patternOffset;
} else {
if (SELF->subsong->mute[channr]) return;
off = vc->patpos;
pat = SELF->subsong->orders[channr][vc->songpos].patnr;
}
row = &SELF->song->patterns[(pat*64)+off];
//init instrument
f = row->srcnote;
if (f) playInstrument(SELF, channr, row->inst, f);
//handle special effects
s = row->script;
d = row->dstnote;
p = row->param;
handleScript(SELF, f, s, d, p, channr);
}
static void advanceSong(JT1Player* SELF) {
handleSong(SELF);
for (int i=0; i < SELF->subsong->nrofchans; i++) {
handlePattern(SELF, i);
if(SELF->voices[i].instrument != -1) {// mute?
handleInstrument(SELF, i); //do volume and pitch things
handleEffects(SELF, i); //do instrument effects
}
}
}
static void PlayPattern(JT1Player* SELF, int PatternNr) {
SELF->playFlg = 1;
SELF->currentPattern = PatternNr;
SELF->patternOffset = 63;
SELF->patternDelay = 1;
SELF->playMode = SE_PM_PATTERN;
SELF->playSpeed = SELF->song->subsongs[0]->songspd - SELF->song->subsongs[0]->groove;
}
static void clearSoundBuffers(JT1Player* SELF) {
int32_t i,j;
// clear delaybuffers
memset(SELF->overlapBuffer, 0, WANTEDOVERLAP*2*sizeof(int16_t));
memset(SELF->leftDelayBuffer, 0, 65536*sizeof(int16_t));
memset(SELF->rightDelayBuffer, 0, 65536*sizeof(int16_t));
//initialize channel data
for (i=0;i<SE_NROFCHANS;i++) {
JT1Voice* vc = &SELF->voices[i];
vc->songpos = 0;
vc->patpos = 0;
vc->instrument = -1;
vc->volcnt = 0;
vc->arpcnt = 0;
vc->pancnt = 0;
vc->curnote = 0;
vc->curfreq = 0;
vc->bendadd = 0;
vc->destfreq = 0;
vc->bendspd = 0;
vc->freqcnt = 0;
vc->freqdel = 0;
vc->sampledata = NULL;
vc->endpoint = 0;
vc->synthPos = 0;
vc->samplepos = 0;
vc->curvol = 0;
vc->curpan = 0;
vc->bendtonote = 0;
vc->looppoint = 0;
vc->loopflg = 0;
vc->bidirecflg = 0;
vc->wavePtr = NULL;
vc->waveLength = 0;
vc->freqOffset = 0;
vc->gainMainL = 0;
vc->gainMainR = 0;
vc->gainEchoL = 0;
vc->gainEchoR = 0;
for(j=0;j<4;j++) {
JT1VoiceEffect* vfx = &vc->fx[j];
vfx->fxcnt1 = 0;
vfx->fxcnt2 = 0;
vfx->osccnt = 0;
vfx->a0 = 0;
vfx->b1 = 0;
vfx->b2 = 0;
vfx->y1 = 0;
vfx->y2 = 0;
vfx->Vhp = 0;
vfx->Vbp = 0;
vfx->Vlp = 0;
}
memset(vc->waves, 0, 4096*sizeof(int16_t));
}
}
//---------------------API
int jaytrax_loadSong(JT1Player* SELF, JT1Song* sng) {
SELF->song = sng;
jaytrax_changeSubsong(SELF, 0);
return 1;
}
// This function ensures that the play routine is called properly and everything is initialized in a good way
void jaytrax_changeSubsong(JT1Player* SELF, int subsongnr) {
int maat, pos, t;
JT1Order* order;
if (subsongnr > SELF->song->nrofsongs) return;
SELF->subsongNr = subsongnr;
SELF->subsong = SELF->song->subsongs[subsongnr];
clearSoundBuffers(SELF);
for(t=0; t < SE_NROFCHANS; t++) {
JT1Voice* vc;
int endpos, lastmaat;
vc = &SELF->voices[t];
maat = pos = lastmaat = 0;
order = SELF->subsong->orders[t];
endpos = (SELF->subsong->songpos * 64) + SELF->subsong->songstep - 1; //minus 1 because we immediately start with the new note
while (pos<256) {
if (maat >= endpos) {
if(pos != endpos) pos--;
break;
}
lastmaat=maat;
maat+=order[pos].patlen;
pos++;
}
//oops! starting position too far!
if (pos == 256) return; //!WARN: >= 256?
endpos-=lastmaat;
//endpos-=maat;
endpos &=63;
vc->songpos = pos;
vc->patpos = endpos;
}
SELF->patternDelay = 1;
SELF->playFlg = 1;
SELF->pauseFlg = 0;
SELF->loopCnt = 0;
SELF->playSpeed = 8 + SELF->subsong->groove;
//SELF->playSpeed = 8;
if (SELF->subsong->songspd != 0) {
float t;
t = (float)SELF->subsong->songspd; //bpm
t /= 60.0; //bps
t *= 32.0;
SELF->timeCnt = SELF->timeSpd = (int)(44100.0/t);
}
if(SELF->subsong->songstep == 0) {
SELF->playPosition = SELF->subsong->songpos - 1;
} else {
SELF->playPosition = SELF->subsong->songpos;
}
SELF->playStep = SELF->subsong->songstep - 1;
SELF->playStep &= 63;
}
void jaytrax_stopSong(JT1Player* SELF) {
SELF->playFlg = 0;
SELF->pauseFlg = 0;
SELF->playMode = SE_PM_SONG;
if(SELF->song) {
SELF->playPosition = SELF->subsong->songpos;
SELF->playStep = SELF->subsong->songstep;
}
}
void jaytrax_pauseSong(JT1Player* SELF) {
SELF->pauseFlg = 1;
}
void jaytrax_continueSong(JT1Player* SELF) {
SELF->pauseFlg = 0;
}
JT1Player* jaytrax_init(void) {
JT1Player* SELF = calloc(1, sizeof(JT1Player));
//lazy static init
if (!isStaticInit) {
int32_t i, j;
double f,y;
//freq and finetune table
y=2;
for (j=0;j<SE_NROFFINETUNESTEPS;j++) {
for (i=0;i<128;i++) {
// formule = wortel(x/12)
f=((i+3)*16)-j; // we beginnen met de a want die is 440hz
f=f/192;
f=pow(y,f);
f=f*220;
frequencyTable[j][i]=(int32_t)(f+0.5);
}
}
//sine table
for (i=0;i<256;i++) {
sineTab[i] = (int16_t)(sin((M_PI*i)/128)*32760);
}
isStaticInit = 1;
}
//init instance
SELF->overlapCnt = 0;
SELF->playPosition = 0; // waar is de song nu?
SELF->playStep = 0;
SELF->subsongNr = 0;
SELF->playFlg = 0;
SELF->pauseFlg = 0;
SELF->loopCnt = 0;
SELF->patternDelay = 0;
SELF->playSpeed = 0;
SELF->masterVolume = 256;
SELF->playMode = SE_PM_SONG;
jaymix_setInterp(&SELF->itp, ITP_CUBIC);
SELF->song = NULL;
SELF->subsong = NULL;
//initialize rendering counters and speed
SELF->timeCnt = 2200;
SELF->timeSpd = 2200;
clearSoundBuffers(SELF);
SELF->delayCnt=0;
return SELF;
}
void jaytrax_free(JT1Player* SELF) {
free(SELF);
}
void jaytrax_setInterpolation(JT1Player* SELF, uint8_t id) {
jaymix_setInterp(&SELF->itp, id);
}
void jaytrax_renderChunk(JT1Player* SELF, int16_t* outbuf, int32_t nrofsamples, int32_t frequency) {
int16_t ic, is;
int32_t r;
int16_t amplification; // amount to amplify afterwards
uint16_t echodelaytime; //delaytime for echo (differs for MIDI or songplayback)
int16_t chanNr;
// we calc nrofsamples samples in blocks of 'timeCnt' big (de songspd)
r = 0;
echodelaytime = amplification = 0;
while (nrofsamples > 0) {
int32_t availOvlap, frameLen;
int16_t nos;
frameLen = (SELF->timeSpd * frequency) / 44100;
availOvlap = MIN(WANTEDOVERLAP, frameLen);
if (SELF->timeCnt<nrofsamples) {
nos = SELF->timeCnt; //Complete block
SELF->timeCnt = frameLen;
} else {
nos = nrofsamples; //Last piece
SELF->timeCnt = SELF->timeCnt - nos;
}
nrofsamples-=nos;
if (!outbuf) {
//times two for stereo
r += (nos*2);
} else {
if (!SELF->song || !SELF->subsong || SELF->subsong->nrofchans == 0) {
for(is=0; is < nos; is++) { //clean renderbuffer
outbuf[r++] = 0;
outbuf[r++] = 0;
}
} else {
chanNr = SELF->subsong->nrofchans;
//preparation of wave pointers and freq offset
for(ic=0; ic < chanNr; ic++) {
JT1Voice* vc;
int16_t instnr;
int16_t volMain, volEcho;
vc = &SELF->voices[ic];
instnr = vc->instrument;
if (instnr == -1) { // mute?
vc->wavePtr = NULL;
} else {
if(vc->sampledata) {
vc->wavePtr = (int16_t*)vc->sampledata;
} else {
JT1Inst* inst = SELF->song->instruments[instnr];
vc->wavePtr = &vc->waves[256*inst->waveform];
vc->waveLength = ((inst->wavelength-1)<<8)+255; //fixed point 8 bit (last 8 bits should be set)
}
}
//calculate frequency
if (vc->curfreq < 10) vc->curfreq = 10;
vc->freqOffset = (256*vc->curfreq)/frequency * (vc->freqOffset<0 ? -1 : 1);
if (vc->curpan == 0) { //panning?
vc->gainMainL = 256; //center
vc->gainMainR = 256;
} else {
if (vc->curpan > 0) {
vc->gainMainL = 256-(vc->curpan);
vc->gainMainR = 256;
} else {
vc->gainMainL = 256;
vc->gainMainR = 256+(vc->curpan);
}
}
//gains
volMain = (vc->curvol+10000)/39;
if (volMain > 256) volMain = 256;
volEcho = SELF->subsong->delayamount[ic];
//premultiply volumes
vc->gainMainL = (vc->gainMainL * volMain)>>8;
vc->gainMainR = (vc->gainMainR * volMain)>>8;
vc->gainEchoL = (vc->gainMainL * volEcho)>>8;
vc->gainEchoR = (vc->gainMainR * volEcho)>>8;
}
amplification = SELF->subsong->amplification;
echodelaytime = SELF->subsong->delaytime;
//main render
while (nos > 0) {
int16_t morenos = MIN(nos, MIXBUF_LEN);
int16_t* overBuf = &SELF->overlapBuffer[0];
int16_t* delLBuf = &SELF->leftDelayBuffer[0];
int16_t* delRBuf = &SELF->rightDelayBuffer[0];
int32_t* tempBuf = &SELF->tempBuf[0];
jaymix_mixCore(SELF, morenos);
for(is=0; is < morenos; is++) {
int32_t lsample, rsample, echosamplel, echosampler;
int32_t off = MIXBUF_NR * is;
int32_t ocnt = SELF->overlapCnt;
int32_t delcnt = SELF->delayCnt;
lsample = tempBuf[off + BUF_MAINL];
rsample = tempBuf[off + BUF_MAINR];
echosamplel = tempBuf[off + BUF_ECHOL];
echosampler = tempBuf[off + BUF_ECHOR];
lsample = ((lsample / chanNr) + delLBuf[delcnt]) / 2;
lsample *= amplification;
lsample /= 100;
CLAMP(lsample, -32760, 32760);
rsample = ((rsample / chanNr) + delRBuf[delcnt]) / 2;
rsample *= amplification;
rsample /= 100;
CLAMP(rsample, -32760, 32760);
//interpolate from overlap buffer
if(ocnt < availOvlap) {
int32_t lovlapsamp, rovlapsamp;
lovlapsamp = overBuf[ocnt*2+0];
rovlapsamp = overBuf[ocnt*2+1];
lsample = ((lsample * (ocnt)) / availOvlap) + ((lovlapsamp * (availOvlap - ocnt)) / availOvlap);
rsample = ((rsample * (ocnt)) / availOvlap) + ((rovlapsamp * (availOvlap - ocnt)) / availOvlap);
SELF->overlapCnt++;
}
outbuf[r++] = lsample;
outbuf[r++] = rsample;
delLBuf[delcnt] = ((echosamplel / chanNr) + delLBuf[delcnt]) / 2;
delRBuf[delcnt] = ((echosampler / chanNr) + delRBuf[delcnt]) / 2;
SELF->delayCnt++;
SELF->delayCnt %= echodelaytime / (44100 / frequency);
}
nos -= morenos;
}
}
}
if(SELF->timeCnt == frameLen) {
int32_t tempdelaycnt;
struct {
int32_t synthPos;
int32_t sampPos;
int32_t freqOffset;
} temp[SE_NROFCHANS];
tempdelaycnt = SELF->delayCnt;
for(ic=0; ic < SE_NROFCHANS; ic++) {
JT1Voice* vc = &SELF->voices[ic];
temp[ic].synthPos = vc->synthPos;
temp[ic].sampPos = vc->samplepos;
temp[ic].freqOffset = vc->freqOffset;
}
if (outbuf && SELF->song && SELF->subsong && SELF->subsong->nrofchans != 0) {
int16_t nos2 = availOvlap;
chanNr = SELF->subsong->nrofchans;
//render to overlap buffer
assert(availOvlap - SELF->overlapCnt == 0);
while (nos2 > 0) {
int16_t morenos = MIN(nos2, MIXBUF_LEN);
int16_t* overBuf = &SELF->overlapBuffer[0];
int16_t* delLBuf = &SELF->leftDelayBuffer[0];
int16_t* delRBuf = &SELF->rightDelayBuffer[0];
int32_t* tempBuf = &SELF->tempBuf[0];
jaymix_mixCore(SELF, morenos);
for(is=0; is < morenos; is++) {
int32_t lsample, rsample;
int32_t off = MIXBUF_NR * is;
int32_t ocnt = SELF->overlapCnt;
int32_t delcnt = SELF->delayCnt;
lsample = tempBuf[off + BUF_MAINL];
rsample = tempBuf[off + BUF_MAINR];
lsample = ((lsample / chanNr) + delLBuf[delcnt]) / 2;
lsample *= amplification;
lsample /= 100;
CLAMP(lsample, -32760, 32760);
rsample = ((rsample / chanNr) + delRBuf[delcnt]) / 2;
rsample *= amplification;
rsample /= 100;
CLAMP(rsample, -32760, 32760);
overBuf[(availOvlap - ocnt)*2+0] = lsample;
overBuf[(availOvlap - ocnt)*2+1] = rsample;
SELF->delayCnt++;
SELF->delayCnt %= echodelaytime / (44100 / frequency);
SELF->overlapCnt--;
}
nos2 -= morenos;
}
assert(SELF->overlapCnt == 0);
}
SELF->delayCnt = tempdelaycnt;
for(ic=0; ic < SE_NROFCHANS; ic++) {
JT1Voice* vc = &SELF->voices[ic];
vc->synthPos = temp[ic].synthPos;
vc->samplepos = temp[ic].sampPos;
vc->freqOffset = temp[ic].freqOffset;
}
//Update song pointers
advanceSong(SELF);
}
}
}
int32_t jaytrax_getLength(JT1Player* SELF, int subsongnr, int loopCnt, int frequency) {
int32_t length = 0;
int32_t lengthMax = frequency * 60 * 30;
int32_t frameLen;
jaytrax_changeSubsong(SELF, subsongnr);
while (SELF->playFlg && SELF->loopCnt < loopCnt && length < lengthMax) {
frameLen = (SELF->timeSpd * frequency) / 44100;
advanceSong(SELF);
length += frameLen;
}
return length < lengthMax ? length : -1;
}