FIR 滤波器FAQ (基本知识问答) 1.1 什么是FIR滤波器? FIR 滤波器是在数字信号处理(DSP)中经常使用的两种基本的滤波器之一,另一个为IIR滤波器. 1.2 FIR代表什么? FIR是有限冲激响应(Finite Impulse Response)的简称. 1.3 FIR(有限冲激响应)中的有限该如何理解? 冲激响应是有限的意味着在滤波器中没有发反馈. 1.4 FIR 怎么发音? 有些人直接读字母音 F-I-R; 也有人发做fir的音[:], fir是冷杉树. 1.5 FIR 滤波器外有什么其他选择? DSP滤波器还有一类: IIR(无限冲激响应,Infinite Impulse Response).IIR滤波器使用反馈,因此当信号输入后,输出是根据算法循环的. 1.6 FIR滤波器与IIR滤波器比较? 每一种都有优缺点.但总得来说, FIR滤波器的优点远大于缺点,因此在实际运用中,FIR滤波器比IIR滤波器使用的比较多. 1.6.1 相对于IIR滤波器, FIR滤波器有什么优点? 相较于IIR滤波器, FIR滤波器有以下的优点: * 可以很容易地设计线性相位的滤波器. 线性相位滤波器延时输入信号,却并不扭曲其相位. * 实现简单. 在大多数DSP处理器, 只需要对一个指令积习循环就可以完成FIR计算. * 适合于多采样率转换,它包括抽取(降低采样率), 插值(增加采样率)操作. 无论是抽取或者插值, 运用FIR滤波器可以省去一些计算, 提高计算效率. 相反,如果使用IIR滤波器,每个输出都要逐一计算,不能省略,即使输出要丢弃. * 具有理想的数字特性. 在实际中,所有的DSP滤波器必须用有限精度(有限bit数目)实现,而在IIR滤波器中使用有限精度会产生很大的问题,由于采用的是反馈电路,因此IIR通常用非常少的bit实现,设计者就能解决更少的与非理想算术有关的问题。 * 可以用小数实现. 不像IIR滤波器,FIR滤波器通常可能用小于1的系数来实现。(如果需要,FIR滤波器的总的增益可以在输出调整)。当使用定点DSP的时候,这也是一个考虑因素,它能使得实现更加地简单。 1.6.2 相较于IIR滤波器, FIR滤波器的缺点是什么? 相比较于IIR滤波器, 有时FIR滤波器为了得到一个给定的滤波响应特性,需要花费更多的存储器或者计算. 当然,用FIR滤波器去实现某些响应也是不实际的. 1.7 在描述FIR滤波器的时候,都要提到什么术语? * 冲激响应 - FIR滤波器的冲激响应实际上是FIR的系数. * 抽头(Tap) - FIR的抽头是系数或者延时对.FIR抽头的个数(通常用N来表示)意味着:1)实现滤波器所需要的存储空间, 2) 需要计算的数目, 3) 滤波器能滤掉的数量, 实际上,越多的抽头意味着有更多的阻带衰减, 更少的波纹,更窄的滤波等等. * 乘累加 (MAC) - 在FIR方面考虑,MAC是指把延时的数据采样与相应的系数相乘,然后累加结果。通常,FIR每一个抽头都需要一个MAC。大多数DSP微处理器实现MAC操作都是单指令周期。 * 跃迁带(Transition Band) -在通带和阻带边沿之间的频带。跃迁带越窄,需要更多的抽头去实现滤波器。也有说,小的跃迁带就是一个sharp滤波器。 * 延时线- 一组存储器单元,实现在FIR计算中的Z^-1延时。 * 环形缓存 - 一个特殊的缓存,是首尾相连的。通常由DSP微处理器实现。 2.1 线性相位 2.1.1 FIR滤波器和线性相位之间有什么关系? 大多数的FIR滤波器是线性相位滤波器. 当需要设计线性相位滤波器时, 通常使用FIR滤波器. 2.1.2 什么是线性相位滤波器? 线性相位是指滤波器的相位响应是频率的线性函数(在+/-180度)。因此滤波器的延时后,所有的频率相位相同。因而滤波器不会产生相位和延迟扭曲。在某些领域,比如数字解调器,没有相位或者延迟扭曲是FIR滤波器相对于其他IIR和模拟滤波器的一个关键优点 2.1.3 线性滤波器的条件是什么? FIR滤波器经常被设计成为线性相位的,当然不是必须要这么做。如果滤波器的系数是关于中心系数对称的,也就是说第一个系数和最后一个系数相同,第二个系数和倒数第二个相同,那么FIR滤波器就是线性的。有奇数个系数的FIR滤波器,中心单独的系数没有对应的。 2.1.4 什么是线性相位FIR滤波器的延时? 非常简单的公式: 给定FIR滤波器有N个抽头,那么延时是(N - 1) / (2 * Fs), 这里Fs是采样频率. 比如, 21抽头的线性相位滤波器运行在1kHz, 那么延时就是(21 - 1) / (2 * 1 kHz)=10 微秒. 2.1.4 除了线性相位,还可以选择什么? 当然是非线性的了。实际上,最流行的选择是最小相位滤波器。最小相位滤波器,也叫最小延时滤波器,比线性相位滤波器具有更少的延时,当两者的幅度响应相同时以非线性相位特性。低通滤波器在它的冲击响应中心有最大的系数。而最小相位滤波器的最大系数在开始部分。 2.2 频率响应 2.2.1 什么是FIR滤波器的Z变换r? 对于N抽头的滤波器, 系数为h(k), 那么输出由: y(n)=h(0)x(n) + h(1)x(n-1) + h(2)x(n-2) + ... h(N-1)x(n-N-1), 滤波器的z变换就是: H(z)=h(0)z-0 + h(1)z-1 + h(2)z-2 + ... h(N-1)z-(N-1) , or 2.2.2 FIR滤波器的频率响应公式是什么? H(z)中的变量z为连续的复数变量,可以描述为 z=r·ejw,这里r是幅度,w是z的角度。如果令r=1,H(z)就变成了滤波器频率响应H(jw)。这也就意味着替代z为ejw,得到了滤波器频率响应H(w)。 H(jw)=h(0)e-j0w + h(1)e-j1w + h(2)e-j2w + ... h(N-1)e-j(N-1)w , or 使用欧拉公式, e-ja=cos(a) - jsin(a), 我们可以把H(jw)写成矩形表示: H(jw)=h(0)[cos(0w) - jsin(0w)] + h(1)[cos(1w) - jsin(1w)] + ... h(N-1)[cos((N-1)w) - jsin((N-1)w)] , or 2.2.3 能用离散傅立叶变换(DFT)来计算FIR的频率响应么? 可以。对于N抽头的FIR,可以得到N evenly-spaced points of the frequency response by doing a DFT on the filter coefficients.但是,为了得到任意频率的频率响应,需要使用上边的公式。 2.2.4 FIR滤波器的DC增益指的是什么? DC(0 Hz)输入信号包含每个采样都为1.0。通过延时线后,输出是所有系数的和。因而,在DC处滤波器的增益就是所有系数之和。 可以通过上边的公式进行验证。问我们设w为0, cos项就一直为1,而sin项则一直为0。因此频率响应就变成了: 2.2.5 如何调整FIR滤波器的增益? 简单地在系数上乘上因子. 2.3 数字性质 2.3.1 FIR滤波器是固有稳定的? 是的,因为没有反馈,任何有限的输入产生有限的输出。 2.3.2 什么使FIR滤波器的数字性质变好? 缺少反馈是关键。在计算机中实现FIR滤波器时,每个计算都产生数字错误。由于FIR滤波器没有反馈,因此不能够记住以前的错误。相反,IIR滤波器的反馈可能导致错误的积累。这个实际的影响就是,可以用更少的bit去实现与IIR滤波器相同精度的滤波器。比如,FIR滤波器通常用16位来实现的话,IIR滤波器就通常需要32位,或者更多。 2.4 为什么通常在多采样率系统中采用FIR滤波器而不采用IIR滤波器? 因为只有一小部分的计算需要用减采样或者插值滤波器来实现。 由于FIR滤波器不使用反馈,因而只有那些实际需要使用的输出才需要计算。比如,在减采样的时候(N个输出中只有一个有效),那么其他的N-1输出就不会进行计算。类似的,对于插值滤波器(在采样点中插入0来提高采样率),你不必实际地用FIR滤波器乘以系数,求和得到,你只需要忽略和这些值有关的乘加(因为它们不会改变结果)。 相反,因为IIR滤波器使用反馈,每个输入都必须使用,每个输入必须计算,因为所有的输入和输出对滤波器的反馈都有影响。 2.5 有哪些特殊的FIR滤波器? Aside from "regular" and "extra crispy" there are: * 矩形 -矩形 FIR 滤波器是每个系数都是1.0的简单的滤波器。因而对于N个抽头的矩形滤波器,它的输出仅仅是过去N个采样之和。由于矩形FIR只能实现加法,因此当乘法器实现比较昂贵时,在硬件实现中会考虑。 * 希尔伯特变换(Hilbert Transformer) - 希尔伯特变换是把信号相移90度。它们经常被用在给定实数部分,产生虚数部分。 * 差分(Differentiator) -差分器的幅度响应是频率的线性函数。现在已经不流行了,但是以前曾经在FM解调器上使用过。 * Lth-Band - 也叫做“Nyquist"滤波器,这些滤波器是在多速率应用中特殊的一类滤波器。主要的卖点是,每L个系数有一个为0,那么就将减少乘累加操作的实现(著名的半带滤波器就是这一种)。 * Raised-Cosine - 这是一种特殊类型的滤波器,有时会用在数字数据应用方面。(通带上的频率响应是被上移一个常数的cos形状)。 3.1 有哪些设计FIR滤波器的方法? 三种最流行的设计方法: - Parks-McClellan: Parks-McClellan 方法( MATLAB里用Remez)是设计FIR滤波器中可能是使用最光的.method (inaccurately called "Remez" by Matlab) is probably the most widely used FIR filter design method. It is an iteration algorithm that accepts filter specifications in terms of passband and stopband frequencies, passband ripple, and stopband attenuation. The fact that you can directly specify all the important filter parameters is what makes this method so popular. The PM method can design not only FIR "filters" but also FIR "differentiators" and FIR "Hilbert transformers".
- Windowing:. In the windowing method, an initial impulse response is derived by taking the Inverse Discrete Fourier Transform (IDFT) of the desired frequency response. Then, the impulse response is refined by applying a data window to it.
- Direct Calculation: The impulse responses of certain types of FIR filters (e.g. Raised Cosine and Windowed Sinc) can be calculated directly from formulas.
3.2 如何实际地设计FIR滤波器? 当然是用FIR设计程序呀. 虽然可以使用手工亲自的方法进行设计滤波器,但是使用FIR滤波器程序比较简单.
Part 4: Implementation 4.1 实现FIR滤波器基本的方法是什么? FIR滤波器的结构上包含两个东西:一个是采样点延迟线,一个是系数. 可以由以下方法实现FIR滤波器: 1. 把输入的采样点放入到延迟线中. 2. 把延迟线中的数与相应的系数相乘并累加. 3. 移位, 使下一个输入采样能进入延迟线. 4.2 用C语言如何实现FIR滤波器? 为了展示众多的方法和技巧,这里提供用C语言实现的FIR滤波器算法。
包括以下功能模块:
1. fir_basic: 实现基本的FIR滤波器 2. fir_circular: 说明环行buffer是如何实现FIR的。 3. fir_shuffle: 一些TI的处理器上使用的shuffle down技巧 4. fir_split: 把FIR滤波器展开为两块,避免使用环行缓存。 5. fir_double_z: 使用双精度的延迟线,使可以使用一个flat buffer。 6. fir_double_h: 使用双精度的系数,使可以使用一个flat buffer。 4.3 用汇编如何实现FIR滤波器? FIR滤波器的汇编算法是跟处理器对应的,但是大多数普通的系统会使用一个DSP处理器提供的环行缓存。 1. 配置环行缓存。加载系数和延迟线指针。然后对每个采样点执行以下操作: 2. Store the incoming data in the delay line; increment the delay-line pointer.Digital 3. Clear the multiplier-accumulator. 4. Loop over all coefficients/delays; accumulate the values obtained by multiplying the coefficients by the delayed samples. 5. Round or truncate the result as the FIR output. Alternatively, a "shuffle down" method is used in Texas Instruments' older fixed-point processors to implement circular buffers. The processor literally moves each sample delay values by one slot during each multiply-accumulate (via the "MACD" instruction). Each DSP microprocessor manufacturer provides example FIR assembly code in its data books or its application handbooks, so be sure to look at those before you "reinvent the circular buffer". 4.4 如何测试以及实现的FIR滤波器? Here are a few methods: - Impulse Test: A very simple and effective test is to put an impulse into it (which is just a "1" sample followed by at lest N - 1 zeroes.) You can also put in an "impulse train", with the "1" samples spaced at least N samples apart. If all the coefficients of the filter come out in the proper order, there is a good chance your filter is working correctly. (You might want to test with non-linear phase coefficients so you can see the order they come out.) We recommend you do this test whenever you write a new FIR filter routine.
- Step Test: Input N or more "1" samples. The output after N samples, should be the sum (DC gain) of the FIR filter.
- Sine Test: Input a sine wave at one or more frequencies and see if the output sine has the expected amplitude.
- Swept FM Test: From Eric Jacobsen: "My favorite test after an impulse train is to take two identical instances of the filter under test, use them as I and Q filters and put a complex FM linear sweep through them from DC to Fs/2. You can do an FFT on the result and see the complete frequency response of the filter, make sure the phase is nice and continuous everywhere, and match the response to what you'd expect from the coefficient set, the precision, etc."
4.5 在实现FIR滤波器的过程中有什么有用的技巧? FIR tricks center on two things 1) not calculating things that don't need to be calculated, and 2) "faking" circular buffers in software. 4.5.1 如何跳过不必要的计算? First, if your filter has zero-valued coefficients, you don't actually have to calculate those taps; you can leave them out. A common case of this is "half-band" filter, which have the property that every-other coefficient is zero. Second, if your filter is "symmetric" (linear phase), you can "pre-add" the samples which will be multiplied by the same coefficient value, prior to doing the multiply. Since this technique essentially trades an add for a multiply, it isn't really useful in DSP microprocessors which can do a multiply in a single instruction cycle. However, it is useful in ASIC implementations (in which addition is usually much less expensive than multiplication); also, some newer DSP processors now offer special hardware and instructions to make use of this trick. 4.5.2 How do I fake circular buffers in software? When hardware support for circular buffers isn't available, you have to "fake" them. Also, since ANSI C has no construct to describe circular buffers, most C compilers can't generate code to use them, even if the target processor has them. You can always implement a circular buffer by duplicating the logic of a circular buffer in software (and many have), but the overhead can be prohibitive; the circular-fake might take several instructions to implement, compared to just a single instruction to do the multiply-accumulate operation. Therefore you need to fake it. Here are several basic techniques to fake circular buffers: 1. Split the calculation: You can split any FIR calculation into its "pre-wrap" and "post-wrap" parts. By splitting the calculation into these two parts, you essentially can do the circular logic only once, rather than once per tap. (See fir_double_z in FirAlgs.c above.) 2. Duplicate the delay line: For a FIR with N taps, use a delay line of size 2N. Copy each sample to its proper location, as well as at location-plus-N. Therefore, the FIR calculation's MAC loop can be done on a flat buffer of N points, starting anywhere within the first set of N points. The second set of N delayed samples provides the "wrap around" comparable to a true circular buffer. (See fir_double_z in FirAlgs.c above.) 3. Duplicate the coefficients: This is similar to the above, except that the duplication occurs in terms of the coefficients, not the delay line. Compared to the previous method, this has a calculation advantage of not having to store each incoming sample twice, and it also has a memory advantage when the same coefficient set will be used on multiple delay lines. (See fir_double_h in FirAlgs.c above.) 4. Use block processing: In block processing, you use a delay line which is a multiple of the number of taps. You therefore only have to move the data once per block to implement the delay-line mechanism. When the block size becomes "large", the overhead of a moving the delay line once per block becomes negligible.
|