How to get standard positive and negative peak

I'm working on a project to record sound from a STM32. I have ADC values raning from 0 to 4095. I can convert it to an audio file and hear my voice. This is my algorithm for getting sample ranges in MATLAB: (ADC Value / 2047.5) - 1

It works great but the problem is that is not standard

I need a negative and positive peak like a normal sound. like this

Maybe there is a filter that removes the DC component.

It is possible to make that in the Arduino (or STM32).
When you have a average value, created by a low pass filter in software, then you can use that as a offset for every sample.

I make such a low pass filter with 'float' variables, but it is faster with integers. I forgot how to do it with integers.

float filtered;

void setup()
  filtered = analogRead( ...          // start with begin value, to get started at the begin.

void loop()
  int adcValue = analogRead( ...
  filtered = (0.99 * filtered) + (0.01 * float( adcValue));   // 1 percent low pass filter
  int sample = adcValue - int( filtered);      // use the filtered value as offset

  // The 'sample' will now be a value around zero without DC offset.

I think that the 1% filter is too much, probably a lower value is better.

Normally you apply a DC offset to the incoming audio so it sits half way through the ADC range. This will give you the biggest range of negative-going and positive-going sound values.

If you subtract 2047 from each value you'll get positive and negative values if that's what you want.

Or have I misunderstood the question?

Hi, i tried
it is it just negative peak?
I need a positive and a negative peak together

I think I should convert the adc value to 16-bit pcm, right?

When speaking into a microphone, then the signal is a normal signal with positive and negative peaks "together".

When using a electret microphone connected to a analog input, then it is no longer a good audio signal.
If you want that, then you should make a small circuit with a transistor as pre-amplifier.
Why is that important ? What you want is trivial and might not be needed. You have one signal zoomed in, and the other signal zoomed out. Therefor it seems as if they are different, but they are similar.

There are MEMS microphones with I2S interface:

I suggest to use a Raspberry Pi, connect a external USB soundcard with microphone input to it and use a common electret microphone.

I built a high quality preamplifier and connected it to the analog input and I can only get one side of the negative or positive peak

like this

Yes, that is the DC offset.

Audacity has a filter "Normalize" that has an option to remove the DC offset. Does that look better if you apply that ?
According to Audacity: "Technically, it does this by finding the average of all the sample values in the selection, then subtracting that average value from all the samples". That about the same what I described before.

1 Like

I'm trying now

thank you so much for your help it's working

but what is the algorithm?

It seems that the ADC is getting values in the range 0...2047 instead of 0...4095.
Try to change your formula to:

(ADC Value / 1023.5) - 1

What is a sound normalization algorithm like Audacity?

can you explain more about this code please ?
filtered = analogRead( ...

That is in setup(), to set the filtered value to analogRead() to avoid that it needs to start at zero.

For this "Normalize" section, I want to create a program for this normalization
Do you know what the Audacity formula is?

Substract the average from every sample.
The average of all samples is found by adding all sample values and dividing that by the number of samples.

Suppose the samples are -10, 1, 5, -20.
The total of all sample values = -24
The average is -24 / 4 = -6
To normalize the samples, add 6 to all the samples.
The normalized samples are -4, 7, 11, -14.

Check: -4 + 7 + 11 -14 = 0. That is correct, the samples are now around the zero line.

Sorry, while you were asking that, I was adding an example to my previous post :face_with_raised_eyebrow:

The preamp output shouldn't have any DC offset. That is a design mistake.