1 /* 2 * SpanDSP - a series of DSP components for telephony 3 * 4 * fir.h - General telephony FIR routines 5 * 6 * Written by Steve Underwood <steveu@coppice.org> 7 * 8 * Copyright (C) 2002 Steve Underwood 9 * 10 * All rights reserved. 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2, as 14 * published by the Free Software Foundation. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 */ 25 26 #if !defined(_FIR_H_) 27 #define _FIR_H_ 28 29 /* 30 Ideas for improvement: 31 32 1/ Rewrite filter for dual MAC inner loop. The issue here is handling 33 history sample offsets that are 16 bit aligned - the dual MAC needs 34 32 bit aligmnent. There are some good examples in libbfdsp. 35 36 2/ Use the hardware circular buffer facility tohalve memory usage. 37 38 3/ Consider using internal memory. 39 40 Using less memory might also improve speed as cache misses will be 41 reduced. A drop in MIPs and memory approaching 50% should be 42 possible. 43 44 The foreground and background filters currenlty use a total of 45 about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo 46 can. 47 */ 48 49 /* 50 * 16 bit integer FIR descriptor. This defines the working state for a single 51 * instance of an FIR filter using 16 bit integer coefficients. 52 */ 53 struct fir16_state_t { 54 int taps; 55 int curr_pos; 56 const int16_t *coeffs; 57 int16_t *history; 58 }; 59 60 /* 61 * 32 bit integer FIR descriptor. This defines the working state for a single 62 * instance of an FIR filter using 32 bit integer coefficients, and filtering 63 * 16 bit integer data. 64 */ 65 struct fir32_state_t { 66 int taps; 67 int curr_pos; 68 const int32_t *coeffs; 69 int16_t *history; 70 }; 71 72 /* 73 * Floating point FIR descriptor. This defines the working state for a single 74 * instance of an FIR filter using floating point coefficients and data. 75 */ 76 struct fir_float_state_t { 77 int taps; 78 int curr_pos; 79 const float *coeffs; 80 float *history; 81 }; 82 83 static inline const int16_t *fir16_create(struct fir16_state_t *fir, 84 const int16_t *coeffs, int taps) 85 { 86 fir->taps = taps; 87 fir->curr_pos = taps - 1; 88 fir->coeffs = coeffs; 89 fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL); 90 return fir->history; 91 } 92 93 static inline void fir16_flush(struct fir16_state_t *fir) 94 { 95 memset(fir->history, 0, fir->taps * sizeof(int16_t)); 96 } 97 98 static inline void fir16_free(struct fir16_state_t *fir) 99 { 100 kfree(fir->history); 101 } 102 103 static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample) 104 { 105 int32_t y; 106 int i; 107 int offset1; 108 int offset2; 109 110 fir->history[fir->curr_pos] = sample; 111 112 offset2 = fir->curr_pos; 113 offset1 = fir->taps - offset2; 114 y = 0; 115 for (i = fir->taps - 1; i >= offset1; i--) 116 y += fir->coeffs[i] * fir->history[i - offset1]; 117 for (; i >= 0; i--) 118 y += fir->coeffs[i] * fir->history[i + offset2]; 119 if (fir->curr_pos <= 0) 120 fir->curr_pos = fir->taps; 121 fir->curr_pos--; 122 return (int16_t) (y >> 15); 123 } 124 125 static inline const int16_t *fir32_create(struct fir32_state_t *fir, 126 const int32_t *coeffs, int taps) 127 { 128 fir->taps = taps; 129 fir->curr_pos = taps - 1; 130 fir->coeffs = coeffs; 131 fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL); 132 return fir->history; 133 } 134 135 static inline void fir32_flush(struct fir32_state_t *fir) 136 { 137 memset(fir->history, 0, fir->taps * sizeof(int16_t)); 138 } 139 140 static inline void fir32_free(struct fir32_state_t *fir) 141 { 142 kfree(fir->history); 143 } 144 145 static inline int16_t fir32(struct fir32_state_t *fir, int16_t sample) 146 { 147 int i; 148 int32_t y; 149 int offset1; 150 int offset2; 151 152 fir->history[fir->curr_pos] = sample; 153 offset2 = fir->curr_pos; 154 offset1 = fir->taps - offset2; 155 y = 0; 156 for (i = fir->taps - 1; i >= offset1; i--) 157 y += fir->coeffs[i] * fir->history[i - offset1]; 158 for (; i >= 0; i--) 159 y += fir->coeffs[i] * fir->history[i + offset2]; 160 if (fir->curr_pos <= 0) 161 fir->curr_pos = fir->taps; 162 fir->curr_pos--; 163 return (int16_t) (y >> 15); 164 } 165 166 #endif 167