Recursive Moving Average Filter

I implemented a recursive moving average filter to reduce background noise in some test audio files. It works in the time domain, which makes it faster than FFT-based algorithms when the number of points is kept small. It’s a simple and very fast filter, making it an optimal choice for certain audio types, such as telephone or normal speech. However, it’s not suitable for musical instruments with rich harmonic content, like strings. When I tested it on a string sound, it lost some of its characteristics. I plan to conduct more experimental implementations based on this technique in the future.

import os
import numpy as np
import scipy.io.wavfile as wavfile
 
def MovingAverageFilter(fileName, N = 7):
 
    #Moving point number has to be an odd positive integer, not too big
    #fs: sampling rate of the wav file, x: integer point array

    if (N % 2 == 0 or N > 19):
        raise ValueError("Please check moving point number")
        
    if (os.path.isfile(fileName) == False):					
        raise ValueError("Input file is not valid")
            
    fs, x = wavfile.read(fileName)

    #We only accept mono and 44.1khz audio files for this implementation  
    
    if (len(x.shape) != 1):                                  
            raise ValueError("Audio file is not mono")
    if (fs != 44100):                                        
            raise ValueError("Sampling rate of input sound is not 44100")
            
    size_x = len(x)
    noised_x = x + np.random.normal(loc = 0., scale = 30., size = size_x) 

    y = np.zeros((size_x), dtype = float)         #output signal
    segment = int((N - 1) / 2)                    #for symmetric averaging   
    accValue = 0                                  #recursive accumulation
    
    for i in range(N + 1):
        accValue = accValue + noised_x[i]
    y[segment] = accValue / N                     #moving average midpoint
    
    for j in range(segment, size_x - segment):
        accValue = accValue + noised_x[j + segment] - noised_x[j - (segment+1)]
        y[j] = accValue / N   
    
    difference = noised_x - y                     #for losing properties
    
    wavfile.write("Noised-Audio.wav", 44100, noised_x.astype(np.int16))
    wavfile.write("Cleaned-Audio.wav", 44100, y.astype(np.int16))
    wavfile.write("Difference-Audio.wav", 44100, difference.astype(np.int16))
    
    return

#Run it with your test audio file 
MovingAverageFilter('C:/Users/[yourname]/Desktop/test.wav')
[1] Advanced Digital Signal Processing and Noise Reduction, Saeed V. Vaseghi

[2] The Scientist and Engineer’s Guide to Digital Signal Processing, Steven W. Smith

[3] Moving Average