int PADnote::noteout(float *outl, float *outr) { computecurrentparameters(); float *smps = pars->sample[nsample].smp; if(smps == NULL) { for(int i = 0; i < synth->buffersize; ++i) { outl[i] = 0.0f; outr[i] = 0.0f; } return 1; } float smpfreq = pars->sample[nsample].basefreq; float freqrap = realfreq / smpfreq; int freqhi = (int) (floor(freqrap)); float freqlo = freqrap - floor(freqrap); if(config.cfg.Interpolation) Compute_Cubic(outl, outr, freqhi, freqlo); else Compute_Linear(outl, outr, freqhi, freqlo); if(firsttime) { fadein(outl); fadein(outr); firsttime = false; } NoteGlobalPar.GlobalFilterL->filterout(outl); NoteGlobalPar.GlobalFilterR->filterout(outr); //Apply the punch if(NoteGlobalPar.Punch.Enabled != 0) for(int i = 0; i < synth->buffersize; ++i) { float punchamp = NoteGlobalPar.Punch.initialvalue * NoteGlobalPar.Punch.t + 1.0f; outl[i] *= punchamp; outr[i] *= punchamp; NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt; if(NoteGlobalPar.Punch.t < 0.0f) { NoteGlobalPar.Punch.Enabled = 0; break; } } if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) // Amplitude Interpolation for(int i = 0; i < synth->buffersize; ++i) { float tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, globalnewamplitude, i, synth->buffersize); outl[i] *= tmpvol * NoteGlobalPar.Panning; outr[i] *= tmpvol * (1.0f - NoteGlobalPar.Panning); } else for(int i = 0; i < synth->buffersize; ++i) { outl[i] *= globalnewamplitude * NoteGlobalPar.Panning; outr[i] *= globalnewamplitude * (1.0f - NoteGlobalPar.Panning); } // Apply legato-specific sound signal modifications legato.apply(*this, outl, outr); // Check if the global amplitude is finished. // If it does, disable the note if(NoteGlobalPar.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; } finished_ = 1; } return 1; }
int PADnote::noteout(REALTYPE *outl, REALTYPE *outr) { computecurrentparameters(); REALTYPE *smps = pars->sample[nsample].smp; if(smps == NULL) { for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { outl[i] = 0.0; outr[i] = 0.0; } return 1; } REALTYPE smpfreq = pars->sample[nsample].basefreq; REALTYPE freqrap = realfreq / smpfreq; int freqhi = (int) (floor(freqrap)); REALTYPE freqlo = freqrap - floor(freqrap); if(config.cfg.Interpolation) Compute_Cubic(outl, outr, freqhi, freqlo); else Compute_Linear(outl, outr, freqhi, freqlo); if(firsttime) { fadein(outl); fadein(outr); firsttime = false; } NoteGlobalPar.GlobalFilterL->filterout(outl); NoteGlobalPar.GlobalFilterR->filterout(outr); //Apply the punch if(NoteGlobalPar.Punch.Enabled != 0) { for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { REALTYPE punchamp = NoteGlobalPar.Punch.initialvalue * NoteGlobalPar.Punch.t + 1.0; outl[i] *= punchamp; outr[i] *= punchamp; NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt; if(NoteGlobalPar.Punch.t < 0.0) { NoteGlobalPar.Punch.Enabled = 0; break; } } } if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) { // Amplitude Interpolation for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { REALTYPE tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, globalnewamplitude, i, SOUND_BUFFER_SIZE); outl[i] *= tmpvol * NoteGlobalPar.Panning; outr[i] *= tmpvol * (1.0 - NoteGlobalPar.Panning); } } else { for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { outl[i] *= globalnewamplitude * NoteGlobalPar.Panning; outr[i] *= globalnewamplitude * (1.0 - NoteGlobalPar.Panning); } } // Apply legato-specific sound signal modifications if(Legato.silent) // Silencer if(Legato.msg != LM_FadeIn) for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { outl[i] = 0.0; outr[i] = 0.0; } switch(Legato.msg) { case LM_CatchUp: // Continue the catch-up... if(Legato.decounter == -10) Legato.decounter = Legato.fade.length; for(int 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; PADlegatonote(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(int 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(int 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. PADlegatonote(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 global amplitude is finished. // If it does, disable the note if(NoteGlobalPar.AmpEnvelope->finished() != 0) { for(int 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; } finished_ = 1; } return 1; }