How To Truncate A 32 Float To A 16bit Float In C#


Recommended Posts

I am processing audio, and sending it over TCP/IP and the people reciving teh package would like to do it this way to make packets smaller.

in c (or C++ )

I found an example of

short float32to16(float f)
{
short s_val;
short *s=&s_val;
*s = (* ((int *)&f) >> 16);
return *s;
}

so would I create a byte array of a fixed size, convert the float to a byte array and then put them in the first array and then put it out as short?

or would this do the same

short truncate(float f)
{
short output = Convert.ToSByte(f);
return output;
}

Edited by iccaros
Link to post
Share on other sites
or would this do the same

Convert.ToSByte() returns a signed byte based on the value of the argument, so no.

Do you really need 16-bit floats? Would, say, a 16-bit fixed-point (e.g., eight bit whole part, eight bit fraction, no exponent) type be adequate? And if you do need floats, do you really want want truncated IEEE singles? And is there any reason to roll your own compression instead of using one of the bazillion free audio codecs?

Link to post
Share on other sites
or would this do the same

Convert.ToSByte() returns a signed byte based on the value of the argument, so no.

Do you really need 16-bit floats? Would, say, a 16-bit fixed-point (e.g., eight bit whole part, eight bit fraction, no exponent) type be adequate? And if you do need floats, do you really want want truncated IEEE singles? And is there any reason to roll your own compression instead of using one of the bazillion free audio codecs?

I am not really trying to create my own, the Navy does this with Time series data (Sonar), and I was given the C code above as an example , but I do not under stand it, it looks like it returns the first 16 most significant bits of a float as a signed short. I guess that when audio is recorded from an hydrophone it is doen at 32 bits and put in to a byte array looking like this.. 00100111011100101010001111110111, and to save broad cast(using HF so very limited bandwidth) space they chop off the last 16 bits and add them back with zeros for play back. so that is what I really need to do, I could change the whole number to a byte array and then fill a 16 bit array with the firt 16 bits and ignore the rest

do something like

byte[] truncate (float f)
{
byte[] output = new byte[16];
byte[] temp = BitConverter.GetBytes( f );
for (int x = 0; x < 16; x++)
{
output[x] = temp[x];
}
return output;
}

In real life this will already be done for me by real equipment and I just add zeros, but for testing I will not have real data and I need to make sure I can create data that will look as close as I can.

Does this sound like it would do the same as the C++ example, or am I way off?

Thanks..

Link to post
Share on other sites
I am not really trying to create my own, the Navy does this with Time series data (Sonar)

Ah. That's annoying.

and I was given the C code above as an example , but I do not under stand it, it looks like it returns the first 16 most significant bits of a float as a signed short.

Indeed it does. If you know that code works, you can just use it in C# in an unsafe block (with one extra cast). If you'd rather use BitConverter (it does seem more .NETy), you want the last two bytes of the array returned by GetBytes(). Perhaps

BitConverter.ToInt16(BitConverter.GetBytes(f), 2);

Edited by jcl
Link to post
Share on other sites
I am not really trying to create my own, the Navy does this with Time series data (Sonar)

Ah. That's annoying.

and I was given the C code above as an example , but I do not under stand it, it looks like it returns the first 16 most significant bits of a float as a signed short.

Indeed it does. If you know that code works, you can just use it in C# in an unsafe block (with one extra cast). If you'd rather use BitConverter (it does seem more .NETy), you want the last two bytes of the array returned by GetBytes(). Perhaps

BitConverter.ToInt16(BitConverter.GetBytes(f), 2);

are the last two bytes the most significant, I thought they were the lest, or does that return the first two bytes.

Link to post
Share on other sites
are the last two bytes the most significant, I thought they were the lest, or does that return the first two bytes.

x86 is little-endian: the MSB is at the highest address.

Edited by jcl
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...