Repository: TheAlgorithms/Java
Pull request #6075 (2024-10-31 10:21:53)

Added Exponential Moving Average Filter for audio signals , EMAFilter.java & EMAFilterTest.java
<!--
Thank you for your contribution!
In order to reduce the number of notifications sent to the maintainers, please:
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
- make sure that all of the CI checks pass,
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
-->

<!-- For completed items, change [ ] to [x] -->

- [X] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
- [X] This pull request is all my own work -- I have not plagiarized it.
- [X] All filenames are in PascalCase.
- [X] All functions and variable names follow Java naming conventions.
- [X] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
- [X] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/TheAlgorithms/Java/pull/6075?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) Report
Attention: Patch coverage is `86.66667%` with `2 lines` in your changes missing coverage. Please review.
> Project coverage is 73.45%. Comparing base [(`03bb8ee`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/03bb8ee66ef479422e68899f05a36ffc2d77d69d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) to head [(`fcb8102`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/fcb8102287cce5b194f45a5b2f7b3fb514d971bb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

| [Files with missing lines](https://app.codecov.io/gh/TheAlgorithms/Java/pull/6075?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) | Patch % | Lines |
|---|---|---|
| [...java/com/thealgorithms/audiofilters/EMAFilter.java](https://app.codecov.io/gh/TheAlgorithms/Java/pull/6075?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fthealgorithms%2Faudiofilters%2FEMAFilter.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms#diff-c3JjL21haW4vamF2YS9jb20vdGhlYWxnb3JpdGhtcy9hdWRpb2ZpbHRlcnMvRU1BRmlsdGVyLmphdmE=) | 86.66% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/TheAlgorithms/Java/pull/6075?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) |

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #6075      +/-   ##
============================================
+ Coverage     73.42%   73.45%   +0.02%     
- Complexity     5078     5082       +4     
============================================
  Files           656      657       +1     
  Lines         17617    17632      +15     
  Branches       3394     3396       +2     
============================================
+ Hits          12936    12951      +15     
  Misses         4180     4180              
  Partials        501      501              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/TheAlgorithms/Java/pull/6075?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

Shreya123714: Hi @yanglbme, @siriak, @vil02, @BamaCharanChhandogi, @alxkm, I’ve added an EMA filter implementation and some test cases in Java, but I'm running into a build error, could you please take a look when you have a moment? I’d appreciate any feedback or suggestions on how to resolve this.
Thank you so much! 🙏
siriak: This is the error
![image](https://github.com/user-attachments/assets/7275be86-db1c-482e-96d2-24618cab550e)

Shreya123714: @siriak , Thank you :) 
Resolved it 🥹.. Done

Patch:
diff --git a/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java b/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java
new file mode 100644
index 00000000..0dd23e93
--- /dev/null
+++ b/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java
@@ -0,0 +1,48 @@
+package com.thealgorithms.audiofilters;
+
+/**
+ * Exponential Moving Average (EMA) Filter for smoothing audio signals.
+ *
+ * <p>This filter applies an exponential moving average to a sequence of audio
+ * signal values, making it useful for smoothing out rapid fluctuations.
+ * The smoothing factor (alpha) controls the degree of smoothing.
+ *
+ * <p>Based on the definition from
+ * <a href="https://en.wikipedia.org/wiki/Moving_average">Wikipedia link</a>.
+ */
+public class EMAFilter {
+    private final double alpha;
+    private double emaValue;
+    /**
+     * Constructs an EMA filter with a given smoothing factor.
+     *
+     * @param alpha Smoothing factor (0 < alpha <= 1)
+     * @throws IllegalArgumentException if alpha is not in (0, 1]
+     */
+    public EMAFilter(double alpha) {
+        if (alpha <= 0 || alpha > 1) {
+            throw new IllegalArgumentException("Alpha must be between 0 and 1.");
+        }
+        this.alpha = alpha;
+        this.emaValue = 0.0;
+    }
+    /**
+     * Applies the EMA filter to an audio signal array.
+     *
+     * @param audioSignal Array of audio samples to process
+     * @return Array of processed (smoothed) samples
+     */
+    public double[] apply(double[] audioSignal) {
+        if (audioSignal.length == 0) {
+            return new double[0];
+        }
+        double[] emaSignal = new double[audioSignal.length];
+        emaValue = audioSignal[0];
+        emaSignal[0] = emaValue;
+        for (int i = 1; i < audioSignal.length; i++) {
+            emaValue = alpha * audioSignal[i] + (1 - alpha) * emaValue;
+            emaSignal[i] = emaValue;
+        }
+        return emaSignal;
+    }
+}


Test patch:
diff --git a/src/test/java/com/thealgorithms/audiofilters/EMAFilterTest.java b/src/test/java/com/thealgorithms/audiofilters/EMAFilterTest.java
new file mode 100644
index 00000000..f2338d3d
--- /dev/null
+++ b/src/test/java/com/thealgorithms/audiofilters/EMAFilterTest.java
@@ -0,0 +1,41 @@
+package com.thealgorithms.audiofilters;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class EMAFilterTest {
+
+    @Test
+    public void testApplyBasicSignal() {
+        EMAFilter emaFilter = new EMAFilter(0.2);
+        double[] audioSignal = {0.1, 0.5, 0.8, 0.6, 0.3, 0.9, 0.4};
+        double[] expectedOutput = {0.1, 0.18, 0.304, 0.3632, 0.35056, 0.460448, 0.4483584};
+        double[] result = emaFilter.apply(audioSignal);
+        assertArrayEquals(expectedOutput, result, 1e-5);
+    }
+
+    @Test
+    public void testApplyEmptySignal() {
+        EMAFilter emaFilter = new EMAFilter(0.2);
+        double[] audioSignal = {};
+        double[] expectedOutput = {};
+        double[] result = emaFilter.apply(audioSignal);
+        assertArrayEquals(expectedOutput, result);
+    }
+
+    @Test
+    public void testAlphaBounds() {
+        EMAFilter emaFilterMin = new EMAFilter(0.01);
+        EMAFilter emaFilterMax = new EMAFilter(1.0);
+        double[] audioSignal = {1.0, 1.0, 1.0, 1.0};
+
+        // Minimal smoothing (alpha close to 0)
+        double[] resultMin = emaFilterMin.apply(audioSignal);
+        assertArrayEquals(audioSignal, resultMin, 1e-5);
+
+        // Maximum smoothing (alpha = 1, output should match input)
+        double[] resultMax = emaFilterMax.apply(audioSignal);
+        assertArrayEquals(audioSignal, resultMax, 1e-5);
+    }
+}