Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * SpanDSP - a series of DSP components for telephony
0004  *
0005  * fir.h - General telephony FIR routines
0006  *
0007  * Written by Steve Underwood <steveu@coppice.org>
0008  *
0009  * Copyright (C) 2002 Steve Underwood
0010  *
0011  * All rights reserved.
0012  */
0013 
0014 #if !defined(_FIR_H_)
0015 #define _FIR_H_
0016 
0017 /*
0018    Ideas for improvement:
0019 
0020    1/ Rewrite filter for dual MAC inner loop.  The issue here is handling
0021    history sample offsets that are 16 bit aligned - the dual MAC needs
0022    32 bit aligmnent.  There are some good examples in libbfdsp.
0023 
0024    2/ Use the hardware circular buffer facility tohalve memory usage.
0025 
0026    3/ Consider using internal memory.
0027 
0028    Using less memory might also improve speed as cache misses will be
0029    reduced. A drop in MIPs and memory approaching 50% should be
0030    possible.
0031 
0032    The foreground and background filters currenlty use a total of
0033    about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo
0034    can.
0035 */
0036 
0037 /*
0038  * 16 bit integer FIR descriptor. This defines the working state for a single
0039  * instance of an FIR filter using 16 bit integer coefficients.
0040  */
0041 struct fir16_state_t {
0042     int taps;
0043     int curr_pos;
0044     const int16_t *coeffs;
0045     int16_t *history;
0046 };
0047 
0048 /*
0049  * 32 bit integer FIR descriptor. This defines the working state for a single
0050  * instance of an FIR filter using 32 bit integer coefficients, and filtering
0051  * 16 bit integer data.
0052  */
0053 struct fir32_state_t {
0054     int taps;
0055     int curr_pos;
0056     const int32_t *coeffs;
0057     int16_t *history;
0058 };
0059 
0060 /*
0061  * Floating point FIR descriptor. This defines the working state for a single
0062  * instance of an FIR filter using floating point coefficients and data.
0063  */
0064 struct fir_float_state_t {
0065     int taps;
0066     int curr_pos;
0067     const float *coeffs;
0068     float *history;
0069 };
0070 
0071 static inline const int16_t *fir16_create(struct fir16_state_t *fir,
0072                           const int16_t *coeffs, int taps)
0073 {
0074     fir->taps = taps;
0075     fir->curr_pos = taps - 1;
0076     fir->coeffs = coeffs;
0077     fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
0078     return fir->history;
0079 }
0080 
0081 static inline void fir16_flush(struct fir16_state_t *fir)
0082 {
0083     memset(fir->history, 0, fir->taps * sizeof(int16_t));
0084 }
0085 
0086 static inline void fir16_free(struct fir16_state_t *fir)
0087 {
0088     kfree(fir->history);
0089 }
0090 
0091 static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample)
0092 {
0093     int32_t y;
0094     int i;
0095     int offset1;
0096     int offset2;
0097 
0098     fir->history[fir->curr_pos] = sample;
0099 
0100     offset2 = fir->curr_pos;
0101     offset1 = fir->taps - offset2;
0102     y = 0;
0103     for (i = fir->taps - 1; i >= offset1; i--)
0104         y += fir->coeffs[i] * fir->history[i - offset1];
0105     for (; i >= 0; i--)
0106         y += fir->coeffs[i] * fir->history[i + offset2];
0107     if (fir->curr_pos <= 0)
0108         fir->curr_pos = fir->taps;
0109     fir->curr_pos--;
0110     return (int16_t) (y >> 15);
0111 }
0112 
0113 static inline const int16_t *fir32_create(struct fir32_state_t *fir,
0114                           const int32_t *coeffs, int taps)
0115 {
0116     fir->taps = taps;
0117     fir->curr_pos = taps - 1;
0118     fir->coeffs = coeffs;
0119     fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL);
0120     return fir->history;
0121 }
0122 
0123 static inline void fir32_flush(struct fir32_state_t *fir)
0124 {
0125     memset(fir->history, 0, fir->taps * sizeof(int16_t));
0126 }
0127 
0128 static inline void fir32_free(struct fir32_state_t *fir)
0129 {
0130     kfree(fir->history);
0131 }
0132 
0133 static inline int16_t fir32(struct fir32_state_t *fir, int16_t sample)
0134 {
0135     int i;
0136     int32_t y;
0137     int offset1;
0138     int offset2;
0139 
0140     fir->history[fir->curr_pos] = sample;
0141     offset2 = fir->curr_pos;
0142     offset1 = fir->taps - offset2;
0143     y = 0;
0144     for (i = fir->taps - 1; i >= offset1; i--)
0145         y += fir->coeffs[i] * fir->history[i - offset1];
0146     for (; i >= 0; i--)
0147         y += fir->coeffs[i] * fir->history[i + offset2];
0148     if (fir->curr_pos <= 0)
0149         fir->curr_pos = fir->taps;
0150     fir->curr_pos--;
0151     return (int16_t) (y >> 15);
0152 }
0153 
0154 #endif