Пример #1
0
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);
}
Пример #2
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);
}
Пример #3
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++;
				}
			}	
		}
	}
}