Skip to content

Exponential moving average filter #12337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

## Audio Filters
* [Butterworth Filter](audio_filters/butterworth_filter.py)
* [Ema Filter](audio_filters/ema_filter.py)
* [Iir Filter](audio_filters/iir_filter.py)
* [Show Response](audio_filters/show_response.py)

Expand Down
71 changes: 71 additions & 0 deletions audio_filters/ema_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""
By @Shreya123714

https://en.wikipedia.org/wiki/Moving_average
"""

import numpy as np


class EMAFilter:
"""
A class for applying an Exponential Moving Average (EMA) filter
to audio data.

Attributes:
alpha (float): Smoothing factor where 0 < alpha <= 1.
ema_value (float): Stores the most recent EMA value
for the ongoing calculation.
"""

def __init__(self, alpha: float) -> None:
"""
Initialize the Exponential Moving Average (EMA) filter.

Parameters:
alpha (float): Smoothing factor where 0 < alpha <= 1.

Raises:
ValueError: If alpha is not within the range (0, 1].
"""
if not (0 < alpha <= 1):
raise ValueError("Alpha must be between 0 and 1.")
self.alpha = alpha
self.ema_value = 0.0

def apply(self, audio_signal: list[float]) -> np.ndarray:
"""
Apply the EMA filter to a sequence of
audio signal values.

Parameters:
audio_signal (list[float]): List of numerical values
representing the audio signal.

Returns:
np.ndarray: Array containing the smoothed audio signal.

Example:
>>> ema_filter = EMAFilter(0.2)
>>> np.allclose(ema_filter.apply([0.1, 0.5, 0.8, 0.6, 0.3, 0.9, 0.4]),
... [0.1, 0.18, 0.304, 0.3632, 0.35056, 0.460448, 0.4483584],
... rtol=1e-5, atol=1e-8)
True
"""
if not audio_signal:
return np.array([])

ema_signal: list[float] = []
self.ema_value = audio_signal[0]
ema_signal.append(self.ema_value)

for sample in audio_signal[1:]:
self.ema_value = self.alpha * sample + (1 - self.alpha) * self.ema_value
ema_signal.append(self.ema_value)
return np.array(ema_signal)


if __name__ == "__main__":
import doctest

doctest.testmod()