void *init(MachineTable *mt, const char *name) { /* Allocate and initiate instance data here */ FboxData *data = (FboxData *)malloc(sizeof(FboxData)); memset(data, 0, sizeof(FboxData)); data->midiC = 0; // filter stuff SETUP_SATANS_MATH(mt); data->cutoff = 10000.0; data->resonance = 2.0; data->freq = 44100.0; data->filter_type = 0; calc_filter(data); /* return pointer to instance data */ return (void *)data; }
void main() { // set up the cosine and sin matched filters for searching // also initialize searching buffer //For times within window set up the sine and cosine //Precalculate the cos and sin values (calculate as double, cast down to float) calc_filter(mfc, mfs, buf); //Initialize the searching buffer. // initialize clock buffer for (i=0;i<L;i++) clockbuf[i] = 0; // set up clock buffer to play modulated sinc centered at zero ///////////////////////////////////////////// for (i=-N;i<=N;i++){ x = i*BW; if (i!=0) { t = i*CBW; y = 32767.0*cos(2*PI*t)*sin(PI*x)/(PI*x); // double (Modulated sinc) } else { y = 32767.0; } j = i; if (j<0) { j += L; // wrap } clockbuf[j] = (short) y; } /////////////////////////////////////////////// init_codec(config, hCodec); while(1) // main loop { } }
void execute(MachineTable *mt, void *data) { FboxData *ld = (FboxData *)data; SignalPointer *midiS = mt->get_input_signal(mt, "midi"); SignalPointer *s = mt->get_input_signal(mt, "Stereo"); SignalPointer *os = mt->get_output_signal(mt, "Stereo"); if(os == NULL ) return; FTYPE *ou = mt->get_signal_buffer(os); int ol = mt->get_signal_samples(os); int oc = mt->get_signal_channels(os); if(s == NULL) { // just clear output, then return int t; for(t = 0; t < ol; t++) { ou[t * 2 + 0] = itoFTYPE(0); ou[t * 2 + 1] = itoFTYPE(0); } return; } void **midi = NULL; FTYPE *in = mt->get_signal_buffer(s); int ic = mt->get_signal_channels(s); if(midiS != NULL) midi = mt->get_signal_buffer(midiS); ld->freq = (float)mt->get_signal_frequency(os); int c; int i; int new_valu = -1; FTYPE d, tmp; calc_filter(ld); for(i = 0; i < ol; i++) { if(midi != NULL && midi[i] != NULL) { MidiEvent *mev = (MidiEvent *)midi[i]; if( (mev != NULL) && ((mev->data[0] & 0xf0) == MIDI_CONTROL_CHANGE) && ((mev->data[0] & 0x0f) == ld->midiC) ) { new_valu = mev->data[2]; } } for(c = 0; c < oc; c++) { d = in[i * ic + c]; tmp = mulFTYPE(ld->coef[0], d) + mulFTYPE(ld->coef[1], ld->hist_x[c * 2]) + mulFTYPE(ld->coef[2], ld->hist_x[c * 2 + 1]) + mulFTYPE(ld->coef[3], ld->hist_y[c * 2]) + mulFTYPE(ld->coef[4], ld->hist_y[c * 2 + 1]); ld->hist_y[c * 2 + 1] = ld->hist_y[c * 2]; ld->hist_y[c * 2] = tmp; ld->hist_x[c * 2 + 1] = ld->hist_x[c * 2]; ld->hist_x[c * 2] = d; ou[i * oc + c] = tmp; } } if(new_valu != -1) { ld->cutoff = 15000.0 * (1.0 - pow(1.0 - (((float)new_valu) / 255.0), 0.4)); } }
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++; } } } } }