void pre_emphasis(fract32 data[], int arr_length) { fract32 xBuffer[BUFFER_SIZE] = {0}; // input buffer fract32 yBuffer[BUFFER_SIZE] = {0}; // output buffer int current = 0; int index; for (index = 0; index < arr_length; index++) { fract32 temp_b0 = mult_fr1x32x32(shelving_coef.b0, data[index]); fract32 temp_b1 = mult_fr1x32x32(shelving_coef.b1, xBuffer[INDEX(current-1)]); fract32 temp_b2 = mult_fr1x32x32(shelving_coef.b2, xBuffer[INDEX(current-2)]); fract32 temp_a1 = mult_fr1x32x32(shelving_coef.a1, yBuffer[INDEX(current-1)]); fract32 temp_a2 = mult_fr1x32x32(shelving_coef.a2, yBuffer[INDEX(current-2)]); fract32 temp_b = add_fr1x32(add_fr1x32(temp_b0, temp_b1), temp_b2); fract32 temp_a = add_fr1x32(temp_a1, temp_a2); fract32 temp = sub_fr1x32(temp_b, temp_a); yBuffer[current] = shl_fr1x32(temp, 2); xBuffer[current] = data[index]; //input data[index] = yBuffer[current]; //output current++; current %= BUFFER_SIZE; } }
// calculate modulated and bandlimited waveshape static inline void osc_calc_wm(osc* osc) { fract32 sm; // mod shape // fract32 sl; // shape limit given current freq // add modulation sm = add_fr1x32(osc->shape, mult_fr1x32x32(osc->wmIn, osc->wmAmt) ); //- hacky magic formula for pseudo-bandlimiting: //- with maximal bandlimiting, want to limit shape to a function of unit freq //- max freq = min shape, min freq = max shape // : // map phase increment to [0,1] fract32 /* sl = (fract32)(((u32)(osc->inc) - incRange) * shapeLimMul); */ /* // invert [0,1] to [1,0] */ /* sl = sub_fr1x32(FR32_MAX, sl); */ /* // limit */ /* if(sl < sm) { */ /* sm = dsp_lerp32(sm, sl, osc->bandLim); */ /* } */ // ok, time for serious bullshit! sm = sub_fr1x32(sm, mult_fr1x32x32( (fract32)(fix16_sub(osc->inc, incMin) * shapeLimMul), osc->bandLim ) ); if(sm < 0) { sm = 0; } osc->shapeMod = sm; }
void module_process_frame(void) { static fract32 tmpDel, tmpSvf; u8 i; tmpDel = 0; tmpSvf = 0; // mix inputs to delay lines mix_del_inputs(); /// TEST for(i=0; i<NLINES; i++) { // process fade integrator // lines[i].fadeWr = filter_ramp_tog_next(&(lpFadeWr[i])); lines[i].fadeRd = filter_ramp_tog_next(&(lpFadeRd[i])); // process delay line tmpDel = delayFadeN_next( &(lines[i]), in_del[i]); // process filters // check integrators for filter params if( !(svfCutSlew[i].sync) ) { filter_svf_set_coeff( &(svf[i]), filter_1p_lo_next(&(svfCutSlew[i])) ); } if( !(svfRqSlew[i].sync) ) { filter_svf_set_rq( &(svf[i]), filter_1p_lo_next(&(svfRqSlew[i])) ); } tmpSvf = filter_svf_next( &(svf[i]), tmpDel); // mix tmpDel = mult_fr1x32x32( tmpDel, mix_fdry[i] ); tmpDel = add_fr1x32(tmpDel, mult_fr1x32x32(tmpSvf, mix_fwet[i]) ); out_del[i] = tmpDel; } // end lines loop // mix outputs to DACs /// TEST /* out[0] = in[0]; */ /* out[1] = in[1]; */ /* out[2] = in[2]; */ /* out[3] = in[3]; */ out[0] = out[1] = out[2] = out[3] = 0x00000000; mix_outputs(); /// do CV output if( cvSlew[cvChan].sync ) { ;; } else { cvVal[cvChan] = filter_1p_lo_next(&(cvSlew[cvChan])); dac_update(cvChan, cvVal[cvChan]); } if(++cvChan == 4) { cvChan = 0; } }
// interpolated write (overwrites old contents) void buffer_tap_write(bufferTap *tap, fract32 val) { static s32 idxB; static fract32 a, b; a = mult_fr1x32x32(val, sub_fr1x32(FR32_MAX, tap->idx.fr)); b = mult_fr1x32x32(val, tap->idx.fr); idxB = tap->idx.i + 1; while(idxB >= tap->loop) { idxB -= tap->loop; } // we can assume idxA is already wrapped tap->buf->data[tap->idx.i] = a; tap->buf->data[idxB] = b; }
// interpolated arbitrary mix of old buffer contents with new void buffer_tap_mix(bufferTap *tap, fract32 val, fract32 preLevel) { static s32 idxB; static fract32 a, b; a = mult_fr1x32x32(val, sub_fr1x32(FR32_MAX, tap->idx.fr)); b = mult_fr1x32x32(val, tap->idx.fr); idxB = tap->idx.i + 1; while(idxB > tap->loop) { idxB -= tap->loop; } // we can assume idxA is already wrapped tap->buf->data[tap->idx.i] = add_fr1x32(a, mult_fr1x32x32(tap->buf->data[tap->idx.i], preLevel)); tap->buf->data[tap->idx.i] = add_fr1x32(b, mult_fr1x32x32(tap->buf->data[idxB], preLevel)); tap->buf->data[idxB] = b; }
void mel_filter(fract32 power_fr[], float energy_melband[], int block_exponent) { int scale = 1 << block_exponent*2; int bank_num; for (bank_num = 0; bank_num < BANK_NUM; bank_num++) { int offset = bank_border[bank_num]/125; int L = bank_border[bank_num+2]/125 - bank_border[bank_num]/125; int bank_gain_offset; switch (bank_num) { case 0: bank_gain_offset = bank_border[0]/125; break; case 1: bank_gain_offset = bank_border[2]/125 - bank_border[0]/125; break; default: bank_gain_offset = bank_border[bank_num+1]/125 + bank_border[bank_num]/125 - bank_border[1]/125 - bank_border[0]/125; } int index; for (index = 0; index < L; index++) { fract32 temp = mult_fr1x32x32(power_fr[index+offset+1], bank_gain[index+bank_gain_offset]); energy_melband[bank_num] = energy_melband[bank_num] + fr32_to_float(temp); } energy_melband[bank_num] = energy_melband[bank_num] * scale; energy_melband[bank_num] = log10f(energy_melband[bank_num]); } }
void hamming(fract32 data[]) { int index; for (index = 0; index < WINDOW_LENGTH; index++) { data[index] = mult_fr1x32x32(data[index], hamming_coef[index]); } }
// interpolated read fract32 buffer_tap_read(bufferTap *tap) { static s32 idxB; static fract32 a, b; idxB = tap->idx.i + 1; while(idxB >= tap->loop) { idxB -= tap->loop; } // we can assume idxA is already wrapped a = tap->buf->data[tap->idx.i]; b = tap->buf->data[idxB]; // apply interpolation from fractional index return add_fr1x32(a, mult_fr1x32x32(tap->idx.fr, sub_fr1x32(b, a))); }
static fract32 filter_svf_calc_frame( filter_svf* f, fract32 in) { // fract32 out; f->low = add_fr1x32(f->low, mult_fr1x32x32(f->freq, f->band)); f->high = sub_fr1x32( sub_fr1x32( in, shl_fr1x32(mult_fr1x32x32(f->rq, f->band), f->rqShift) ), f->low ); f->band = add_fr1x32(f->band, mult_fr1x32x32(f->freq, f->high) ); // f->notch = add_fr1x32(f->low, f->high); // return out; return *(f->mode); }
// calculate phase static inline void osc_calc_pm(osc* osc) { osc->idxMod = fix16_add( osc->idx, fix16_mul( FRACT_FIX16( mult_fr1x32x32( osc->pmIn, osc->pmAmt ) ), WAVE_TAB_MAX16 ) ); // wrap negative while (BIT_SIGN_32(osc->idxMod)) { osc->idxMod = fix16_add(osc->idxMod, WAVE_TAB_MAX16); } // wrap positive while(osc->idxMod > WAVE_TAB_MAX16) { osc->idxMod = fix16_sub(osc->idxMod, WAVE_TAB_MAX16); } }
void calc_mfcc(fract32 input_fr[], float mfcc_row[]) { int i; int block_exponent; rfft_fr32(input_fr, fft_spectrum, twiddle_table, TWIDDLE_STRIDE, WINDOW_LENGTH, &block_exponent, DYNAMIC_SCALING); fract32 power_spectrum[WINDOW_LENGTH]; for (i = 0; i < WINDOW_LENGTH; ++i) { fract32 absolute = cabs_fr32(fft_spectrum[i]); power_spectrum[i] = mult_fr1x32x32(absolute, absolute); } float energy_melband[BANK_NUM] = {0.0}; mel_filter(power_spectrum, energy_melband, block_exponent); discrete_cosine_transform(energy_melband, mfcc_row); }
// interpolated read extern fract32 echoTap24_8_read(echoTap24_8* echoTap){ s32 loop = echoTap->tapWr->loop * 256; s32 idx = (echoTap->tapWr->idx * 256 + loop - echoTap->echoTime) % loop; u32 samp1_index = idx / 256; u32 samp2_index = ( (idx + 256) % loop ) / 256 ; fract32 samp1 = echoTap->tapWr->buf->data[samp1_index ]; fract32 samp2 = echoTap->tapWr->buf->data[samp2_index ]; fract32 inter_sample = FR32_MAX/256 * (idx % 256); u8 samp1_sign = abs(samp1) / samp1; u8 samp2_sign = abs(samp2) / samp2; echoTap->zero_crossing = (samp1_sign != samp2_sign); fract32 pre_fader = pan_lin_mix(samp1, samp2, inter_sample) ; s32 fader = echoTap24_8_envelope(echoTap); fract32 post_fader = mult_fr1x32x32 ( pre_fader, fader); return post_fader; }
float calc_energy(fract32 data[], int arr_length) { int shift = 9; // shift = log_2(arr_length) fract32 energy_fr = float_to_fr32(0.0); int index; for (index = 0; index < arr_length; index++) { fract32 temp = mult_fr1x32x32(data[index], data[index]); temp = shl_fr1x32(temp, -shift); // right shift in case of overflow energy_fr = add_fr1x32(energy_fr, temp); } float energy = fr32_to_float(energy_fr) * (1<<shift); return energy; }
s32 echoTap24_8_envelope(echoTap24_8 *tap){ s32 center = (tap->echoMin + tap->echoMax+1) / 2; s32 dist_from_center = tap->echoTime - center; if ( dist_from_center < 0 ) dist_from_center *= -1; s32 max_dist_from_center = (tap->echoMax - tap->echoMin +1) / 2 ; s32 scale_factor = FR32_MAX / max_dist_from_center; s32 amplitude; //FIXME add SHAPE_FADESHORT, SHAPE_FADEMEDIUM, SHAPE_FADELONG if( tap->shape ==SHAPE_TOPHAT) { amplitude = FR32_MAX; } else if( tap->shape ==SHAPE_TRIANGLE) { amplitude = dist_from_center * scale_factor; amplitude = FR32_MAX - amplitude; } else if( tap->shape ==SHAPE_LUMP) { amplitude = dist_from_center * scale_factor; amplitude = mult_fr1x32x32(amplitude, amplitude); amplitude = FR32_MAX - amplitude; } else if( tap->shape ==SHAPE_FATLUMP) { amplitude = dist_from_center * scale_factor; amplitude = mult_fr1x32x32(amplitude, amplitude); amplitude = mult_fr1x32x32(amplitude, amplitude); amplitude = FR32_MAX - amplitude; } else if( tap->shape ==SHAPE_OBESELUMP) { amplitude = dist_from_center * scale_factor; amplitude = mult_fr1x32x32(amplitude, amplitude); amplitude = mult_fr1x32x32(amplitude, amplitude); amplitude = mult_fr1x32x32(amplitude, amplitude); amplitude = FR32_MAX - amplitude; } else { amplitude = FR32_MAX; } return amplitude ; }
static void mix_outputs(void) { fract32 mul; //fract32 oscs; //-- out 0 out[0] = 0; // osc mul = mix_osc_dac[0][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(voice[0].out, mul)); mul = mix_osc_dac[1][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(voice[1].out, mul)); // adc mul = mix_adc_dac[0][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[3], mul)); //-- out 1 out[1] = 0; // osc mul = mix_osc_dac[0][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(voice[0].out, mul)); mul = mix_osc_dac[1][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(voice[1].out, mul)); // adc mul = mix_adc_dac[0][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[3], mul)); ////////////////// /// TEST: skip outs 3+4, see where we run out of CPU... out[2] = out[0]; out[3] = out[1]; return; ///////////// //////////// //-- out 2 out[2] = 0; // osc mul = mix_osc_dac[0][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(voice[0].out, mul)); mul = mix_osc_dac[1][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(voice[1].out, mul)); // adc mul = mix_adc_dac[0][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[3], mul)); //-- out 3 out[3] = 0; // osc mul = mix_osc_dac[0][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(voice[0].out, mul)); mul = mix_osc_dac[1][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(voice[1].out, mul)); // adc mul = mix_adc_dac[0][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[3], mul)); }
// mix delay inputs static void mix_del_inputs(void) { // u8 i, j; // fract32* pIn; fract32 mul; //--- del 0 in_del[0] = 0; //adc->del mul = mix_adc_del[0][0]; in_del[0] = add_fr1x32(in_del[0], mult_fr1x32x32(in[0], mul)); mul = mix_adc_del[1][0]; in_del[0] = add_fr1x32(in_del[0], mult_fr1x32x32(in[1], mul)); mul = mix_adc_del[2][0]; in_del[0] = add_fr1x32(in_del[0], mult_fr1x32x32(in[2], mul)); mul = mix_adc_del[3][0]; in_del[0] = add_fr1x32(in_del[0], mult_fr1x32x32(in[3], mul)); // del->del mul = mix_del_del[0][0]; in_del[0] = add_fr1x32(in_del[0], mult_fr1x32x32(out_del[0], mul)); mul = mix_del_del[1][0]; in_del[0] = add_fr1x32(in_del[0], mult_fr1x32x32(out_del[1], mul)); //--- del 1 in_del[1] = 0; // adc mul = mix_adc_del[0][1]; in_del[1] = add_fr1x32(in_del[1], mult_fr1x32x32(in[0], mul)); mul = mix_adc_del[1][1]; in_del[1] = add_fr1x32(in_del[1], mult_fr1x32x32(in[1], mul)); mul = mix_adc_del[2][1]; in_del[1] = add_fr1x32(in_del[1], mult_fr1x32x32(in[2], mul)); mul = mix_adc_del[3][1]; in_del[1] = add_fr1x32(in_del[1], mult_fr1x32x32(in[3], mul)); // del mul = mix_del_del[0][1]; in_del[1] = add_fr1x32(in_del[1], mult_fr1x32x32(out_del[0], mul)); mul = mix_del_del[1][1]; in_del[1] = add_fr1x32(in_del[1], mult_fr1x32x32(out_del[1], mul)); }
static void mix_outputs(void) { fract32 mul; //-- out 0 out[0] = 0; // del mul = mix_del_dac[0][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(out_del[0], mul)); mul = mix_del_dac[1][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(out_del[1], mul)); // adc mul = mix_adc_dac[0][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][0]; out[0] = add_fr1x32(out[0], mult_fr1x32x32(in[3], mul)); //-- out 1 out[1] = 0; // del mul = mix_del_dac[0][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(out_del[0], mul)); mul = mix_del_dac[1][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(out_del[1], mul)); // adc mul = mix_adc_dac[0][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][1]; out[1] = add_fr1x32(out[1], mult_fr1x32x32(in[3], mul)); //-- out 2 out[2] = 0; // del mul = mix_del_dac[0][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(out_del[0], mul)); mul = mix_del_dac[1][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(out_del[1], mul)); // adc mul = mix_adc_dac[0][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][2]; out[2] = add_fr1x32(out[2], mult_fr1x32x32(in[3], mul)); //-- out 3 out[3] = 0; // del mul = mix_del_dac[0][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(out_del[0], mul)); mul = mix_del_dac[1][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(out_del[1], mul)); // adc mul = mix_adc_dac[0][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[0], mul)); mul = mix_adc_dac[1][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[1], mul)); mul = mix_adc_dac[2][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[2], mul)); mul = mix_adc_dac[3][3]; out[3] = add_fr1x32(out[3], mult_fr1x32x32(in[3], mul)); }
// arbitrary mix of old buffer contents with new void buffer_tapN_mix(bufferTapN *tap, fract32 val, fract32 preLevel) { tap->buf->data[tap->idx] = add_fr1x32( mult_fr1x32x32(tap->buf->data[tap->idx], preLevel), val ); }
// frame calculation static void calc_frame(void) { #if 1 u8 i; wavesVoice* v; for(i=0; i<WAVES_NVOICES; i++) { v = &(voice[i]); // oscillator class includes hz and mod integrators v->oscOut = shr_fr1x32( osc_next( &(v->osc) ), 2); // phase mod with fixed 1-frame delay osc_pm_in( &(v->osc), v->pmIn ); // shape mod with fixed 1-frame delay osc_wm_in( &(v->osc), v->wmIn ); // process filter integrators and set filter_svf_set_coeff( &(v->svf), filter_1p_lo_next( &(v->cutSlew) ) ); filter_svf_set_rq( &(v->svf), filter_1p_lo_next( &(v->rqSlew) ) ); // process filter v->svfOut = filter_svf_next( &(v->svf), shr_fr1x32(v->oscOut, 1) ); // process amp smoother v->amp = filter_1p_lo_next( &(v->ampSlew) ); // mix to output bus v->out = mult_fr1x32x32(v->amp, add_fr1x32(mult_fr1x32x32( v->oscOut, v->fDry), mult_fr1x32x32( v->svfOut, v->fWet) ) ); } // end voice loop /// FIXME: later, more voices, mod matrix, arbitrary mod delay. /// for now, simple direct mod feedback routing and 1-frame delay. voice[0].pmIn = voice[1].oscOut; // voice[0].wmIn = voice[1].oscOut << 1; voice[1].pmIn = voice[0].oscOut; // voice[1].wmIn = voice[0].oscOut << 1; // mix outputs using matrix mix_outputs(); #else /* // fract32 out1, out0; */ /* // osc output */ /* oscOut1 = shr_fr1x32(osc_next( &(osc1) ), 2); */ /* oscOut0 = shr_fr1x32(osc_next( &(osc0) ), 2); */ /* // phase mod feedback with 1frame delay */ /* osc_pm_in( &osc1, oscOut0 ); */ /* osc_pm_in( &osc0, oscOut1 ); */ /* // shape mod feedback with 1frame delay */ /* osc_wm_in( &osc1, oscOut0 ); */ /* osc_wm_in( &osc0, oscOut1 ); */ /* /////////// */ /* /////////// */ /* // apply filters */ /* if( !(svfCutSlew[i].sync) ) { */ /* filter_svf_set_coeff( &(svf[i]), filter_1p_lo_next(&(svfCutSlew[i])) ); */ /* } */ /* if( !(svfRqSlew[i].sync) ) { */ /* filter_svf_set_rq( &(svf[i]), filter_1p_lo_next(&(svfRqSlew[i])) ); */ /* } */ /* // svfOut1 = shl_fr1x32(filter_svf_next( &(svf1), shr_fr1x32(oscOut1, 1)), 1); */ /* // svfOut2 = shl_fr1x32(filter_svf_next( &(svf2), shr_fr1x32(oscOut2, 1)), 1); */ /* svfOut1 = filter_svf_next( &(svf1), shr_fr1x32(oscOut1, 1)); */ /* svfOut0 = filter_svf_next( &(svf0), shr_fr1x32(oscOut0, 1)); */ /* ///////// */ /* ///////// */ /* // amp smoothers */ /* oscAmp1 = filter_1p_lo_next(amp1Lp); */ /* oscAmp0 = filter_1p_lo_next(amp0Lp); */ /* // apply osc amplitudes and sum */ /* oscOut1 = mult_fr1x32x32(oscAmp1, */ /* add_fr1x32(mult_fr1x32x32( oscOut1, fdry1), */ /* mult_fr1x32x32( svfOut1, fwet1) */ /* )); */ /* oscOut0 = mult_fr1x32x32(oscAmp0, */ /* add_fr1x32(mult_fr1x32x32( oscOut0, fdry0), */ /* mult_fr1x32x32( svfOut0, fwet0) */ /* )); */ /* //// */ /* /// fixme: mono */ /* frameVal = add_fr1x32( oscOut0, oscOut1); */ /* // mix to output */ /* //...todo */ #endif }
// frame calculation static void calc_frame(void) { int i; wavesVoice* v = voice; fract32* vout = voiceOut; for(i=0; i<WAVES_NVOICES; i++) { // v = &(voice[i]); // oscillator class includes hz and mod integrators v->oscOut = shr_fr1x32( osc_next( &(v->osc) ), 2); // /set modulation - FIXME this is redundant... osc_pm_in( &(v->osc), v->pmIn ); osc_wm_in( &(v->osc), v->wmIn ); // set filter params slew32_calc(v->cutSlew); slew32_calc(v->rqSlew); filter_svf_set_coeff( &(v->svf), v->cutSlew.y ); filter_svf_set_rq( &(v->svf), v->rqSlew.y ); // process filter v->svfOut = filter_svf_next( &(v->svf), shr_fr1x32(v->oscOut, 1) ); // process amp/mix smoothing slew32_calc(v->ampSlew); slew16_calc(v->drySlew); slew16_calc(v->wetSlew); // mix dry/filter and apply amp *vout = mult_fr1x32x32( v->ampSlew.y, add_fr1x32( mult_fr1x32( trunc_fr1x32(v->oscOut), v->drySlew.y ), mult_fr1x32( trunc_fr1x32(v->svfOut), v->wetSlew.y ) ) ); // advance phase del indices v->pmDelWrIdx = (v->pmDelWrIdx + 1) & WAVES_PM_DEL_SAMPS_1; v->pmDelRdIdx = (v->pmDelRdIdx + 1) & WAVES_PM_DEL_SAMPS_1; // set pm input from delay v->pmIn = v->pmDelBuf[v->pmDelRdIdx]; // no tricky modulation routing here! v->wmIn = v->pmDelBuf[v->pmDelRdIdx]; // advance pointers vout++; v++; } // end voice loop // // simple cross-patch modulation // add delay, before filter voice[0].pmDelBuf[voice[0].pmDelWrIdx] = voice[1].oscOut; voice[1].pmDelBuf[voice[1].pmDelWrIdx] = voice[0].oscOut; /* voice[0].pmIn = voice[1].oscOut; */ /* voice[1].pmIn = voice[0].oscOut; */ // zero the outputs out[0] = out[1] = out[2] = out[3] = 0; // patch filtered oscs outputs mix_voice(); // oatch adc mix_adc(); }
// frame calculation static void calc_frame(void) { // ----- smoothers: // amp amp = filter_1p_fix16_next(ampLp); // time if(timeLp->sync) { ;; } else { time = filter_1p_fix16_next(timeLp); buffer_tap_sync(&tapRd, &tapWr, time); #if ARCH_LINUX if(dbgFlag) { fprintf(dbgFile, "%d \t %f \r\n", dbgCount, fix16_to_float(time) ); dbgCount++; } #endif } // rate //// NOTE: setting a different rate is pretty much pointless in this simple application. /// leaving it in just to test fractional interpolation methods. if(rateLp->sync) { ;; } else { rate = filter_1p_fix16_next(rateLp); buffer_tap_set_rate(&tapRd, rate); buffer_tap_set_rate(&tapWr, rate); } // get interpolated echo value echoVal = buffer_tap_read(&tapRd); /* // store interpolated input+fb value */ // buffer_tap_write(&tapWr, add_fr1x32(in0, mult_fr1x32x32(echoVal, fb ) ) ); buffer_tap_write(&tapWr, add_fr1x32(in0 >> 1, mult_fr1x32x32(echoVal, fb ) ) ); //FIXME: clip / saturate input buf here //// potentially, scale input by inverse feedback /// test: no fb //buffer_tap_write(&tapWr, in0); /* // output */ frameVal = add_fr1x32( mult_fr1x32x32( echoVal, FIX16_FRACT_TRUNC(amp) ), mult_fr1x32x32( in0, FIX16_FRACT_TRUNC(dry) ) ); //// test: no dry // frameVal = echoVal; /// FIXME: clip here buffer_tap_next(&tapRd); buffer_tap_next(&tapWr); }