News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

More fpu questions

Started by normcook, August 09, 2009, 06:06:10 PM

Previous topic - Next topic

normcook

Thanks to expert help here I learned how to interpret the
value of a returned float from a function.

Now I need to send a float to a function.

local arg1:DWORD
local arg2:DWORD
local result:FLOAT           ;REAL10, REAL8, REAL4 ??             

mov arg1,50        ;slider pos (slider min=0, max=100, using 50 as test, trying to get 0.5
mov arg2,100 
fild arg1
fidiv arg2
fistp result
;Bass expects a single                     here, I want it to be 0.5
invoke BASS_SetVolume, result       ;but its always zero, i. e. turns the sound off

dedndave

to use fidiv, you have to divide by a real
also, multiplying is faster than dividing
when you use fild, the value is converted to an extended real
so, i would define a real10 constant of 0.01

Constant01 real10 1.0e-2

then,

        finit
        fld real10 ptr Constant01
        fild dword ptr arg1
        fmul    st,st(1)
        fstp real4 ptr result
        ffree   st

that would...
initialize the fpu, setting the resolution to extended real
load the constant 0.01 in real10 format
load the integer 50 (arg1), converting it to real10
multiply st x st(1)
store and pop the result as a real4
free the st register

of course, you don't have to finit every time, but it is there to show it needs to be done
windows gives you the fpu with 53 bit precision (for some stupid reason) - you want to run in 64-bit precision

MichaelW

AFAIK for BASS all of the floating-point values are REAL4, with only a 24-bit precision, so I see little reason to slow the FPU down by pushing the internal precision from 53 bits to 64 bits.
eschew obfuscation

dedndave

64 bits is it's native "element" - the fpu was designed around extended reals internally
it's even possible that 53 bits is slower
which ever is fastest, the difference is going to be minute
have a look at these timings.....

http://www.masm32.com/board/index.php?topic=11999.msg91486#msg91486

can't get much faster than that with the fpu

JayPee

Hi

This is a proc I use

SetVolume Proc

LOCAL Var1 :DWORD
LOCAL Volume :DWORD

;NewPos is a Global Variable

Mov Var1,100
Finit ; default instruction if the fpu stack isn't clean
Fild NewPos ; load source integer
Fild Var1 ; load 100
Fdiv ; divide source by 100
Fstp Volume ; store result in variable

Invoke BASS_ChannelSetAttribute,Chan,BASS_ATTRIB_VOL,Volume
invoke SendDlgItemMessage,hWnd,1002,TBM_SETPOS,1,NewPos
; invoke SendDlgItemMessage,hWnd,1004,UDM_SETPOS,1,NewPos
ret
SetVolume endp


I'm sure this could be improved however it works fine for me

Cheers
John
Greetings From New Zealand
(Land of the Long White Cloud)

normcook

Thanks to all.  Starting to get a handle on it.

raymond

normcook

Your initial code was excellent except for one detail. The fistp instruction stores the result as a rounded integer. In your case, it would be either a 0 (<0.5) or a 1 (>=0.5). However, as a float, that always gets interpreted as 0.

Simply replace that instruction with fstp which will store the result as a float and your code would work. No need to finit if you don't require anything better than single precision.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

GregL

Quote from: dedndaveto use fidiv, you have to divide by a real

FIDIV   Divide ST(0) by an integer located in memory and store the result in ST(0)


dedndave

oops - lol
my bad - was thinking fdiv

GregL

I just didn't want normcook to be confused.


JayPee

Hi Normcook

I found I had to use a DWORD variable for RESULT as the BASS_ChannelSetAttribute,Chan,BASS_ATTRIB_VOL seems to only accept a DWORD and not a FLOAT

Regards
John
Greetings From New Zealand
(Land of the Long White Cloud)

GregL

normcook,

I wanted to point out FLOAT is not a MASM directive, REAL4 is.

From windows.inc
FLOAT typedef REAL4

You should use REAL4 instead of FLOAT.

And as you found, DWORD will work too, it's the same size as a REAL4 or single.


raymond

QuoteFrom windows.inc
FLOAT typedef REAL4

He should thus be OK if he includes windows.inc in his header.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

dedndave

this code doesn't work ?
i get a real4 of 0.5 for result

        local   arg1:DWORD
        local   arg2:DWORD
        local   result:REAL4   ;as per MichaelW

        mov     arg1,50
        mov     arg2,100
        fild    arg1
        fidiv   arg2
        fstp    result         ;as per Ray

        invoke  BASS_SetVolume,result

JayPee

Dave

Your code is correct up to the invoke BASS_SetVolume

BASS.inc does not accept real4 or any floats

The correct syntax for adjusting the channel volume is

Invoke BASS_ChannelSetAttribute,Chan,BASS_ATTRIB_VOL,NewLevel
where NewLevel is a DWORD that holds the float value

Cheers
John
Greetings From New Zealand
(Land of the Long White Cloud)