I believe there is a function which returns the max value for a double, however, I do not need this. I'm converting the following function:

public void StaticCompress(short[] samples, float param)
{
    for (int i = 0; i < samples.Length; i++)
    {
        int sign = (samples[i] < 0) ? -1 : 1;
        float norm = ABS(samples[i] / 32768); // NOT short.MaxValue
        norm = 1.0 - POW(1.0 - norm, param);
        samples[i] = 32768 * norm * sign;
    }
}

But instead of using shorts I pass in a double array. Anyone have any suggestions?

I think it is 1.79769e+308.

You can access it via numeric_limits::max

i.e. -

#include <limits>

If you then output a statement for this limit for type double, it should give the number I gave up top.

But in the line:

float norm = ABS(samples[i] / 32768); // NOT short.MaxValue

It tells me not to use short.MaxValue so I assumed that numeric_limits::max will do the same as this?

What is telling you not to use short.MaxValue? The compiler?

Perhaps you could use a macro instead. This is what is in <cfloat> itself:

#define DBL_MAX 1.7976931348623158e+308

Include <cfloat> in your program, use DBL_MAX in that line, and see what happens.

The problem with using the maximum value of a double is that you will most certainly lose all meaningful value in your samples array. For example, if you do samples[i] / std::numeric_limits<double>::max(), then it won't really matter much what the value of samples[i] is, unless it is extremely close to the maximum value. What you'll get is just a number extremely close to zero, within the number of significant digits. So, I don't think that such a strategy would make any sense. You need to rely on a meaningful upper-bound to your sample values.

When I see this code ABS(samples[i] / 32768);, to me, this looks like just a normal ADC (Analog-Digital Conversion) sample conversion to a floating point value normalized to the 0-1 range. This is because ADC units take an analog signal and convert it to a digital signal of a certain number of bits N, and thus, to an integer value within a range [0, 2^N]. To map that integer value back to the range of the analog signal (0 to 5 Volts, or just 0 to 1 in normalized units), you have to perform a very simple conversion, like samples[i] / 32768.

So, you have to see that function as doing this:

public void StaticCompress(short[] samples, float param)
{
  for(int i = 0; i < samples.Length; i++)
  {
    int sign = get_sign_of(samples[i]);
    float norm = normalize_abs_value( samples[i] );
    norm = 1.0 - POW(1.0 - norm, param);
    samples[i] = denormalize_value( norm * sign );
  }
}

where in the case of a full-range 16bit ADC sample, the normalize / denormalize process is just a division or multiplication by 2^15.

But if you have double values coming in, then they have their own range already, which is certainly not [- std::numeric_limits<double>::max(), std::numeric_limits<double>::max()]. You need to know the meaningful range for those values, period.

It tells me not to use short.MaxValue

The reason it tells you that the 32768 is not the short.MaxValue is because the person who wrote that code was working on the same principle I just explained. The value 32768 is not the maximum value of a short (well, it is, but by coincidence only), it is the maximum of the meaningful range of the sample values. And you need to apply the same principle if you are going to use something else, like doubles.

Another example, it is not uncommon to have weird ADC bit numbers. For example, you could have a 6-bit ADC unit, meaning that you can store the samples in a byte (8 bits), but the meaningful range is only 6 bits (the other two are always zero). So, in that case, the conversion factor would be either 32 or 64, depending on whether the value is signed or unsigned.

Edited 3 Years Ago by mike_2000_17: added explanation

Comments
Thanks for the input Mike. Your posts are always thorough, going above and beyond simply answering the question

I think it is 1.79769e+308.

It's implementation defined.

It tells me not to use short.MaxValue so I assumed that numeric_limits::max will do the same as this?

The two are roughly synonymous. I suspect the comment is saying not to use short.MaxValue because short.MaxValue gives you 32767 rather than 32768, which breaks the algorithm.

So in the normalize_abs_value function, I would take the value of samples[i] and then multiply by 2 to the power of 15?

multiply by 2 to the power of 15?

2^15 == 32768, I thought that was obvious.

All I did in that code was replace a line of code by an abstract function call, it was just to make you think about it at an abstract level, instead of just focusing on the details. You look at the initial piece of code and see a "division by the maximum value", and then, you wonder how to do the same when the type is double instead of short. What I want you to see in that piece of code is a "normalization to a range of [0,1]", and then, ask yourself what would be a meaningful normalization for your problem domain. For the author of the code, in his problem domain, the meaningful normalization was a conversion between the range [-32768, 32768] to [-1.0, 1.0]. What is yours?

This question has already been answered. Start a new discussion instead.