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