Skip to content

Commit

Permalink
Add conversion from float to fixed-point i16
Browse files Browse the repository at this point in the history
To encode float values between -1 and 1.

PR #3369 <#3369>
  • Loading branch information
rom1v committed Aug 28, 2022
1 parent 1ab6c19 commit 1f138ae
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
15 changes: 15 additions & 0 deletions app/src/util/binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,19 @@ sc_float_to_u16fp(float f) {
return (uint16_t) u;
}

/**
* Convert a float between -1 and 1 to a signed 16-bit fixed-point value
*/
static inline int16_t
sc_float_to_i16fp(float f) {
assert(f >= -1.0f && f <= 1.0f);
int32_t i = f * 0x1p15f; // 2^15
assert(i >= -0x8000);
if (i >= 0x7fff) {
assert(i == 0x8000); // for f == 1.0f
i = 0x7fff;
}
return (int16_t) i;
}

#endif
20 changes: 20 additions & 0 deletions app/tests/test_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ static void test_float_to_u16fp(void) {
assert(sc_float_to_u16fp(1.0f) == 0xffff);
}

static void test_float_to_i16fp(void) {
assert(sc_float_to_i16fp(0.0f) == 0);
assert(sc_float_to_i16fp(0.03125f) == 0x400);
assert(sc_float_to_i16fp(0.0625f) == 0x800);
assert(sc_float_to_i16fp(0.125f) == 0x1000);
assert(sc_float_to_i16fp(0.25f) == 0x2000);
assert(sc_float_to_i16fp(0.5f) == 0x4000);
assert(sc_float_to_i16fp(0.75f) == 0x6000);
assert(sc_float_to_i16fp(1.0f) == 0x7fff);

assert(sc_float_to_i16fp(-0.03125f) == -0x400);
assert(sc_float_to_i16fp(-0.0625f) == -0x800);
assert(sc_float_to_i16fp(-0.125f) == -0x1000);
assert(sc_float_to_i16fp(-0.25f) == -0x2000);
assert(sc_float_to_i16fp(-0.5f) == -0x4000);
assert(sc_float_to_i16fp(-0.75f) == -0x6000);
assert(sc_float_to_i16fp(-1.0f) == -0x8000);
}

int main(int argc, char *argv[]) {
(void) argc;
(void) argv;
Expand All @@ -90,5 +109,6 @@ int main(int argc, char *argv[]) {
test_read64be();

test_float_to_u16fp();
test_float_to_i16fp();
return 0;
}
11 changes: 11 additions & 0 deletions server/src/main/java/com/genymobile/scrcpy/Binary.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@ public static float u16FixedPointToFloat(short value) {
// 0x1p16f is 2^16 as float
return unsignedShort == 0xffff ? 1f : (unsignedShort / 0x1p16f);
}

/**
* Convert signed 16-bit fixed-point to a float between -1 and 1
*
* @param value encoded value
* @return Float value between -1 and 1
*/
public static float i16FixedPointToFloat(short value) {
// 0x1p15f is 2^15 as float
return value == 0x7fff ? 1f : (value / 0x1p15f);
}
}
22 changes: 22 additions & 0 deletions server/src/test/java/com/genymobile/scrcpy/BinaryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,26 @@ public void testU16FixedPointToFloat() {
Assert.assertEquals(0.75f, Binary.u16FixedPointToFloat((short) 0xc000), delta);
Assert.assertEquals(1.0f, Binary.u16FixedPointToFloat((short) 0xffff), delta);
}

@Test
public void testI16FixedPointToFloat() {
final float delta = 0.0f; // on these values, there MUST be no rounding error

Assert.assertEquals(0.0f, Binary.i16FixedPointToFloat((short) 0), delta);
Assert.assertEquals(0.03125f, Binary.i16FixedPointToFloat((short) 0x400), delta);
Assert.assertEquals(0.0625f, Binary.i16FixedPointToFloat((short) 0x800), delta);
Assert.assertEquals(0.125f, Binary.i16FixedPointToFloat((short) 0x1000), delta);
Assert.assertEquals(0.25f, Binary.i16FixedPointToFloat((short) 0x2000), delta);
Assert.assertEquals(0.5f, Binary.i16FixedPointToFloat((short) 0x4000), delta);
Assert.assertEquals(0.75f, Binary.i16FixedPointToFloat((short) 0x6000), delta);
Assert.assertEquals(1.0f, Binary.i16FixedPointToFloat((short) 0x7fff), delta);

Assert.assertEquals(-0.03125f, Binary.i16FixedPointToFloat((short) -0x400), delta);
Assert.assertEquals(-0.0625f, Binary.i16FixedPointToFloat((short) -0x800), delta);
Assert.assertEquals(-0.125f, Binary.i16FixedPointToFloat((short) -0x1000), delta);
Assert.assertEquals(-0.25f, Binary.i16FixedPointToFloat((short) -0x2000), delta);
Assert.assertEquals(-0.5f, Binary.i16FixedPointToFloat((short) -0x4000), delta);
Assert.assertEquals(-0.75f, Binary.i16FixedPointToFloat((short) -0x6000), delta);
Assert.assertEquals(-1.0f, Binary.i16FixedPointToFloat((short) -0x8000), delta);
}
}

0 comments on commit 1f138ae

Please sign in to comment.