blob: 5270ef0e2c93cf8806a258fb8d4bcb60441fd4df [file] [log] [blame]
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "ewma_power.h"
#include "math.h"
/* One sample per 1ms. */
#define EWMA_SAMPLE_RATE 1000
/* Smooth factor for EWMA, 1 - expf(-1.0/(rate * 0.01))
* where the 0.01 corresponds to 10ms interval that is chosen and
* being used in Chrome for a long time.
* Here the |rate| is set to the down sampled EWMA_SAMPLE_RATE and
* whenever it changes the calculated |smooth_factor| should be updated
* accordingly.
*/
const static float smooth_factor = 0.095;
void ewma_power_disable(struct ewma_power *ewma)
{
ewma->enabled = 0;
}
void ewma_power_init(struct ewma_power *ewma, unsigned int rate)
{
ewma->enabled = 1;
ewma->power_set = 0;
ewma->step_fr = rate / EWMA_SAMPLE_RATE;
}
void ewma_power_calculate(struct ewma_power *ewma, const int16_t *buf,
unsigned int channels, unsigned int size)
{
int i, ch;
float power, f;
if (!ewma->enabled)
return;
for (i = 0; i < size; i += ewma->step_fr * channels) {
power = 0.0f;
for (ch = 0; ch < channels; ch++) {
f = buf[i + ch] / 32768.0f;
power += f * f / channels;
}
if (!ewma->power_set) {
ewma->power = power;
ewma->power_set = 1;
} else {
ewma->power = smooth_factor * power +
(1 - smooth_factor) * ewma->power;
}
}
}
void ewma_power_calculate_area(struct ewma_power *ewma, const int16_t *buf,
struct cras_audio_area *area, unsigned int size)
{
int i, ch;
float power, f;
if (!ewma->enabled)
return;
for (i = 0; i < size; i += ewma->step_fr * area->num_channels) {
power = 0.0f;
for (ch = 0; ch < area->num_channels; ch++) {
if (area->channels[ch].ch_set == 0)
continue;
f = buf[i + ch] / 32768.0f;
power += f * f / area->num_channels;
}
if (!ewma->power_set) {
ewma->power = power;
ewma->power_set = 1;
} else {
ewma->power = smooth_factor * power +
(1 - smooth_factor) * ewma->power;
}
}
}