• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2020 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 "ewma_power.h"
7 #include "math.h"
8 
9 /* One sample per 1ms. */
10 #define EWMA_SAMPLE_RATE 1000
11 
12 /* Smooth factor for EWMA, 1 - expf(-1.0/(rate * 0.01))
13  * where the 0.01 corresponds to 10ms interval that is chosen and
14  * being used in Chrome for a long time.
15  * Here the |rate| is set to the down sampled EWMA_SAMPLE_RATE and
16  * whenever it changes the calculated |smooth_factor| should be updated
17  * accordingly.
18  */
19 const static float smooth_factor = 0.095;
20 
ewma_power_disable(struct ewma_power * ewma)21 void ewma_power_disable(struct ewma_power *ewma)
22 {
23 	ewma->enabled = 0;
24 }
25 
ewma_power_init(struct ewma_power * ewma,unsigned int rate)26 void ewma_power_init(struct ewma_power *ewma, unsigned int rate)
27 {
28 	ewma->enabled = 1;
29 	ewma->power_set = 0;
30 	ewma->step_fr = rate / EWMA_SAMPLE_RATE;
31 }
32 
ewma_power_calculate(struct ewma_power * ewma,const int16_t * buf,unsigned int channels,unsigned int size)33 void ewma_power_calculate(struct ewma_power *ewma, const int16_t *buf,
34 			  unsigned int channels, unsigned int size)
35 {
36 	int i, ch;
37 	float power, f;
38 
39 	if (!ewma->enabled)
40 		return;
41 	for (i = 0; i < size; i += ewma->step_fr * channels) {
42 		power = 0.0f;
43 		for (ch = 0; ch < channels; ch++) {
44 			f = buf[i + ch] / 32768.0f;
45 			power += f * f / channels;
46 		}
47 		if (!ewma->power_set) {
48 			ewma->power = power;
49 			ewma->power_set = 1;
50 		} else {
51 			ewma->power = smooth_factor * power +
52 				      (1 - smooth_factor) * ewma->power;
53 		}
54 	}
55 }
56 
ewma_power_calculate_area(struct ewma_power * ewma,const int16_t * buf,struct cras_audio_area * area,unsigned int size)57 void ewma_power_calculate_area(struct ewma_power *ewma, const int16_t *buf,
58 			       struct cras_audio_area *area, unsigned int size)
59 {
60 	int i, ch;
61 	float power, f;
62 
63 	if (!ewma->enabled)
64 		return;
65 	for (i = 0; i < size; i += ewma->step_fr * area->num_channels) {
66 		power = 0.0f;
67 		for (ch = 0; ch < area->num_channels; ch++) {
68 			if (area->channels[ch].ch_set == 0)
69 				continue;
70 			f = buf[i + ch] / 32768.0f;
71 			power += f * f / area->num_channels;
72 		}
73 		if (!ewma->power_set) {
74 			ewma->power = power;
75 			ewma->power_set = 1;
76 		} else {
77 			ewma->power = smooth_factor * power +
78 				      (1 - smooth_factor) * ewma->power;
79 		}
80 	}
81 }
82