inline int comb::process(int input) { int output; output = buffer[bufidx]; undenormalise(output); filterstore = FMUL(output, damp2) + FMUL(filterstore, damp1); undenormalise(filterstore); buffer[bufidx] = input + FMUL(filterstore, feedback); if(++bufidx>=bufsize) bufidx = 0; return output; }
inline float comb::process(float input) { float output; output = buffer[bufidx]; undenormalise(output); filterstore = (output*damp2) + (filterstore*damp1); undenormalise(filterstore); buffer[bufidx] = input + (filterstore*feedback); if(++bufidx>=bufsize) bufidx = 0; return output; }
void Reverb::process(float *p_src,float *p_dst,int p_frames) { if (p_frames>INPUT_BUFFER_MAX_SIZE) p_frames=INPUT_BUFFER_MAX_SIZE; int predelay_frames=lrint((params.predelay/1000.0)*params.mix_rate); if (predelay_frames<10) predelay_frames=10; if (predelay_frames>=echo_buffer_size) predelay_frames=echo_buffer_size-1; for (int i=0;i<p_frames;i++) { if (echo_buffer_pos>=echo_buffer_size) echo_buffer_pos=0; int read_pos=echo_buffer_pos-predelay_frames; while (read_pos<0) read_pos+=echo_buffer_size; float in=undenormalise(echo_buffer[read_pos]*params.predelay_fb+p_src[i]); echo_buffer[echo_buffer_pos]=in; input_buffer[i]=in; p_dst[i]=0; //take the chance and clear this echo_buffer_pos++; } if (params.hpf>0) { float hpaux=expf(-2.0*Math_PI*params.hpf*6000/params.mix_rate); float hp_a1=(1.0+hpaux)/2.0; float hp_a2=-(1.0+hpaux)/2.0; float hp_b1=hpaux; for (int i=0;i<p_frames;i++) { float in=input_buffer[i]; input_buffer[i]=in*hp_a1+hpf_h1*hp_a2+hpf_h2*hp_b1; hpf_h2=input_buffer[i]; hpf_h1=in; } } for (int i=0;i<MAX_COMBS;i++) { Comb &c=comb[i]; int size_limit=c.size-lrintf((float)c.extra_spread_frames*(1.0-params.extra_spread)); for (int j=0;j<p_frames;j++) { if (c.pos>=size_limit) //reset this now just in case c.pos=0; float out=undenormalise(c.buffer[c.pos]*c.feedback); out=out*(1.0-c.damp)+c.damp_h*c.damp; //lowpass c.damp_h=out; c.buffer[c.pos]=input_buffer[j]+out; p_dst[j]+=out; c.pos++; } } static const float allpass_feedback=0.7; /* this one works, but the other version is just nicer.... int ap_size_limit[MAX_ALLPASS]; for (int i=0;i<MAX_ALLPASS;i++) { AllPass &a=allpass[i]; ap_size_limit[i]=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread)); } for (int i=0;i<p_frames;i++) { float sample=p_dst[i]; float aux,in; float AllPass*ap; #define PROCESS_ALLPASS(m_ap) \ ap=&allpass[m_ap]; \ if (ap->pos>=ap_size_limit[m_ap]) \ ap->pos=0; \ aux=undenormalise(ap->buffer[ap->pos]); \ in=sample; \ sample=-in+aux; \ ap->pos++; PROCESS_ALLPASS(0); PROCESS_ALLPASS(1); PROCESS_ALLPASS(2); PROCESS_ALLPASS(3); p_dst[i]=sample; } */ for (int i=0;i<MAX_ALLPASS;i++) { AllPass &a=allpass[i]; int size_limit=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread)); for (int j=0;j<p_frames;j++) { if (a.pos>=size_limit) a.pos=0; float aux=a.buffer[a.pos]; a.buffer[a.pos]=undenormalise(allpass_feedback*aux+p_dst[j]); p_dst[j]=aux-allpass_feedback*a.buffer[a.pos]; a.pos++; } } static const float wet_scale=0.6; for (int i=0;i<p_frames;i++) { p_dst[i]=p_dst[i]*params.wet*wet_scale+p_src[i]*params.dry; } }
void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { const float *src = (const float *)p_src_frames; float *dst = (float *)p_dst_frames; //float lpf_c=expf(-2.0*Math_PI*keep_hf_hz.get()/(mix_rate*(float)OVERSAMPLE)); float lpf_c = expf(-2.0 * Math_PI * base->keep_hf_hz / (AudioServer::get_singleton()->get_mix_rate())); float lpf_ic = 1.0 - lpf_c; float drive_f = base->drive; float pregain_f = Math::db2linear(base->pre_gain); float postgain_f = Math::db2linear(base->post_gain); float atan_mult = pow(10, drive_f * drive_f * 3.0) - 1.0 + 0.001; float atan_div = 1.0 / (atanf(atan_mult) * (1.0 + drive_f * 8)); float lofi_mult = powf(2.0, 2.0 + (1.0 - drive_f) * 14); //goes from 16 to 2 bits for (int i = 0; i < p_frame_count * 2; i++) { float out = undenormalise(src[i] * lpf_ic + lpf_c * h[i & 1]); h[i & 1] = out; float a = out; float ha = src[i] - out; //high freqs a *= pregain_f; switch (base->mode) { case AudioEffectDistortion::MODE_CLIP: { a = powf(a, 1.0001 - drive_f); if (a > 1.0) a = 1.0; else if (a < (-1.0)) a = -1.0; } break; case AudioEffectDistortion::MODE_ATAN: { a = atanf(a * atan_mult) * atan_div; } break; case AudioEffectDistortion::MODE_LOFI: { a = floorf(a * lofi_mult + 0.5) / lofi_mult; } break; case AudioEffectDistortion::MODE_OVERDRIVE: { const double x = a * 0.686306; const double z = 1 + exp(sqrt(fabs(x)) * -0.75); a = (expf(x) - expf(-x * z)) / (expf(x) + expf(-x)); } break; case AudioEffectDistortion::MODE_WAVESHAPE: { float x = a; float k = 2 * drive_f / (1.00001 - drive_f); a = (1.0 + k) * x / (1.0 + k * fabsf(x)); } break; } dst[i] = a * postgain_f + ha; } }
void Filter::prepare_coefficients(Coeffs *p_coeffs) { double final_cutoff=(cutoff>=(sampling_rate/2))?(sampling_rate/2-1):cutoff; if (final_cutoff<20) //avoid crapness final_cutoff=20; //i dont allow less than this double omega=2.0*M_PI*final_cutoff/sampling_rate; double sin_v=sin(omega); double cos_v=cos(omega); float Q=resonance; if (Q<=0.0) { Q=0.0001; } if (mode==BANDPASS) Q*=2.0; if (stages>1) { Q=(Q>1.0 ? pow(Q,1.0/stages) : Q); } double alpha = sin_v/(2*Q); double a0 = 1.0 + alpha; switch (mode) { case LOWPASS: { p_coeffs->b0= (1.0 - cos_v)/2.0 ; p_coeffs->b1= 1.0 - cos_v ; p_coeffs->b2= (1.0 - cos_v)/2.0 ; p_coeffs->a1= -2.0*cos_v ; p_coeffs->a2= 1.0 - alpha ; } break; case HIGHPASS: { p_coeffs->b0 = (1.0 + cos_v)/2.0; p_coeffs->b1 = -(1.0 + cos_v); p_coeffs->b2 = (1.0 + cos_v)/2.0; p_coeffs->a1 = -2.0*cos_v; p_coeffs->a2 = 1.0 - alpha; } break; case BANDPASS: { p_coeffs->b0 = alpha*sqrt(Q+1); p_coeffs->b1 = 0.0 ; p_coeffs->b2 = -alpha*sqrt(Q+1); p_coeffs->a1 = -2.0*cos_v; p_coeffs->a2 = 1.0 - alpha; } break; case NOTCH: { p_coeffs->b0 = 1.0; p_coeffs->b1 = -2.0*cos_v; p_coeffs->b2 = 1.0; p_coeffs->a1 = -2.0*cos_v; p_coeffs->a2 = 1.0 - alpha; } break; }; p_coeffs->b0/=a0; p_coeffs->b1/=a0; p_coeffs->b2/=a0; p_coeffs->a1/=0.0-a0; p_coeffs->a2/=0.0-a0; //undenormalise p_coeffs->b0=undenormalise(p_coeffs->b0); p_coeffs->b1=undenormalise(p_coeffs->b1); p_coeffs->b2=undenormalise(p_coeffs->b2); p_coeffs->a1=undenormalise(p_coeffs->a1); p_coeffs->a2=undenormalise(p_coeffs->a2); }