-2

I'm trying to make a simple filter incoming data (save maximum and minimum pick), for example: 44100 comes samples per second, but the screen must be displayed 1000. I choose a maximum or minimum in the range of 44.1 samples, and output the screen. However, this algorithm is not very accurate. In the code, it looks like this:

example pseudo algorithm

float max = 0;
float min = 0;
float filter = 0;
float step  = 44100/1000;
for(int i = 0 ; i < 44100; i++){

    if(input[i] > 0)
        if(max < input[i])
            max = input[i];
    if(input[i] < 0)
        if(min > input[i])
            min = input[i];

    filter++;
    if(filter >= step){
        filter = filter - step;

        //1st version  (bad version)
        memory[count] = max + min;

        //2nd version (bad version)
        if(max > abs(min))
            memory[count] = max;
        else if(max < abs(min))
            memory[count] = min;

        //3nd version (only maximum)
            memory[count] = max; //work great, but only > 0

        //4nd version (only minimum)
            memory[count] = min; //work great, but only < 0

        max = 0;
        min = 0;
        count++;
        if(count >= 1000)
            count = 0;
    };
};

What am I doing wrong? Separately, everything works fine (max or min), but when connecting all together, result bad.

I have picture, but I can not paste them here. Links to pictures under this post.

gotostereo
  • 37
  • 1
  • 7
  • You should note that the integer division `44100/1000` actually yields `44` not `44.1` as you might expect. – πάντα ῥεῖ Mar 13 '15 at 12:13
  • you sure you initialize min & max to 0? – user3528438 Mar 13 '15 at 12:18
  • It is not so important, the incoming data can be infinite, and we can take 1 for example every 10 sample. The task of preserving the maximum and minimum, choosing from .... – gotostereo Mar 13 '15 at 12:27
  • http://rghost.ru/8jVDdMqZC/image.png http://rghost.ru/8sGsnj4Jt/image.png http://rghost.ru/874LyBpqk/image.png – gotostereo Mar 13 '15 at 12:50
  • @user3528438: For a typical AC signal that's fine. Assume the actual signal varies between -100 and +100. The `min` value will quickly decrease as all negative values are smaller than 0. Similarly, all positive values are >0 so `max` will quickly converge to 100. – MSalters Mar 13 '15 at 13:40

3 Answers3

0

To properly compute the min/max of a set of numbers you have to initialize the values correctly. By setting them to 0 you run into the problems you've found. You have basically two ways to initialize min/max:

  1. Set them to a value larger/smaller than any of your input data.
  2. Set them to the first value in the array.

For (1), if you know your data is, for example, always between -100 and +100 you can simply do:

min =  101;
max = -101;

Note that this doesn't work if your inputs can be any value in the range of the type. For (2) you can do something like:

float max = input[0];
float min = input[0];

...

for (int i ... ) 
{
    ...

    if (filter >= step)
    {
        ...
        min = input[i + 1];   // Be aware of overflow on the last element if
        max = input[i + 1];   // input[] is exactly 44100 elements in size
    }
}
uesp
  • 6,194
  • 20
  • 15
  • Why so initialize variables? axis signal 0. value -1 to 1. – gotostereo Mar 13 '15 at 13:09
  • If you know your inputs are always from -1 to 1 then you can do: `min = 2; max = -2;` – uesp Mar 13 '15 at 13:26
  • This does not change the result. 3 pictures added. How does it work now. Under the top post links. – gotostereo Mar 13 '15 at 13:41
  • Wrong answer; that part actually works (see individual plots). The input has no DC component so it's known that the maximum is non-negative. Your initial estimate of the maximum must be the lower bound of the range, and the smallest non-negative number indeed is 0. – MSalters Mar 13 '15 at 13:43
  • I was assuming @gotostereo was trying to find the min/max of the inputs within a range of values. If he is trying to find the negative min and positive max then his original code for finding them is fine. The question may be what to do with steps with both a non-zero min and max. For example, what do you wish to output (store in `memory[]`) if `min=-0.5` and `max=+0.5`? Or `min=-0.5` and `max=+0.6`? Or `min=-0.6` and `max=+0.5`? – uesp Mar 13 '15 at 14:54
0

What do you actually want to see? If it is audio sample, zero means quiet, you probably want to see the envelope - store minimum and maximum for each bin (your bin here=1000 counts) together and display the two in the same picture.

Your sample rate (after division) is 44 Hz, so you can forget some nice simplified waveform (if it is audio)...

jaromrax
  • 274
  • 1
  • 12
0

The problem that you're seeing in the third graph is that you are storing either a minimum (about -1) or a maximum (about +1). And it's pretty random which of the two you store.

When you then connect the dots, you see a short line segment (2 pixels) whenever you stored two minima or two maxima. But if you store a minimum followed by a maximum, connecting the two gives you a line with a very steep upwards slope. A maximum followed by a minimum gives you a strong downward slope.

The real problem here is that you probably don't realize what you wanted to draw. You should have two arrays, memory_min[] and memory_max[]. And don't mix those two.

MSalters
  • 173,980
  • 10
  • 155
  • 350