linux/drivers/misc/echo/fir.h
<<
>>
Prefs
   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
 155