ÿþ#include <math.h> #include <assert.h> #include <stdlib.h> #include "delay_mono.h" #define M_PI 3.14159265358979323f enum { High_Ratio_dmn, HPF_dmn, LPF_dmn }FilterType; //FILE *fp; int hlpf_coeff(float *c, float fs, float freq, int type) { double K = tan(M_PI * freq / fs); double Q = sqrt(2)/2.0; double norm; float b[3], a[3]; if (NULL == c) return -1; switch (type) { case High_Ratio_dmn: a[1] = -expf(-2.0 * M_PI * (freq / fs)); b[0] = 1.0 + a[1]; b[1] = b[2] = a[2] = 0; break; case HPF_dmn: norm = 1 / (1 + K / Q + K * K); b[0] = 1 * norm; b[1] = -2 * b[0]; b[2] = b[0]; a[1] = 2 * (K * K - 1) * norm; a[2] = (1 - K / Q + K * K) * norm; break; case LPF_dmn: norm = 1 / (1 + K / Q + K * K); b[0] = K * K * norm; b[1] = 2 * b[0]; b[2] = b[0]; a[1] = 2 * (K * K - 1) * norm; a[2] = (1 - K / Q + K * K) * norm; break; default: break; } c[0] = b[0]; c[1] = b[1]; c[2] = b[2]; c[3] = a[1]; c[4] = a[2]; return 0; } int hlpf_dealwith(float* data, float *s, float *c, int len) { if((NULL == data) || (NULL == s) || (NULL == c)) return -1; float x1 = s[0], x2 = s[1], y1 = s[2], y2 = s[3]; for (int i = 0; i < len; i++) { float x = data[i]; float y = ((c[0] * data[i]) + (c[1] * x1) + (c[2] * x2)) - (c[3] * y1) - (c[4] * y2); x2 = x1; y2 = y1; x1 = x; y1 = y; data[i] = y; } s[0] = x1; s[1] = x2; s[2] = y1; s[3] = y2; return 0; } int delay_mono_set_len(Delay_mono *d, int len) { if(len > d->size - 1) len = d->size - 1; if(len < 0) len = 0; d->tail = d->head - len; if(d->tail < 0) d->tail += d->size; return len; } Delay_mono *delay_mono_new(int channels, int frame_size, Delay_mono_param *p) { int i; Delay_mono *d = (Delay_mono *)malloc(sizeof(*d)); assert(d); d->channels = channels; d->frame_size = frame_size; d->max_delay = 2000; //ms d->size = d->max_delay * p->sample_rate / 1000.0f + 1; d->head = 0; d->tail = 0; d->buf = (float **)malloc(channels * sizeof(*d->buf)); assert(d->buf); for (i = 0; i < channels; i++) { d->buf[i] = (float *)calloc(d->size, sizeof(*d->buf[i])); assert(d->buf[i]); } d->s = (float **)malloc(channels * sizeof(*d->s)); assert(d->s); for (i = 0; i < channels; i++) { d->s[i] = (float *)calloc(12, sizeof(*d->s[i])); //0~3:high_ratio status, 4~7:hpf, 8~11:lpf assert(d->s[i]); } d->tmp = (float *)calloc(d->frame_size, sizeof(*d->tmp)); d->size = p->set_delay * p->sample_rate / 1000.0f + 1; d->param.sample_rate = p->sample_rate; d->param.wet_dry = p->wet_dry; d->param.set_delay = p->set_delay; d->param.feed_back = p->feed_back / 100.0f; d->param.high_ratio = p->high_ratio; d->param.hpf = p->hpf; d->param.lpf = p->lpf; delay_mono_set_len(d, d->size); //fp = fopen("pug.txt", "w"); float hi_rat_freq = 1000.0f * powf(20000.0f / 1000.0f, (d->param.high_ratio - 0.1f) / 0.9f); hlpf_coeff(d->chirt, d->param.sample_rate, hi_rat_freq, High_Ratio_dmn); hlpf_coeff(d->chpf, d->param.sample_rate, d->param.hpf, HPF_dmn); hlpf_coeff(d->clpf, d->param.sample_rate, d->param.lpf, LPF_dmn); //for (i = 0; i < 5; i++) { //fprintf(fp, "%f,\t %f,\t %f\n", d->chirt[i], d->chpf[i], d->clpf[i]); //} // fprintf(fp, "coeffs %d: %f %f %f %f %f %f\n", High_Ratio_dmn,c[0],c[1],c[2],c[3],c[4]); //fclose(fp); return d; } void param_setting(Delay_mono *d, Delay_mono_param *p) { if(d->param.sample_rate != p->sample_rate) d->param.sample_rate = p->sample_rate; else if(d->param.wet_dry != p->wet_dry) d->param.wet_dry = p->wet_dry; else if(d->param.set_delay != p->set_delay) { d->param.set_delay = p->set_delay; d->size = p->set_delay * p->sample_rate / 1000.0f + 1; delay_mono_set_len(d, d->size); } else if(d->param.feed_back != p->feed_back / 100.0f) d->param.feed_back = p->feed_back / 100.0f; else if(d->param.high_ratio != p->high_ratio) { d->param.high_ratio = p->high_ratio; float hi_rat_freq = 1000.0f * powf(20000.0f / 1000.0f, (d->param.high_ratio - 0.1f) / 0.9f); hlpf_coeff(d->chirt, d->param.sample_rate, hi_rat_freq, High_Ratio_dmn); } else if(d->param.hpf != p->hpf) { d->param.hpf = p->hpf; hlpf_coeff(d->chpf, d->param.sample_rate, d->param.hpf, HPF_dmn); } else if(d->param.lpf != p->lpf) { d->param.lpf = p->lpf; hlpf_coeff(d->clpf, d->param.sample_rate, d->param.lpf, LPF_dmn); } else return; } void delay_mono_process(Delay_mono *d, float **data, Delay_mono_param *param) { int i,j; int ch = d->channels; int n = d->frame_size; int L = d->size; int h, t; param_setting(d, param); for(i = 0; i < ch; i++) { hlpf_dealwith(data[i], &d->s[i][4], d->chpf, n); hlpf_dealwith(data[i], &d->s[i][8], d->clpf, n); } for(i = 0; i < ch; i++) { h = d->head; t = d->tail; for(j = 0; j < n; j++) { d->tmp[j] = d->buf[i][t]; d->buf[i][h] = data[i][j] + d->buf[i][t] * d->param.feed_back; h = (h + 1) % L; t = (t + 1) % L; } hlpf_dealwith(d->tmp, &d->s[i][0], d->chirt, n); h = d->head; t = d->tail; for(j = 0; j < n; j++) { data[i][j] = (data[i][j] * (100 - d->param.wet_dry) + d->tmp[j] * d->param.wet_dry) / 100.0f; h = (h + 1) % L; t = (t + 1) % L; } d->head = h; d->tail = t; } } void delay_mono_delete(Delay_mono *d) { int i; int ch = d->channels; free(d->tmp); for(i = 0; i < ch; i++) { free(d->s[i]); free(d->buf[i]); } free(d->s); free(d->buf); free(d); }