1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Google LLC. All rights reserved.
4 //
5 // Author: Sebastiano Carlucci <scarlucci@google.com>
6 
7 #include <stdint.h>
8 #include <sof/audio/component.h>
9 #include <sof/audio/format.h>
10 #include <sof/audio/dcblock/dcblock.h>
11 
12 /**
13  *
14  * Genereric processing function. Input is 32 bits.
15  *
16  */
dcblock_generic(struct dcblock_state * state,int64_t R,int32_t x)17 static int32_t dcblock_generic(struct dcblock_state *state,
18 			       int64_t R, int32_t x)
19 {
20 	/*
21 	 * R: Q2.30, y_prev: Q1.31
22 	 * R * y_prev: Q3.61
23 	 */
24 	int64_t out = ((int64_t)x) - state->x_prev +
25 		      Q_SHIFT_RND(R * state->y_prev, 61, 31);
26 
27 	state->y_prev = sat_int32(out);
28 	state->x_prev = x;
29 
30 	return state->y_prev;
31 }
32 
33 #if CONFIG_FORMAT_S16LE
dcblock_s16_default(const struct comp_dev * dev,const struct audio_stream * source,const struct audio_stream * sink,uint32_t frames)34 static void dcblock_s16_default(const struct comp_dev *dev,
35 				const struct audio_stream *source,
36 				const struct audio_stream *sink,
37 				uint32_t frames)
38 {
39 	struct comp_data *cd = comp_get_drvdata(dev);
40 	struct dcblock_state *state;
41 	int16_t *x;
42 	int16_t *y;
43 	int32_t R;
44 	int32_t tmp;
45 	int idx;
46 	int ch;
47 	int i;
48 	int nch = source->channels;
49 
50 	for (ch = 0; ch < nch; ch++) {
51 		state = &cd->state[ch];
52 		R = cd->R_coeffs[ch];
53 		idx = ch;
54 		for (i = 0; i < frames; i++) {
55 			x = audio_stream_read_frag_s16(source, idx);
56 			y = audio_stream_read_frag_s16(sink, idx);
57 			tmp = dcblock_generic(state, R, *x << 16);
58 			*y = sat_int16(Q_SHIFT_RND(tmp, 31, 15));
59 			idx += nch;
60 		}
61 	}
62 }
63 #endif /* CONFIG_FORMAT_S16LE */
64 
65 #if CONFIG_FORMAT_S24LE
dcblock_s24_default(const struct comp_dev * dev,const struct audio_stream * source,const struct audio_stream * sink,uint32_t frames)66 static void dcblock_s24_default(const struct comp_dev *dev,
67 				const struct audio_stream *source,
68 				const struct audio_stream *sink,
69 				uint32_t frames)
70 {
71 	struct comp_data *cd = comp_get_drvdata(dev);
72 	struct dcblock_state *state;
73 	int32_t *x;
74 	int32_t *y;
75 	int32_t R;
76 	int32_t tmp;
77 	int idx;
78 	int ch;
79 	int i;
80 	int nch = source->channels;
81 
82 	for (ch = 0; ch < nch; ch++) {
83 		state = &cd->state[ch];
84 		R = cd->R_coeffs[ch];
85 		idx = ch;
86 		for (i = 0; i < frames; i++) {
87 			x = audio_stream_read_frag_s32(source, idx);
88 			y = audio_stream_read_frag_s32(sink, idx);
89 			tmp = dcblock_generic(state, R, *x << 8);
90 			*y = sat_int24(Q_SHIFT_RND(tmp, 31, 23));
91 			idx += nch;
92 		}
93 	}
94 }
95 #endif /* CONFIG_FORMAT_S24LE */
96 
97 #if CONFIG_FORMAT_S32LE
dcblock_s32_default(const struct comp_dev * dev,const struct audio_stream * source,const struct audio_stream * sink,uint32_t frames)98 static void dcblock_s32_default(const struct comp_dev *dev,
99 				const struct audio_stream *source,
100 				const struct audio_stream *sink,
101 				uint32_t frames)
102 {
103 	struct comp_data *cd = comp_get_drvdata(dev);
104 	struct dcblock_state *state;
105 	int32_t *x;
106 	int32_t *y;
107 	int32_t R;
108 	int idx;
109 	int ch;
110 	int i;
111 	int nch = source->channels;
112 
113 	for (ch = 0; ch < nch; ch++) {
114 		state = &cd->state[ch];
115 		R = cd->R_coeffs[ch];
116 		idx = ch;
117 		for (i = 0; i < frames; i++) {
118 			x = audio_stream_read_frag_s32(source, idx);
119 			y = audio_stream_read_frag_s32(sink, idx);
120 			*y = dcblock_generic(state, R, *x);
121 			idx += nch;
122 		}
123 	}
124 }
125 #endif /* CONFIG_FORMAT_S32LE */
126 
127 const struct dcblock_func_map dcblock_fnmap[] = {
128 /* { SOURCE_FORMAT , PROCESSING FUNCTION } */
129 #if CONFIG_FORMAT_S16LE
130 	{ SOF_IPC_FRAME_S16_LE, dcblock_s16_default },
131 #endif /* CONFIG_FORMAT_S16LE */
132 #if CONFIG_FORMAT_S24LE
133 	{ SOF_IPC_FRAME_S24_4LE, dcblock_s24_default },
134 #endif /* CONFIG_FORMAT_S24LE */
135 #if CONFIG_FORMAT_S32LE
136 	{ SOF_IPC_FRAME_S32_LE, dcblock_s32_default },
137 #endif /* CONFIG_FORMAT_S32LE */
138 };
139 
140 const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap);
141