/* * Note Output */ int SUBnote::noteout(float *outl, float *outr) { memcpy(outl, synth.denormalkillbuf, synth.bufferbytes); memcpy(outr, synth.denormalkillbuf, synth.bufferbytes); if(NoteEnabled == OFF) return 0; float tmprnd[synth.buffersize]; float tmpsmp[synth.buffersize]; //left channel for(int i = 0; i < synth.buffersize; ++i) tmprnd[i] = RND * 2.0f - 1.0f; for(int n = 0; n < numharmonics; ++n) { float rolloff = overtone_rolloff[n]; memcpy(tmpsmp, tmprnd, synth.bufferbytes); for(int nph = 0; nph < numstages; ++nph) filter(lfilter[nph + n * numstages], tmpsmp); for(int i = 0; i < synth.buffersize; ++i) outl[i] += tmpsmp[i] * rolloff; } if(GlobalFilterL != NULL) GlobalFilterL->filterout(&outl[0]); //right channel if(stereo) { for(int i = 0; i < synth.buffersize; ++i) tmprnd[i] = RND * 2.0f - 1.0f; for(int n = 0; n < numharmonics; ++n) { float rolloff = overtone_rolloff[n]; memcpy(tmpsmp, tmprnd, synth.bufferbytes); for(int nph = 0; nph < numstages; ++nph) filter(rfilter[nph + n * numstages], tmpsmp); for(int i = 0; i < synth.buffersize; ++i) outr[i] += tmpsmp[i] * rolloff; } if(GlobalFilterR != NULL) GlobalFilterR->filterout(&outr[0]); } else memcpy(outr, outl, synth.bufferbytes); if(firsttick != 0) { int n = 10; if(n > synth.buffersize) n = synth.buffersize; for(int i = 0; i < n; ++i) { float ampfadein = 0.5f - 0.5f * cosf( (float) i / (float) n * PI); outl[i] *= ampfadein; outr[i] *= ampfadein; } firsttick = 0; } if(ABOVE_AMPLITUDE_THRESHOLD(oldamplitude, newamplitude)) // Amplitude interpolation for(int i = 0; i < synth.buffersize; ++i) { float tmpvol = INTERPOLATE_AMPLITUDE(oldamplitude, newamplitude, i, synth.buffersize); outl[i] *= tmpvol * panning; outr[i] *= tmpvol * (1.0f - panning); } else for(int i = 0; i < synth.buffersize; ++i) { outl[i] *= newamplitude * panning; outr[i] *= newamplitude * (1.0f - panning); } oldamplitude = newamplitude; computecurrentparameters(); // Apply legato-specific sound signal modifications legato.apply(*this, outl, outr); // Check if the note needs to be computed more if(AmpEnvelope->finished() != 0) { for(int i = 0; i < synth.buffersize; ++i) { //fade-out float tmp = 1.0f - (float)i / synth.buffersize_f; outl[i] *= tmp; outr[i] *= tmp; } KillNote(); } return 1; }
/* * Note Output */ int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr) { int i; memcpy(outl, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); memcpy(outr, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); if (NoteEnabled==OFF) return(0); //left channel for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0; for (int n=0;n<numharmonics;n++) { memcpy(tmpsmp, tmprnd, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); for (int nph=0;nph<numstages;nph++) filter(lfilter[nph+n*numstages],tmpsmp); for (i=0;i<SOUND_BUFFER_SIZE;i++) outl[i]+=tmpsmp[i]; }; if (GlobalFilterL!=NULL) GlobalFilterL->filterout(&outl[0]); //right channel if (stereo!=0) { for (i=0;i<SOUND_BUFFER_SIZE;i++) tmprnd[i]=RND*2.0-1.0; for (int n=0;n<numharmonics;n++) { memcpy(tmpsmp, tmprnd, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); for (int nph=0;nph<numstages;nph++) filter(rfilter[nph+n*numstages],tmpsmp); for (i=0;i<SOUND_BUFFER_SIZE;i++) outr[i]+=tmpsmp[i]; }; if(GlobalFilterR != NULL) GlobalFilterR->filterout(&outr[0]); } else memcpy(outr, outl, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); if (firsttick!=0) { int n=10; if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; for (i=0;i<n;i++) { REALTYPE ampfadein=0.5-0.5*cos((REALTYPE) i/(REALTYPE) n*PI); outl[i]*=ampfadein; outr[i]*=ampfadein; }; firsttick=0; }; if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude,newamplitude)) { // Amplitude interpolation for (i=0;i<SOUND_BUFFER_SIZE;i++) { REALTYPE tmpvol=INTERPOLATE_AMPLITUDE(oldamplitude ,newamplitude,i,SOUND_BUFFER_SIZE); outl[i]*=tmpvol*panning; outr[i]*=tmpvol*(1.0-panning); }; } else { for (i=0;i<SOUND_BUFFER_SIZE;i++) { outl[i]*=newamplitude*panning; outr[i]*=newamplitude*(1.0-panning); }; }; oldamplitude=newamplitude; computecurrentparameters(); // Apply legato-specific sound signal modifications if (Legato.silent) { // Silencer if (Legato.msg!=LM_FadeIn) { memset(outl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); memset(outr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); }; }; switch (Legato.msg) { case LM_CatchUp : // Continue the catch-up... if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; for (i=0;i<SOUND_BUFFER_SIZE;i++) {//Yea, could be done without the loop... Legato.decounter--; if (Legato.decounter<1) { // Catching-up done, we can finally set // the note to the actual parameters. Legato.decounter=-10; Legato.msg=LM_ToNorm; SUBlegatonote(Legato.param.freq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); break; } } break; case LM_FadeIn : // Fade-in if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; Legato.silent=false; for (i=0;i<SOUND_BUFFER_SIZE;i++) { Legato.decounter--; if (Legato.decounter<1) { Legato.decounter=-10; Legato.msg=LM_Norm; break; } Legato.fade.m+=Legato.fade.step; outl[i]*=Legato.fade.m; outr[i]*=Legato.fade.m; } break; case LM_FadeOut : // Fade-out, then set the catch-up if (Legato.decounter==-10) Legato.decounter=Legato.fade.length; for (i=0;i<SOUND_BUFFER_SIZE;i++) { Legato.decounter--; if (Legato.decounter<1) { for (int j=i;j<SOUND_BUFFER_SIZE;j++) { outl[j]=0.0; outr[j]=0.0; } Legato.decounter=-10; Legato.silent=true; // Fading-out done, now set the catch-up : Legato.decounter=Legato.fade.length; Legato.msg=LM_CatchUp; REALTYPE catchupfreq=Legato.param.freq*(Legato.param.freq/Legato.lastfreq);//This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. SUBlegatonote(catchupfreq, Legato.param.vel, Legato.param.portamento, Legato.param.midinote, false); break; } Legato.fade.m-=Legato.fade.step; outl[i]*=Legato.fade.m; outr[i]*=Legato.fade.m; } break; default : break; } // Check if the note needs to be computed more if (AmpEnvelope->finished()!=0) { for (i=0;i<SOUND_BUFFER_SIZE;i++) {//fade-out REALTYPE tmp=1.0-(REALTYPE)i/(REALTYPE)SOUND_BUFFER_SIZE; outl[i]*=tmp; outr[i]*=tmp; }; KillNote(); }; return(1); };
SUBnote::~SUBnote() { if(NoteEnabled != OFF) KillNote(); }
SUBnote::~SUBnote() { if (NoteEnabled!=OFF) KillNote(); delete [] tmpsmp; delete [] tmprnd; };