4

Can anyone show me an algorithm of removing white noise from a byte[] sound? I work for a personal audio recording app for android and I use android API for recording. Below is the method used to write the recording to file (in wav format).

 private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener()
 {
    public void onPeriodicNotification(AudioRecord recorder)
    {
        aRecorder.read(buffer, 0, buffer.length);
        try
        { 
            fWriter.write(buffer); // Write buffer to file
            payloadSize += buffer.length;
            if (bSamples == 16)
            {
                for (int i=0; i<buffer.length/2; i++)
                { // 16bit sample size
                    short curSample = getShort(buffer[i*2], buffer[i*2+1]);
                    if (curSample > cAmplitude)
                    { // Check amplitude
                        cAmplitude = curSample;
                    }
                }
            }
            else
            { // 8bit sample size
                for (int i=0; i<buffer.length; i++)
                {
                    if (buffer[i] > cAmplitude)
                    { // Check amplitude
                        cAmplitude = buffer[i];
                    }
                }
            }
        }
        catch (IOException e)
        {
            Log.e(AudioRecorder2.class.getName(), "Error occured in updateListener, recording is aborted");
        }
    }

    public void onMarkerReached(AudioRecord recorder)
    {}
};

I want to apply some transformations to buffer to remove the white noise which can be heard during playback of the recording. If anybody know some algorithm/link to some low-pass filter (or anything else that might be helpful), please help.

Thanks.

4
  • 4
    In general, you can't remove white noise, unless you know something about your audio signal. For instance, if you know that it only occupies a certain frequency band, then you can use a low-pass filter, which will remove the high-frequency noise. There is no general solution, though. Commented Apr 30, 2012 at 11:12
  • I am also getting the same noise. Did you find the solution? Commented Oct 1, 2012 at 5:04
  • No, I left this project behind. If you find it, PLEASE reply here so I will accept your answer. Commented Oct 2, 2012 at 12:28
  • @AlexandruCircus Hi sir, i hope my comment will finds you well. I am also working on my project and want to simple audio recorder but as a newbie, i am not understanding from stuff given on internet. Could you please share your code with me? I will be very thankful to you. Looking forward for your positive response :) Commented Jul 26, 2019 at 18:29

3 Answers 3

1

You could average the samples if you know: sample frequency (8,16,32,64,128) and bit depth (8,16,32) and channels recorded (mono, stereo).

.wav audio is written alternating channels or interlaced in an array in the size of bit depth. (I think it starts with the left channel)

16kHz 16-bit is a short[] with 16,000 entries per second of audio

64kHZ 32-bit is a int[] with 64,000 " "

you could average the 16-bit channels going from stereo to mono (short[even]+short[odd])/2

you could average the 16-bit frequency 128kHz to 16kHz (8 to 1) short[0,2,4,6,8,10,12,14]/8

averaging lower than 16kHZ frequency will probably sound worse

Depending on how the audio was quantized (analog to digital linearly or logarithmically a-law/u-law/linear) you may need to try different methods.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I will try stereo to mono first (If I'm not wrong a .wav frame(16 bit depth) is composed by 2 samples (4 bytes) - 1 sample for right channel, 1 for left), so averaging will result as mono output.
1

Another approach would be to the following at your pre-processing stage,

recorder.read(data, 0, data.length);
if(isAudible(data)) {
    // TODO further processing can go here
}

public static boolean isAudible(short[] data) {
    double rms = getRootMeanSquared(data);
    return (rms > 198 && 5600 > rms);
}

public static double getRootMeanSquared(short[] data) {
    double ms = 0;
    for (int i = 0; i < data.length; i++) {
        ms += data[i] * data[i];
    }
    ms /= data.length;
    return Math.sqrt(ms);
}

Comments

0

The most simple way to implement a low pass is to average multiple samples. so if you have n samples, you can do something like that:

// your sample data array
int[] samples
//number of samples you want to average
int AVERAGE_SAMPLE_COUNT = 3;

for(int i=0; i<samples.length-AVERAGE_SAMPLE_COUNT; i++){
    //variable for storing the values of multiple samples
    int avgSample = 0;
    for(int a=0; a<AVERAGE_SAMPLE_COUNT; a++){
        //add up the current and the next n samples
        avgSample += samples[i+a]
    }
    //devide by the number of samples to average them
    avgSample /= AVERAGE_SAMPLE_COUNT;
    //replace first sample with the averaged value
    samples[i] = avgSample
}

As you can see, the only flaw might be, that the output gets shorter by AVERAGE_SAMPLE_COUNT. You can easily try out different strength of the algo by a changing AVERAGE_SAMPLE_COUNT. Also, it is working in-place, that means it changes your initial input data.

3 Comments

Averaging gives a very poor low pass filter - also the audio quality will suffer badly if you throw away 2/3 of the bandwidth.
Thanks, I will try implementing this filter and see the results.
Indeed the quality of the output is even worse than original(the original has "a little" noise though, so for the moment I will leave it as it is - maybe in the future I will start studying in deep the sounds theory so I'll be able to implement noise removal like audacity does. Dreams:) .) Thanks anyway for your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.