void LFO::process(float *data, unsigned int nsamples){ unsigned int i; float d=freq/synth->samplerate(); switch(_type){ case saw: for (i=0;i<nsamples;i++){ data[i]=SAW(phase)*pivotDelta + pivotLevel; phase+=d; } break; case sine: for (i=0;i<nsamples;i++){ data[i]=SIN(phase)*pivotDelta + pivotLevel; phase+=d; } break; } phase=fmod(phase,1.0); }
/** * @short Calculates the chunk for just an oscillator (actually 4), its is more like a voice. */ void Polybase::Oscillator::oscillatorChunk(float *data, unsigned int nsamples){ if (note==0){ // freq 0 == stopped memset(data,0,sizeof(float)*nsamples); return; } #define NWAVES 5 #define NWAVESBLOCK (128/NWAVES) #define SIN(x) (sin(x*2.0*M_PI)) #define SAW(x) (fmod(1.0f+(x*4.0f),2.0)-1.0) #define TRIANGLE(x) ((x>0.25 && x<0.75) ? - SAW(x) : SAW(x)) #define SQUARE(x) (x < 0.5 ? 1.0 : -1.0); #define NOISE(x) (((float(rand())/RAND_MAX)*2.0) - 1.0) unsigned int i; float *temp=data; float os,ds,v; float sr=poly->samplerate(); float pstep[4]={freq[0]/sr, freq[1]/sr, freq[2]/sr, freq[3]/sr}; for (i=0;i<nsamples;i++){ float r=0; for (int o=0;o<4;o++){ phase[o]+=pstep[o]; float form=(poly->oscillatorForm[o]%NWAVESBLOCK)/float(NWAVESBLOCK); int nform=poly->oscillatorForm[o]/NWAVESBLOCK; float mphase=fmod(phase[o],1.0); //DEBUG("nform %d",nform); switch(nform){ case 0: os=SIN(mphase); ds=SAW(mphase); break; case 1: os=SAW(mphase); ds=TRIANGLE(mphase); break; case 2: os=TRIANGLE(mphase); ds=SQUARE(mphase); break; case 3: os=SQUARE(mphase); ds=SIN(mphase); break; default: //DEBUG("NOISE"); os=NOISE(mphase); ds=NOISE(mphase); } v=(os*(1.0-form)) + (ds*form); r+=v*poly->oscillatorLevel[o]/64.0; } *temp=r; temp++; } phase[0]=fmod(phase[0],1.0); phase[1]=fmod(phase[1],1.0); phase[2]=fmod(phase[2],1.0); phase[3]=fmod(phase[3],1.0); }
void execute(MachineTable *mt, void *void_grooveiator) { grooveiator_t *grooveiator = (grooveiator_t *)void_grooveiator; SignalPointer *outsig = NULL; SignalPointer *insig = NULL; insig = mt->get_input_signal(mt, "midi"); if(insig == NULL) return; outsig = mt->get_output_signal(mt, "Mono"); if(outsig == NULL) return; void **midi_in = (void **)mt->get_signal_buffer(insig); if(midi_in == NULL) return; int midi_l = mt->get_signal_samples(insig); FTYPE *out = (FTYPE *)mt->get_signal_buffer(outsig); int out_l = mt->get_signal_samples(outsig); if(midi_l != out_l) return; // we expect equal lengths.. float Fs = (float)mt->get_signal_frequency(outsig); grooveiator->freq = Fs; FTYPE volume = ftoFTYPE(grooveiator->volume); FTYPE wave_mix = ftoFTYPE(grooveiator->wave_mix); int t, n_k; #ifdef THIS_IS_A_MOCKERY SignalPointer *int_sig_a = NULL; SignalPointer *int_sig_b = NULL; int_sig_a = mt->get_mocking_signal(mt, "A"); int_sig_b = mt->get_mocking_signal(mt, "B"); FTYPE *int_out_a = (FTYPE *)mt->get_signal_buffer(int_sig_a); FTYPE *int_out_b = (FTYPE *)mt->get_signal_buffer(int_sig_b); #endif for(t = 0; t < out_l; t++) { // check for midi events MidiEvent *mev = (MidiEvent *)midi_in[t]; if( (mev != NULL) && ((mev->data[0] & 0xf0) == MIDI_CONTROL_CHANGE) && ((mev->data[0] & 0x0f) == grooveiator->midi_channel) ) { int valu = mev->data[2]; grooveiator->cutoff = 15000.0 * (1.0 - pow(1.0 - (((float)valu) / 255.0), 0.4)); } if((mev != NULL) && ((mev->data[0] & 0xf0) == MIDI_PROGRAM_CHANGE) && ((mev->data[0] & 0x0f) == grooveiator->midi_channel) ) { grooveiator->program = mev->data[1]; } if((mev != NULL) && ((mev->data[0] & 0xf0) == MIDI_NOTE_ON) && ((mev->data[0] & 0x0f) == grooveiator->midi_channel) ) { int note = mev->data[1]; float velocity = (float)(mev->data[2]); for(n_k = 0; n_k < POLYPHONY; n_k++) { if(!(grooveiator->note[n_k].active)) { note_t *n = &(grooveiator->note[n_k]); n->active = 1; n->t = 0; n->note = note; n->note_on = 1; n->period_A = (int)(Fs / (float)(note_table[note])); int t_note = note + grooveiator->wave_transpose; n->period_B = (int)(Fs / (float)(note_table[t_note] + grooveiator->wave_detune * ((note_table[t_note+1] - note_table[t_note])/100.0) )); // just make sure we don't hit notes we can't possibly play... if(n->period_A == 0 || n->period_B == 0) { n->active = 0; DYNLIB_DEBUG("note %d out of playable range!\n", note); } // amplitude stuff n->amp_phase = 0; n->amplitude = ftoFTYPE(0.0); n->amp_attack_steps = 1 + (int)((float)grooveiator->amp_attack * (float)Fs); n->amp_attack_step = ftoFTYPE((velocity / 127.0) / n->amp_attack_steps); n->amp_hold_steps = 1 + (int)((float)grooveiator->amp_hold * (float)Fs); n->amp_decay_steps = 1 + (int)((float)grooveiator->amp_decay * (float)Fs); n->amp_decay_step = ftoFTYPE((1.0 - grooveiator->amp_sustain) * (velocity / 127.0) / n->amp_decay_steps); // filter stuff n->fil_phase = 0; n->filter = ftoFTYPE(0.0); n->fil_attack_steps = 1 + (int)((float)grooveiator->fil_attack * (float)Fs); n->fil_attack_step = ftoFTYPE((velocity / 127.0) / n->fil_attack_steps); n->fil_hold_steps = 1 + (int)((float)grooveiator->fil_hold * (float)Fs); n->fil_decay_steps = 1 + (int)((float)grooveiator->fil_decay * (float)Fs); n->fil_decay_step = ftoFTYPE((1.0 - grooveiator->fil_sustain) * (velocity / 127.0) / n->fil_decay_steps); n->hist_x[0] = itoFTYPE(0); n->hist_x[1] = itoFTYPE(0); n->hist_y[0] = itoFTYPE(0); n->hist_y[1] = itoFTYPE(0); break; } } } if((mev != NULL) && ((mev->data[0] & 0xf0) == MIDI_NOTE_OFF) && ((mev->data[0] & 0x0f) == grooveiator->midi_channel) ) { int note = mev->data[1]; float velocity = (float)(mev->data[2]); velocity = velocity / 127.0; for(n_k = 0; n_k < POLYPHONY; n_k++) { if((grooveiator->note[n_k].active) && (grooveiator->note[n_k].note == note) && (grooveiator->note[n_k].note_on)) { note_t *n = &(grooveiator->note[n_k]); n->note_on = 0; n->amp_phase = 4; n->amp_release_steps = 1 + grooveiator->amp_release * Fs / (velocity + 1.0); n->amp_release_step = ftoFTYPE(FTYPEtof(n->amplitude) / (float)(n->amp_release_steps)); n->fil_phase = 4; n->fil_release_steps = 1 + grooveiator->fil_release * Fs / (velocity + 1.0); n->fil_release_step = ftoFTYPE(FTYPEtof(n->filter) / (float)(n->fil_release_steps)); break; } } } /* zero out */ out[t] = itoFTYPE(0); #ifdef __SATAN_USES_FXP // << 8 is to convert fp16p16 to fp8p24 #define SAW(r,x,f) r = (( divfp16p16( itofp16p16(((x)%(f))<<1), itofp16p16(f)) - itofp16p16(1) ) << 8) #else int saw_tempura; #define SAW(r,x,f) { saw_tempura = x % f; r = (2.0f * ((float)saw_tempura / (float)f) - 1.0f); } #endif #define SIN(x,f) ftoFTYPE(SAT_SIN_SCALAR(((x)%(f))/(float)(f))) #define SQR(x,f) ((((x)%(f)) > (f>>1)) ? ftoFTYPE(-1.0) : ftoFTYPE(1.0)) #define COSHALF(x,f) ftoFTYPE(SAT_COS_SCALAR(((x)%(f))/(float)(2*f))) /* process active notes */ for(n_k = 0; n_k < POLYPHONY; n_k++) { note_t *n = &(grooveiator->note[n_k]); if(n->active) { { /* amplitude parameters */ switch(n->amp_phase) { case 0: // attack phase n->amplitude += n->amp_attack_step; n->amp_attack_steps--; if(n->amp_attack_steps < 0) { n->amp_phase++; } break; case 1: // hold phase n->amp_hold_steps--; if(n->amp_hold_steps < 0) { n->amp_phase++; } break; case 2: // decay phase n->amplitude -= n->amp_decay_step; n->amp_decay_steps--; if(n->amp_decay_steps < 0) { n->amp_phase++; } break; case 3: // sustain phase /* hold here until a NOTE_OFF message arrives */ break; case 4: // release phase n->amplitude -= n->amp_release_step; if(n->amplitude < itoFTYPE(0)) { n->amp_release_step = 0; n->amp_release_steps = 0; } n->amp_release_steps--; if(n->amp_release_steps < 0) { n->amplitude = itoFTYPE(0); n->active = 0; } break; } } { /* filter amplitude parameters */ switch(n->fil_phase) { case 0: // attack phase n->filter += n->fil_attack_step; n->fil_attack_steps--; if(n->fil_attack_steps < 0) n->fil_phase++; break; case 1: // hold phase n->fil_hold_steps--; if(n->fil_hold_steps < 0) n->fil_phase++; break; case 2: // decay phase n->filter -= n->fil_decay_step; n->fil_decay_steps--; if(n->fil_decay_steps < 0) n->fil_phase++; break; case 3: // sustain phase /* hold here until a NOTE_OFF message arrives */ break; case 4: // release phase if(n->filter > itoFTYPE(0) && n->fil_release_steps > 0) { n->filter -= n->fil_release_step; n->fil_release_steps--; } if(n->filter < itoFTYPE(0)) n->filter = itoFTYPE(0); break; } } if(((n->t & SAMPLES_PER_FILTER_UPDATE) == 0) && (grooveiator->enable_filter)) { calc_filter(grooveiator, n); } { /* signal generation and filtration */ FTYPE filter_tmp; float tempura2 = 0; int tempura1; FTYPE valX = itoFTYPE(0), valY = itoFTYPE(0), val; switch(grooveiator->wave_A) { case 0: tempura1 = n->t + n->t % n->period_A; SAW(tempura2,tempura1, n->period_A); SAW(valX,n->t,n->period_A); valX = valX - mulFTYPE(ftoFTYPE(0.5), tempura2); #ifdef THIS_IS_A_MOCKERY int_out_a[t] = valX; #endif break; case 1: valX = SIN(n->t,n->period_A) - mulFTYPE(ftoFTYPE(0.5), SIN (n->t + n->t % n->period_A, n->period_A)); break; case 2: valX = SQR(n->t,n->period_A) - mulFTYPE(ftoFTYPE(0.5), SQR (n->t + n->t % n->period_A, n->period_A)); break; case 3: valX = COSHALF(n->t,n->period_A); break; } switch(grooveiator->wave_B) { case 0: tempura1 = n->t + n->t % n->period_A; SAW(tempura2,tempura1, n->period_A); SAW(valX,n->t,n->period_B); valX = valX - mulFTYPE(ftoFTYPE(0.5), tempura2); break; case 1: valY = SIN(n->t,n->period_B) - mulFTYPE(ftoFTYPE(0.5), SIN (n->t + n->t % n->period_B, n->period_B)); break; case 2: valY = SQR(n->t,n->period_B) - mulFTYPE(ftoFTYPE(0.5), SQR (n->t + n->t % n->period_B, n->period_B)); break; case 3: valY = COSHALF(n->t,n->period_B); break; } val = mulFTYPE(itoFTYPE(1) - wave_mix, valX) + mulFTYPE(wave_mix, valY); val = mulFTYPE(val, n->amplitude); #ifdef THIS_IS_A_MOCKERY int_out_b[t] = valX * n->amplitude; #endif if(grooveiator->enable_filter) { filter_tmp = mulFTYPE(n->coef[0], val) + mulFTYPE(n->coef[1], n->hist_x[0]) + mulFTYPE(n->coef[2], n->hist_x[1]) + mulFTYPE(n->coef[3], n->hist_y[0]) + mulFTYPE(n->coef[4], n->hist_y[1]); n->hist_y[1] = n->hist_y[0]; n->hist_y[0] = filter_tmp; n->hist_x[1] = n->hist_x[0]; n->hist_x[0] = val; } else { filter_tmp = val; } out[t] += mulFTYPE(filter_tmp, volume); n->t++; } } } } }