#include #include #include "const.h" #include "RenderAPI.h" #include "FreqResponse.h" #include "IIRFilter.h" #include "FIRFilter.h" #include "windowsfunc.h" enum pulse_type { pulse_orginal, //ԭʼµ¼ÈëµÄÂö³å pulse_invert, //Ïà·´µÄÏàλÓë·ù¶È pulse_eq1, //eqµ÷ÕûµÄÂö³å pulse_eq2, pulse_eq3, pulse_eq4, pulse_eq5, pulse_eq6, pulse_eq7, pulse_eq8, pulse_out, //×îÖÕÉú³ÉµÄÂö³å pulse_count, }; typedef struct { //ÄÚ²¿ÁÙʱÊý¾Ý double linear_freq[KERNEL_HALF_FFT]; double gain[KERNEL_HALF_FFT]; double phase[KERNEL_HALF_FFT]; pulse_t hn_list[pulse_count]; }FiltersRender; void* FiltersRenderInit() { FiltersRender* render = new FiltersRender; FreqResponse response; memset(render, 0 , sizeof(FiltersRender)); //²úÉúÏßÐÔÆµÂÊ response.linearspace(0, KERNEL_SAMPLE_RATE / 2, render->linear_freq, KERNEL_HALF_FFT); return render; } void FilterRenderFree(void* handle) { FiltersRender* render = (FiltersRender*)handle; if(render) delete render; } static void FilterReset(pulse_t* p) { memset(p, 0, sizeof(pulse_t)); } int FIRDrawFreqzData(void* handle, double coeffs[], int tap, int fs , double f[], double gain[], double phase[], int num) { FreqResponse response; FiltersRender* render = (FiltersRender*)handle; if (render == 0) return ret_param_error; //µ¼ÈëµÄÊÇ·ù¶ÈÐÅÏ¢. if (f[tap - 1] < KERNEL_SAMPLE_RATE / 2 && f[tap - 1] > 10000) { response.deg2rad(phase, tap); //ÏßÐÔÄÚ²å֮ǰ±ØÐë¶ÔÏàλ½â²øÈÆ response.unwrap_phase(phase, tap, render->phase); //°´ÕÕ²úÉúµÄÏßÐÔÆµÂÊ×ö³éÈ¡gainºÍpahse. response.extra(f, gain, render->phase, tap, render->linear_freq , render->hn_list[pulse_orginal].gain, render->hn_list[pulse_orginal].phase, KERNEL_HALF_FFT); //ÄÚ²åºóÏàλת»»µ½-pi~piÇø¼ä for (int i =0; i < KERNEL_HALF_FFT; i++) { render->hn_list[pulse_orginal].phase[i] = response.wrap_phase(render->hn_list[pulse_orginal].phase[i]); } render->hn_list[pulse_orginal].enable = true; FilterReset(&render->hn_list[pulse_invert]); return num; } //·ñÔòµ¼ÈëµÄÊÇϵÊýÎļþ. //Ìî³äƵÂÊÐÅÏ¢. response.logspace(10, 20000, f, num); //ϵÊýΪ¿Õ //if (coeffs[0] == 0 && coeffs[1] == 0) { // return ret_param_error; //} int n = response.freqz(coeffs, tap, KERNEL_SAMPLE_NUM, KERNEL_SAMPLE_RATE, render->linear_freq , render->hn_list[pulse_orginal].gain, render->hn_list[pulse_orginal].phase); //n==4097 //³éÈ¡ÎÞÐè½â²øÈÆ. response.extra(render->linear_freq, render->hn_list[pulse_orginal].gain, render->hn_list[pulse_orginal].phase , n, f, gain, phase, num); response.rad2deg(phase, num); render->hn_list[pulse_orginal].enable = true; FilterReset(&render->hn_list[pulse_invert]); return ret_success; } int FIRAutoMagCalibration(void* handle, double f[], double gain[] , double start_freq, double end_freq, int smooth_type, int num) { FreqResponse response; FiltersRender* render = (FiltersRender*)handle; const double oct[] = {1./3, 1./6,1./10, 0}; if (render == 0) return ret_param_error; for (int i = 0; i < KERNEL_HALF_FFT; i++) { if (render->linear_freq[i] >= start_freq && render->linear_freq[i] <= end_freq) { render->gain[i] = -render->hn_list[pulse_orginal].gain[i]; } else { render->gain[i] = 0; //²»¸Ä±äÔöÒæ. } } response.sw_smooth(oct[smooth_type], start_freq, end_freq, render->linear_freq , render->gain, render->hn_list[pulse_invert].gain, KERNEL_HALF_FFT); render->hn_list[pulse_invert].enable = true; response.mulimpulse(render->hn_list, pulse_count); //Ìî³äƵÂÊÐÅÏ¢. response.logspace(10, 20000, f, num); response.extra(render->linear_freq, render->hn_list[pulse_out].gain, render->hn_list[pulse_out].phase, KERNEL_HALF_FFT , f, gain, NULL, num); return 0; } int FIRAutoPhaseCalibration(void* handle, double f[], double phase[] , double start_freq, double end_freq, int smooth_type, int num) { FreqResponse response; FiltersRender* render = (FiltersRender*)handle; const double oct[] = { 1. / 3, 1. / 6,1. / 10, 0 }; if (render == 0) return ret_param_error; for (int i = 0; i < KERNEL_HALF_FFT; i++) { if (render->linear_freq[i] >= start_freq && render->linear_freq[i] <= end_freq) { //-pi~piÇø¼ä. render->phase[i] = -render->hn_list[pulse_orginal].phase[i]; } else { render->phase[i] = 0; //²»¸Ä±äÏàλ. } } response.sw_smooth(oct[smooth_type], start_freq, end_freq, render->linear_freq , render->phase, render->hn_list[pulse_invert].phase, KERNEL_HALF_FFT); render->hn_list[pulse_invert].enable = true; response.mulimpulse(render->hn_list, pulse_count); //Ìî³äƵÂÊÐÅÏ¢. response.logspace(10, 20000, f, num); response.extra(render->linear_freq, render->hn_list[pulse_out].gain, render->hn_list[pulse_out].phase, KERNEL_HALF_FFT , f, NULL, phase, num); response.rad2deg(phase ,num); return 0; } int FIRAdjustFilter(void* handle, int nsection, int bypass, int filter_type , int freq, double Q, double g, double f[], double gain[], double phase[], int num) { FreqResponse response; FiltersRender* render = (FiltersRender*)handle; //param check. if (render == 0 || nsection > 7 || nsection < 0) return ret_param_error; if (freq < 20 || freq > 20000) return ret_param_error; if (Q < 0.02 || Q > 50) return ret_param_error; if (g < -24 || g > 18) return ret_param_error; double sos[6]; switch (filter_type) { case FIRFilterType::HIGHPASS: IIRFilter().eq(IIRBANDType::highpass, freq, g, Q, KERNEL_SAMPLE_RATE, &sos); break; case FIRFilterType::LOWPASS: IIRFilter().eq(IIRBANDType::lowpass, freq, g, Q, KERNEL_SAMPLE_RATE, &sos); break; case FIRFilterType::EQ: IIRFilter().eq(IIRBANDType::peaking_eq, freq, g, Q, KERNEL_SAMPLE_RATE, &sos); break; default: return ret_param_error; } nsection += pulse_eq1; response.freqz(&sos, 1, KERNEL_HALF_FFT, KERNEL_SAMPLE_RATE, render->linear_freq, render->hn_list[nsection].gain); render->hn_list[nsection].enable = bypass==0?true:false; response.mulimpulse(render->hn_list, pulse_count); //Ìî³äƵÂÊÐÅÏ¢. response.logspace(10, 20000, f, num); response.extra(render->linear_freq, render->hn_list[pulse_out].gain, render->hn_list[pulse_out].phase, KERNEL_HALF_FFT , f, gain, phase, num); response.rad2deg(phase, num); return 0; } int FIRGetCoeffs(void* handle, double coffefs[], int windowType, double delay_ms, int tap) { FiltersRender* render = (FiltersRender*)handle; FreqResponse response; if (render == 0 || tap > 4096) return ret_param_error; double wn[4096]; switch (windowType) { case FIRWindowType::Blackman: Windows().BlackManWin(wn, tap); break; case FIRWindowType::Hamming: Windows().HammingWin(wn, tap); break; case FIRWindowType::Hanning: Windows().HannWin(wn, tap); break; case FIRWindowType::Kaiser: Windows().KaiserWin(wn, tap); break; case FIRWindowType::Rectangle: Windows().RectangleWin(wn, tap); break; case FIRWindowType::Triangle: Windows().TriangularWin(wn, tap); break; default: return ret_param_error; } //ifft->»ùÓÚÄÜÁ¿ÖÐÐĽØÈ¡->¼Ó´° response.mulimpulse(render->hn_list, pulse_count , pulse_invert); response.unwrap_phase(render->hn_list[pulse_type::pulse_out].phase, KERNEL_HALF_FFT, render->phase); response.impulse_response(render->linear_freq, render->hn_list[pulse_type::pulse_out].gain, render->phase, KERNEL_HALF_FFT , coffefs, tap , wn, delay_ms, true); return 0; } void FilterRenderReset(void* handle) { FiltersRender* render = (FiltersRender*)handle; //param check. if (render) { memset(render->hn_list, 0, sizeof(pulse_t) * pulse_count); } }