brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · 4d08210 Raw
155 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * SpanDSP - a series of DSP components for telephony4 *5 * fir.h - General telephony FIR routines6 *7 * Written by Steve Underwood <steveu@coppice.org>8 *9 * Copyright (C) 2002 Steve Underwood10 *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 handling21   history sample offsets that are 16 bit aligned - the dual MAC needs22   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 be29   reduced. A drop in MIPs and memory approaching 50% should be30   possible.31 32   The foreground and background filters currenlty use a total of33   about 10 MIPs/ch as measured with speedtest.c on a 256 TAP echo34   can.35*/36 37/*38 * 16 bit integer FIR descriptor. This defines the working state for a single39 * 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 single50 * instance of an FIR filter using 32 bit integer coefficients, and filtering51 * 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 single62 * 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#endif155