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; }
// 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 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))); }
// 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; }
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); }
// add 32.32 value with overflow/underflow checking void add_fix32(fix32* a, fix32* b) { // tmp fract fract32 tfr = a->fr; // tmp int s32 ti = a->i + b->i; /// FIXME: could be arch-specific inline ASM here for better speed /// (e.g. add fract32, check overflow flag ?) if(tfr >= 0) { if( sub_fr1x32(FRACT32_MAX,tfr) < b->fr) { // wrap by subtraction tfr = sub_fr1x32( add_fr1x32( sub_fr1x32(tfr, FR32_MAX), b->fr), FR32_MAX); ti += 1; // carry } } else { if(b->fr < sub_fr1x32(FRACT32_MAX,tfr)) { // wrap by addition tfr = add_fr1x32( add_fr1x32( add_fr1x32(tfr, FR32_MAX), b->fr), FR32_MAX); ti -= 1; // carry (negative) } } // yet another comparison and carry for negative fr if(tfr < 0) { a->fr = add_fr1x32(FR32_MAX, tfr); a->i = ti -1; } else { a->fr = tfr; a->i = ti; } }
// set target value void filter_ramp_in(filter_ramp* f, fract32 val) { f->x = val; f->sync = (val == f->y); if(BIT_SIGN_32(sub_fr1x32(f->y, f->x))) { f->sinc = negate_fr1x32(f->inc); f->dec = 1; } else { f->sinc = f->inc; f->dec = 0; } }
// read fract32 buffer_tapN_read(bufferTapN *tap) { fract32 a, b; fix16 tmp; #if 1 if(tap->divCount == 0) { return tap->buf->data[tap->idx]; } else { // interpolate during phase-division a = tap->buf->data[tap->idx]; if( (tap->idx + 1) >= tap->loop) { b = tap->buf->data[0]; } else { b = tap->buf->data[ tap->idx + 1 ]; } tmp = FRACT_FIX16( sub_fr1x32(b, a) ); tmp = fix16_mul(tmp, fix16_from_int(tap->divCount)); return add_fr1x32(a, FIX16_FRACT_TRUNC(tmp)); } #else return tap->buf->data[tap->idx]; #endif }
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); } } // lookup static inline fract32 osc_lookup(osc* osc) { u32 idxA = osc->shapeMod >> WAVE_TAB_RSHIFT; u32 idxB = idxA + 1; fract32 mul = (osc->shapeMod & WAVE_TAB_MASK) << WAVE_TAB_LSHIFT; fract32 mulInv = sub_fr1x32(FR32_MAX, mul); return add_fr1x32( mult_fr1x32x32(table_lookup_idx( (fract32*)(*(osc->tab))[idxA], WAVE_TAB_SIZE, osc->idxMod ), mulInv ), mult_fr1x32x32(table_lookup_idx( (fract32*)(*(osc->tab))[idxB], WAVE_TAB_SIZE, osc->idxMod ), mul ) ); } // advance phase static inline void osc_advance(osc* osc) {