1 /*
2  * Copyright (C) 2018 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  * [Sample Rate Estimator]
19  * This module periodically estimates the mean sampling rate of a uniformly
20  * sampled signal. Note, this estimator uses a floating point accumulator for
21  * the timing intervals. This trades-off some accumulation of finite precision
22  * error to enhance the range of estimated sampling rates and prevent overflow
23  * when an equivalent 32bit integer accumulator is used. In typical use cases
24  * (sample rates: 5Hz - 2kHz, num_intervals_to_collect 10 - 100), the sample
25  * rate accuracy is typically much better than 0.1Hz.
26  *
27  * FUNCTIONALITY:
28  * sampleRateEstimatorInit -- Initializes the estimator. Sets the number of time
29  *   intervals require to compute the sample rate mean, and the upper limit for
30  *   the acceptable time interval.
31  *
32  * new_sampling_rate_estimate_ready -- Check this boolean flag if polling for
33  *   new estimates is desired.
34  *
35  * sampleRateEstimatorGetHz -- Returns the latest sample rate estimate and
36  *   resets the polling flag.
37  *
38  * sampleRateEstimatorUpdate -- Processes new timestamp data and computes new
39  *   sample rate estimates.
40  */
41 
42 #ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SAMPLE_RATE_ESTIMATOR_SAMPLE_RATE_ESTIMATOR_H_
43 #define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SAMPLE_RATE_ESTIMATOR_SAMPLE_RATE_ESTIMATOR_H_
44 
45 #include <stdbool.h>
46 #include <stddef.h>
47 #include <stdint.h>
48 #include <sys/types.h>
49 
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53 
54 // Designates the value used to indicate an invalid sample rate estimate.
55 #define SAMPLE_RATE_ESTIMATOR_INVALID_SAMPLE_RATE_HZ (-1.0f)
56 
57 // Sample rate estimator data structure.
58 struct SampleRateEstimator {
59   // Used to compute sample intervals to estimate the sampling rate.
60   uint64_t last_timestamp_nanos;
61 
62   // Accumulator used for computing the mean sampling interval.
63   float interval_accumulator_nanos;
64 
65   // The upper limit on the acceptance of valid time intervals (in nanoseconds).
66   // Larger time deltas result in a reset of the interval accumulator.
67   float max_interval_nanos;
68 
69   // The most recent mean sampling rate estimate.
70   float mean_sampling_rate_estimate_hz;
71 
72   /*
73    * The targeted number of time intervals required for a new sample rate mean
74    * calculation.
75    *
76    * NOTE: Assuming that the time interval noise is independent and identically
77    * distributed and drawn from a zero-mean normal distribution with variance
78    * 'Sigma^2'. The expected noise reduction is related to the choice of
79    * 'num_intervals_to_collect' as:
80    *
81    *   Output RMS Noise = Sigma / sqrt(num_intervals_to_collect).
82    *
83    * Example, a value of 100 for a 100Hz signal would provide updates once every
84    * second and provide a 90% reduction (i.e., [1 - 1/sqrt(100)] * 100%) in time
85    * interval noise.
86    */
87   size_t num_intervals_to_collect;
88 
89   // The number of time intervals currently collected.
90   size_t num_intervals_collected;
91 
92   // Polling flag used to signal that a new estimate is ready. This flag is
93   // reset when 'sampleRateEstimatorGetHz' is called.
94   bool new_sampling_rate_estimate_ready;
95 };
96 
97 // Initializes the sample rate estimator, sets the number of time intervals
98 // for the mean sample rate calculation, and defines the tolerable gap in timing
99 // data (in seconds).
100 void sampleRateEstimatorInit(struct SampleRateEstimator* sample_rate_estimator,
101                              size_t num_intervals_to_collect,
102                              float max_interval_sec);
103 
104 // Rather than using a function to poll for new sample rate estimates, which
105 // would incur an additional function call, simply check
106 // 'new_sampling_rate_estimate_ready' directly.
107 
108 // Returns the most recent sampling rate estimate, and resets the
109 // 'new_sampling_rate_estimate_ready' polling flag. Note, if polling is not
110 // used, one may access the sample rate estimate directly from the struct and
111 // avoid this function call.
112 float sampleRateEstimatorGetHz(
113     struct SampleRateEstimator* sample_rate_estimator);
114 
115 // Takes in a new timestamp and updates the sampling rate estimator.
116 void sampleRateEstimatorUpdate(
117     struct SampleRateEstimator* sample_rate_estimator,
118     uint64_t timestamp_nanos);
119 
120 #ifdef __cplusplus
121 }
122 #endif
123 
124 #endif  // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SAMPLE_RATE_ESTIMATOR_SAMPLE_RATE_ESTIMATOR_H_
125