Performance: sail to fill and clipping to range

I am doing audio processing using float. The result should be converted back to PCM samples, and I noticed that casting from float to int is surprisingly expensive. Also, the disappointment is that I need to copy the result into a short range (from -32768 to 32767). Although I usually assumed that this could be guaranteed by simply resetting the float to a short one, this will not abate in Java, since at the bytecode level it leads to F2I, followed by I2S. Therefore, instead of simple:

int sample = (short) flotVal;

I needed to resort to this ugly sequence:

int sample = (int) floatVal;
if (sample > 32767) {
    sample = 32767;
} else if (sample < -32768) {
    sample = -32768;
}

Is there a faster way to do this?

(about 6% of the total execution time seems to be spent on casting, and 6% seems to be not so much at first glance, it is amazing when I consider that the processing part includes a good piece of matrix multiplications and IDCT)

  • The EDITED throw / clipping code above (not surprisingly) in the body of the loop, which reads the float values ​​from float [] and puts them in byte []. I have a test suite that measures total execution time in several test cases (processing about 200 MB of source audio data). 6% were inferred from the difference in runtime when the translation destination "int sample = (int) floatVal" was replaced by the destination of the loop index for the sample.

  • EDIT @leopoldkot: Java, ( - F2I, I2S). , , Java - F2S, , , ( 68K, "fmove.w FP0, D0" , ).

+3
5

, . . , . ( )

if (sample + 0x7fff8000 < 0x7fff0000)
    sample = sample < 0 ? -32768 : 32767;
+2

int , , , . . () -40000 25536, -32768, .

, , , , -. , JIT, ( ) , .

, .

+1

float to int convertions - , x86, x87 (), . , SSE x87, , java. , JVM x86_64?

0

This is Python, but it is easy to convert. I don’t know how expensive floating point operations are, but if you can store them in integer registers, you may have some momentum; this suggests that you can reinterpret the IEEE754 bits as int. (This is what makes my bad name float2hex).

import struct

def float2hex(v):
    s = struct.pack('f', v)
    h = struct.unpack('I', s)[0]
    return h

def ToInt(f):
    h = float2hex(f)
    s = h >> 31
    exp = h >> 23 & 0xFF
    mantissa = h & 0x7FFFFF
    exp = exp - 126
    if exp >= 16:
        if s:
            v = -32768
        else:
            v = 32767
    elif exp < 0:
        v = 0
    else:
        v = mantissa | (1 << 23)
        exp -= 24
        if exp > 0:
            v = v << exp
        elif exp < 0:
            v = v >> -exp

        if s:
            v = -v

    print v

This fork may kill you, but maybe it is still something useful? This rounds to zero.

0
source

int sample = ((int) floatval) and 0xffff;

-1
source

Source: https://habr.com/ru/post/1747401/


All Articles