0

I have a sample set of 32-bit data in the format 24-bit, 2’s complement, MSB first. The data precision is 18 bits; unused bits are zeros. I want to process the numbers in this sample set to find their average value.

However, I am not sure how to convert all the numbers to the same type and then use them for calculating the average.

One way is to bit shift all the numbers from the sample set to right by 14. This way I directly get the 18 useful bits (since it is 24-bit data with 18-bit precision, so extract only 18 useful bits). Then I can directly use these numbers to calculate their average.

Following is an example sample set of data samples:-

  • 0xF9AFC000

  • 0xF9AFC000

  • 0xF9AE4000

  • 0xF9AE0000

  • 0xF9AE0000

  • 0xF9AD0000

  • 0xF9AC8000

  • 0xF9AC8000

  • 0xF9AC4000

  • 0xF9AB4000

  • 0xF9AB8000

  • 0xF9AB4000

  • 0xF9AA4000

  • 0xF9AA8000

  • 0xF9A98000

  • 0xF9A8C000

  • 0xF9A8C000

  • 0xF9A8C000

  • 0xF9A88000

  • 0xF9A84000

However, the 18-bit number still has the sign bit (MSB). This bit is not always set and might be 0 or 1 depending upon the data.

Should I just mask the sign bit by &ing all the numbers with 0x1FFFF and use them for calculating average?

Or should I first convert them from 2's complement to integers by negating and adding 1?

Please suggest a proper way to extract and process "24-bit, 2’s complement, MSB first" number from a 32-bit number.

Thanks in advance!

Sandrocottus
  • 521
  • 3
  • 8
  • 31
  • Possible dup, have a look at [reversing two's complement for 18bit int](https://stackoverflow.com/questions/51887441/reversing-twos-complement-for-18bit-int) -- with multiple included links to relevant answers. (including `14-bit` two's compliment) – David C. Rankin Dec 06 '18 at 07:27
  • Can you share a sample input file? It's really confusing what you mean by saying `32-bit data` followed by `24-bit`, followed by `the data precision is 18 bits`. – selbie Dec 06 '18 at 07:27
  • 2
    Your words aren't clear enough to understand how the data is formatted. You should draw a picture of a 32-bit word and show how the unused bits are set. A negative 2s-complement number starts with all 1's in the high order bits. One question is whether the high byte of the 32 bits all 1's if the number is negative, or is it zero? – Gene Dec 06 '18 at 07:28
  • Easiest might be to sign-extend the values to 32-bit integers, do the calculations on the 32-bit integers, and then mask out the high 8 bits (simply truncating over-/under-flowing values). Otherwise there are plenty of documentation and examples of doing arithmetic on arbitrary bit-length integers all over the Internet. – Some programmer dude Dec 06 '18 at 07:29
  • Hi @selbie, I have edited the question to show a sample set. I need to extract the 24-bits from these 32-bit numbers. Furthermore, 18 bits of precision means that I can mask the least 6-bits from those 24-bits. – Sandrocottus Dec 06 '18 at 08:47
  • Hi @Gene, the high byte of the 32 bits is not necessarily all 1's, it can change. However, in the question, I have added a sample set which has all the 32-bit numbers whose high byte is all 1's. – Sandrocottus Dec 06 '18 at 08:49
  • 2
    There are two parts to the data for an MCVE ([MCVE]): the input and the expected output. You've provide the input; thanks. What do you expect as output? It looks like all the values are negative; is that correct? And all the values have 14 zero-bits in the least-significant bits? There's also a question of 'what have you tried' and therefore the actual output vs the expected output. – Jonathan Leffler Dec 06 '18 at 08:50
  • Hi @JonathanLeffler, thanks for your comments. 1.What do you expect as output? I need to extract the 24-bit, 2’s complement, MSB first from the 32-bit numbers that I have mentioned in the edit. 2. It looks like all the values are negative; is that correct? And all the values have 14 zero-bits in the least-significant bits? Yes, correct. 3. 'what have you tried' and therefore the actual output vs the expected output. I have already mentioned two ways which I tried, but both seem to yield incorrect values, hence this post!! – Sandrocottus Dec 06 '18 at 09:03
  • Yes, you mentioned what you’d tried, but you didn’t show it, so we can’t tell wether there was a simple mistake or a major misunderstanding. And you don’t say what you want. Do you want the value in a 32-but signed integer with leading one bits for negatives and zeros for positives, or do you want the leading 8 bits all zero or what? This is why you need to show what you want. On a 32-bit or 64-but machine, the only way of storing a 24-bit value in 24 bits is to use an array of 3 characters. Is that what you want? – Jonathan Leffler Dec 06 '18 at 09:28
  • "Convert from 2's complement". To what? Do you have 1's complement or sign-and-magnitude hardware in your possession? – n. m. could be an AI Dec 06 '18 at 09:34
  • Convert from 2's complement to decimal integer (by negating, then adding 1) – Sandrocottus Dec 06 '18 at 10:51
  • 2
    There's no such data type as "decimal integer" in C. `int` and friends store integers, not "decimal integers". A decimal representation is what `printf` outputs. It is created at the moment you use `%d` or a similar format string. – n. m. could be an AI Dec 06 '18 at 13:15
  • Why don't you refer to the answer by @Diego Cabral in the post https://stackoverflow.com/questions/47142902/digital-microphone-i2s-data-output. How about the "decimal" over there? Even they are working with 24-bit data. – Sandrocottus Dec 06 '18 at 13:58
  • I really lost my direction following the comments. A simple suggestion would've sufficed. But never mind... – Sandrocottus Dec 06 '18 at 14:01
  • 1
    You might want to check whether your system does a signed or unsigned shift: https://stackoverflow.com/questions/7622/are-the-shift-operators-arithmetic-or-logical-in-c If it does a signed shift, that's all you need. (At the expense of portability.) – Matthew Woodruff Dec 06 '18 at 15:23
  • If you want to answer to a specific user mention their username like this: @Sandrocottus . Now about that answer — there are many people who misunderstand or mususe thevterminology, you are nit the only one. Someone mentioned "decimal" in an answer doesn't mean it's correct usage. Not all answers here are impeccable. About a suggestion — I cannot really know what you want because your wording is not clear and your understanding of the subject is AFAICT incomplete, so I cannot make a suggestion. The purpose of the comments is to clarify the question, that's what I'm trying to do. – n. m. could be an AI Dec 07 '18 at 09:06

1 Answers1

1

Well, providing sample data isn't a complete spec, but let's look at

F9AFC000

It looks like the data are in the high order 3 bytes. That's a guess. If they're indeed 24 bits of 2's complement, then getting the true value into a 32 bit int is just

int32_t get_value_from_datum(uint32_t datum) {
  return (int32_t) datum >> 8; 
}

On the sample, this will sign extend the high bit of the leading F. The result will be FFF9AFC0. As a 2's complement integer written in base 10, this is -413760.

Or perhaps you mean that the 18 bits of interest are fully left-justified in the 32-bit word. Then it's

int32_t get_value_from_datum(uint32_t datum) {
  return (int32_t) datum >> 14; 
}

This results in -6465.

As I said in the comment, you need to more clearly explain the data format.

A precise spec is most easily shown as a picture of the 32-bit word, MSB to LSB, which identifies which 18 bits are the data bits.

Gene
  • 46,253
  • 4
  • 58
  • 96