0

I have used the WinFilter Program to compute the FIR filter on C code but I got a issue:

The program only provide the 16 bits signed array and i need to that this vector be a unsigned int. So i am looking for a simple solution to relocated the array values to the next "values".

int16_t FIRCoef[Ntap] = {
    -1029,
    -1560,
    -1188,
        0,
     1405,
     2186,
     1718,
        0,
    -2210,
    -3647,
    -3095,
        0,
     5160,
    10947,
    15482,
    17197,
    15482,
    10947,
     5160,
        0,
    -3095,
    -3647,
    -2210,
        0,
     1718,
     2186,
     1405,
        0,
    -1188,
    -1560,
    -1029,
        0
};

uint16_t fir(uint16_t NewSample) {
    static uint16_t x[Ntap]; //input samples
    uint32_t y=0;            //output sample
    int n;

    //shift the old samples
    for(n=Ntap-1; n>0; n--)
       x[n] = x[n-1];

    //Calculate the new output
    x[0] = NewSample;
    for(n=0; n<Ntap; n++)
        y += FIRCoef[n] * x[n]; // calculo da convolucao na amostra
                                // Calculation of the convolution in the sample    
    return y / DCgain;
}

I think that one solution should be like this:

uint16_t--------int16_t---------index
0               -32767            1
1               -32766            2
2               -32765            3
...              ...             ...
65535            32767            65535

any hint?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
miguel747
  • 3
  • 1
  • 5
  • What about -32768, which is representable as an `int16_t`? Shouldn't that be the value that maps to 0? And if the "index" values start at 1 and run to 65535, but the corresponding `uint16_t` values start at 0 and run to 65535, then which `uint16_t` value is skipped? – John Bollinger Jun 01 '17 at 19:44
  • `return y / DCgain;` this looks wrong. I'd expect `int32_t iy=0; ... return iy / DCgain;` – chux - Reinstate Monica Jun 01 '17 at 19:45
  • Consider the off-by-one of the "one solution should be like this: `0...65535` is an even to an odd and `-32767 ... 32767` is an odd to an odd. That is mapping 65,536 `uint16_t` into 65,535 `int16_t`. Something is missing. – chux - Reinstate Monica Jun 01 '17 at 19:50
  • Is the `fir()` function essential to the question? I don't see what aspect of it would affect the content of an answer. – John Bollinger Jun 01 '17 at 20:04
  • the fir() function has already fixed. In fact i dont actually need the 32 bits output value. – miguel747 Jun 02 '17 at 01:51

1 Answers1

2

The value range for an int16_t is -32768 to 32767. Your question is unclear on this point, but it seems like you want simply to shift these values into the range of a uint16_t, 0 to 65535. That's reasonable, as the number of representable values for the two types is the same; it would be accomplished by adding the inverse of the minimum possible value of an int16_t to the input.

Of course, the Devil is in the details. When signed addition overflows, undefined behavior results. When an out-of-range value is converted to a signed integer type, the result is implementation defined, and can be an (implementation-defined) exception. It is desirable to avoid implementation-defined behavior and essential to avoid undefined behavior; that can be done in this case with just a little care:

uint16_t convert(int16_t in) {
    return (uint16_t) 32768 + (uint16_t) in;
}

That reliably does the right thing on any conforming system that provides the uint16_t and int16_t types in the first place, because the conversion and the addition operate modulo one plus the maximum value of a uint16_t. The negative input values are converted to unsigned values in the upper half of the range of uint16_t, and the addition then rotates all the values, bringing those from the upper half of the range around to the lower half.

As for doing it to a whole array, if you want to rely only on well-defined C behavior (i.e. if you want a solution that strictly conforms to the standard) then you'll need to make a copy of the data. You could use a function such as the above to populate the copy.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Upvoted, but doesn't this shift the values into the range [1, 65535]? – ad absurdum Jun 01 '17 at 20:46
  • No, @DavidBowling, why would it? -32768 converts to 0; +32767 converts to 65535; everything else converts 1:1 onto the numbers between. – John Bollinger Jun 01 '17 at 20:54
  • But isn't `INT_MIN` -32767? – ad absurdum Jun 01 '17 at 20:56
  • @DavidBowling, `INT_MIN` is implementation defined and irrelevant. -32767 is the largest it can be, but on many common platforms, even those with 16-bit `int`s, it is smaller (more negative). `int16_t`, where provided, is a 16-bit, two's complement integer type with no padding bits. It follows that its minimum value is definitely -32768. Always. – John Bollinger Jun 01 '17 at 20:58
  • There it is.... I was thinking that the largest allowable `INT_MIN`, which is -32767, is the same as the smallest 16 bit signed integer, but now I see that was wrong. Thanks :) – ad absurdum Jun 01 '17 at 21:03
  • Signed overflow is undefined not implementation defined. – R.. GitHub STOP HELPING ICE Jun 01 '17 at 21:54
  • tks for your simple solution. idk that signed int range value begin -32768. anyways i cant do upvote cause i newb on stackoverflow. – miguel747 Jun 02 '17 at 01:50