⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filter.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
字号:
/*    TiMidity -- Experimental MIDI to WAVE converter    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   filter.c: written by Vincent Pagel ( pagel@loria.fr )     implements fir antialiasing filter : should help when setting sample   rates as low as 8Khz.   April 95      - first draft   22/5/95      - modify "filter" so that it simulate leading and trailing 0 in the buffer   */#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include "config.h"#include "common.h"#include "ctrlmode.h"#include "instrum.h"#include "filter.h"/*  bessel  function   */static float ino(float x){    float y, de, e, sde;    int i;        y = x / 2;    e = 1.0;    de = 1.0;    i = 1;    do {	de = de * y / (float) i;	sde = de * de;	e += sde;    } while (!( (e * 1.0e-08 - sde > 0) || (i++ > 25) ));    return(e);}	/* Kaiser Window (symetric) */static void kaiser(float *w,int n,float beta){    float xind, xi;    int i;        xind = (float)((2*n - 1) * (2*n - 1));    for (i =0; i<n ; i++) 	{	    xi = (float)(i + 0.5);	    w[i] = ino((float)(beta * sqrt((double)(1. - 4 * xi * xi / xind))))		/ ino((float)beta);	}}/* * fir coef in g, cuttoff frequency in fc */static void designfir(float *g , float fc){    int i;    float xi, omega, att, beta ;    float w[ORDER2];        for (i =0; i < ORDER2 ;i++) 	{	    xi = (float) (i + 0.5);	    omega = (float)(PI * xi);	    g[i] = (float)(sin( (double) omega * fc) / omega);	}        att = 40.; /* attenuation  in  db */    beta = (float) (exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 	* (att - 20.96));    kaiser( w, ORDER2, beta);        /* Matrix product */    for (i =0; i < ORDER2 ; i++)	g[i] = g[i] * w[i];}/* * FIR filtering -> apply the filter given by coef[] to the data buffer * Note that we simulate leading and trailing 0 at the border of the  * data buffer */static void filter(sample_t *result,sample_t *data, int32 length,float coef[]){    int32 sample,i,sample_window;    int16 peak = 0;    float sum;    /* Simulate leading 0 at the begining of the buffer */     for (sample = 0; sample < ORDER2 ; sample++ )	{	    sum = 0.0;	    sample_window= sample - ORDER2;	   	    for (i = 0; i < ORDER ;i++) 		sum += (float)(coef[i] *		    ((sample_window<0)? 0.0 : data[sample_window++])) ;	    	    /* Saturation ??? */	    if (sum> 32767.) { sum=32767.; peak++; }	    if (sum< -32768.) { sum=-32768; peak++; }	    result[sample] = (sample_t) sum;	}    /* The core of the buffer  */    for (sample = ORDER2; sample < length - ORDER + ORDER2 ; sample++ )	{	    sum = 0.0;	    sample_window= sample - ORDER2;	    for (i = 0; i < ORDER ;i++) 		sum += data[sample_window++] * coef[i];	    	    /* Saturation ??? */	    if (sum> 32767.) { sum=32767.; peak++; }	    if (sum< -32768.) { sum=-32768; peak++; }	    result[sample] = (sample_t) sum;	}        /* Simulate 0 at the end of the buffer */    for (sample = length - ORDER + ORDER2; sample < length ; sample++ )	{	    sum = 0.0;	    sample_window= sample - ORDER2;	    	    for (i = 0; i < ORDER ;i++) 		sum += (float)(coef[i] *		    ((sample_window>=length)? 0.0 : data[sample_window++])) ;	    	    /* Saturation ??? */	    if (sum> 32767.) { sum=32767.; peak++; }	    if (sum< -32768.) { sum=-32768; peak++; }	    result[sample] = (sample_t) sum;	}    if (peak)	ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 		  "Saturation %2.3f %%.", 100.0*peak/ (float) length);}/***********************************************************************//* Prevent aliasing by filtering any freq above the output_rate        *//*                                                                     *//* I don't worry about looping point -> they will remain soft if they  *//* were already                                                        *//***********************************************************************/void antialiasing(Sample *sp, int32 output_rate ){    sample_t *temp;    int i;    float fir_symetric[ORDER];    float fir_coef[ORDER2];    float freq_cut;  /* cutoff frequency [0..1.0] FREQ_CUT/SAMP_FREQ*/     ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: Fsample=%iKHz",	      sp->sample_rate);     /* No oversampling  */    if (output_rate>=sp->sample_rate)	return;        freq_cut= (float) output_rate / (float) sp->sample_rate;    ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: cutoff=%f%%",	      freq_cut*100.);    designfir(fir_coef,freq_cut);        /* Make the filter symetric */    for (i = 0 ; i<ORDER2 ;i++) 	fir_symetric[ORDER-1 - i] = fir_symetric[i] = fir_coef[ORDER2-1 - i];        /* We apply the filter we have designed on a copy of the patch */    temp = safe_malloc(sp->data_length);    memcpy(temp,sp->data,sp->data_length);        filter(sp->data,temp,sp->data_length/sizeof(sample_t),fir_symetric);        free(temp);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -