1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #ifndef OBOETESTER_UNUSED_H
19 #define OBOETESTER_UNUSED_H
20 
21 // Store this code for later use.
22 #if 0
23 
24 /*
25 
26 FIR filter designed with
27 http://t-filter.appspot.com
28 
29 sampling frequency: 48000 Hz
30 
31 * 0 Hz - 8000 Hz
32   gain = 1.2
33   desired ripple = 5 dB
34   actual ripple = 5.595266169703693 dB
35 
36 * 12000 Hz - 20000 Hz
37   gain = 0
38   desired attenuation = -40 dB
39   actual attenuation = -37.58691566571914 dB
40 
41 */
42 
43 #define FILTER_TAP_NUM 11
44 
45 static const float sFilterTaps8000[FILTER_TAP_NUM] = {
46         -0.05944219353343189f,
47         -0.07303434839503208f,
48         -0.037690487672689066f,
49          0.1870480506596512f,
50          0.3910337357836833f,
51          0.5333672385425637f,
52          0.3910337357836833f,
53          0.1870480506596512f,
54         -0.037690487672689066f,
55         -0.07303434839503208f,
56         -0.05944219353343189f
57 };
58 
59 class LowPassFilter {
60 public:
61 
62     /*
63      * Filter one input sample.
64      * @return filtered output
65      */
66     float filter(float input) {
67         float output = 0.0f;
68         mX[mCursor] = input;
69         // Index backwards over x.
70         int xIndex = mCursor + FILTER_TAP_NUM;
71         // Write twice so we avoid having to wrap in the middle of the convolution.
72         mX[xIndex] = input;
73         for (int i = 0; i < FILTER_TAP_NUM; i++) {
74             output += sFilterTaps8000[i] * mX[xIndex--];
75         }
76         if (++mCursor >= FILTER_TAP_NUM) {
77             mCursor = 0;
78         }
79         return output;
80     }
81 
82     /**
83      * @return true if PASSED
84      */
85     bool test() {
86         // Measure the impulse of the filter at different phases so we exercise
87         // all the wraparound cases in the FIR.
88         for (int offset = 0; offset < (FILTER_TAP_NUM * 2); offset++ ) {
89             // LOGD("LowPassFilter: cursor = %d\n", mCursor);
90             // Offset by one each time.
91             if (filter(0.0f) != 0.0f) {
92                 LOGD("ERROR: filter should return 0.0 before impulse response\n");
93                 return false;
94             }
95             for (int i = 0; i < FILTER_TAP_NUM; i++) {
96                 float output = filter((i == 0) ? 1.0f : 0.0f); // impulse
97                 if (output != sFilterTaps8000[i]) {
98                     LOGD("ERROR: filter should return impulse response\n");
99                     return false;
100                 }
101             }
102             for (int i = 0; i < FILTER_TAP_NUM; i++) {
103                 if (filter(0.0f) != 0.0f) {
104                     LOGD("ERROR: filter should return 0.0 after impulse response\n");
105                     return false;
106                 }
107             }
108         }
109         return true;
110     }
111 
112 private:
113     float   mX[FILTER_TAP_NUM * 2]{}; // twice as big as needed to avoid wrapping
114     int32_t mCursor = 0;
115 };
116 
117 /**
118  * Low pass filter the recording using a simple FIR filter.
119  * Note that the lowpass filter cutoff tracks the sample rate.
120  * That is OK because the impulse width is a fixed number of samples.
121  */
122 void lowPassFilter() {
123     for (int i = 0; i < mFrameCounter; i++) {
124         mData[i] = mLowPassFilter.filter(mData[i]);
125     }
126 }
127 
128 /**
129  * Remove DC offset using a one-pole one-zero IIR filter.
130  */
131 void dcBlocker() {
132     const float R = 0.996; // narrow notch at zero Hz
133     float x1 = 0.0;
134     float y1 = 0.0;
135     for (int i = 0; i < mFrameCounter; i++) {
136         const float x = mData[i];
137         const float y = x - x1 + (R * y1);
138         mData[i] = y;
139         y1 = y;
140         x1 = x;
141     }
142 }
143 #endif
144 
145 #endif //OBOETESTER_UNUSED_H
146