1 /* Copyright 2017 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <stdlib.h>
7 #include "dcblock.h"
8 
9 #define RAMP_TIME_MS 20
10 
11 struct dcblock {
12 	float R;
13 	float x_prev;
14 	float y_prev;
15 	float ramp_factor;
16 	float ramp_increment;
17 	int initialized;
18 };
19 
dcblock_new(float R,unsigned long sample_rate)20 struct dcblock *dcblock_new(float R, unsigned long sample_rate)
21 {
22 	struct dcblock *dcblock = (struct dcblock *)calloc(1, sizeof(*dcblock));
23 	dcblock->R = R;
24 	dcblock->ramp_increment = 1000. / (float)(RAMP_TIME_MS * sample_rate);
25 	return dcblock;
26 }
27 
dcblock_free(struct dcblock * dcblock)28 void dcblock_free(struct dcblock *dcblock)
29 {
30 	free(dcblock);
31 }
32 
33 /* This is the prototype of the processing loop. */
dcblock_process(struct dcblock * dcblock,float * data,int count)34 void dcblock_process(struct dcblock *dcblock, float *data, int count)
35 {
36 	int n;
37 	float x_prev = dcblock->x_prev;
38 	float y_prev = dcblock->y_prev;
39 	float R = dcblock->R;
40 
41 	if (!dcblock->initialized) {
42 		x_prev = data[0];
43 		dcblock->initialized = 1;
44 	}
45 
46 	for (n = 0; n < count; n++) {
47 		float x = data[n];
48 		float d = x - x_prev + R * y_prev;
49 
50 		y_prev = d;
51 		x_prev = x;
52 
53 		/*
54 		 * It takes a while for this DC-block filter to completely
55 		 * filter out a large DC-offset, so apply a mix-in ramp to
56 		 * avoid any residual jump discontinuities that can lead to
57 		 * "pop" during capture.
58 		 */
59 		if (dcblock->ramp_factor < 1.0) {
60 			d *= dcblock->ramp_factor;
61 			dcblock->ramp_factor += dcblock->ramp_increment;
62 		}
63 
64 		data[n] = d;
65 	}
66 	dcblock->x_prev = x_prev;
67 	dcblock->y_prev = y_prev;
68 }
69