HardwareHeaven.com

HardwareHeaven.com

Looking for the skin chooser?
 
 
  • Home

  • Reviews

  • Articles

  • News

  • Tools

  • GamingHeaven

  • Forums

  • Network

 

Go Back   HardwareHeaven.com > Forums > Hardware and Related Topics > kX Project Audio Driver Support Forum > Effects and the DSP


Reply
 
LinkBack Thread Tools
Old Mar 7, 2005, 07:05 PM   #1
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Dane number conversions, etc

The Dane programming guide does not give a full description of how Dane translates numbers from decimal to hexadecimal. I did some basic tests in Dane trying to verify how it handles the translations and the following seems to be how it works.

Positive Fractional numbers (0 < number <= 1) works as listed in programmers guide.
i.e.
Hex = Dec * (2^31-1)

The guide however does not mention negative numbers.
It seems that negative fractional numbers (-1 <= number < 0) are represented as follows:
hex = ~( abs( (Dec) * (2^31-1) ) )
Where "~" inverses all the bits, and abs is the absolute value function.

Integer numbers however work differently.
Positive integers take their normal representation in hex (with the exception of 1 which gets translated to fractional 1).
i.e.
3 decimal = 00000003 hex

Negative integers (with the exception of -1 which gets translated to fractional -1) on the other hand seem to be represented as follows:
hex = ~( abs(Dec) ) + 1

Rounding of floating point numbers that are greater than 1 or less than -1 seem to work as follows. (you can't use floating point numbers like this, but the .da will still compile, as Dane will round the numbers and give you a warning that the numbers were truncated). The numbers are rounded to the nearest integer (based on the 1st decimal place only), and then represented in hex using the above integer representations (this time including 1 and -1. 1 and -1 are treated as integers and not fractional numbers after rounding (i.e. 1.1 decimal gets rounded to 1 decimal and translated to 00000001 hex))


I thought I would post this info, so that other people do not have to try and figure it out themselves. Can anyone verify that the above is accurate for me? Maybe I will make a small utility to convert the numbers for anyone that wants to use it, and thus not have to constantly do it manually with a calculator, which can be a pain, especially with the negative numbers.



Also, I did not find much information on kxctrl anywhere, but have found it useful (from just playing around with it to try and figure out what it does) in troubleshooting plugins, and for simple testing to verify how some things work in Dane, etc. If you run kxctrl with the -gui switch, you can use the "mp" command to view all of the loaded plugins. You can then use "mp" and the number of the plugin (as listed from the "mp" command, i.e. "mp 2") to view the registers, and thus verify the values of those registers. Of course it is only a snapshot of the registers (some of which might be changing 48000 times a second), but it is useful to check constant values, and check for saturations, and as I mentioned previously, for simple testing to verify how something might work in Dane, etc. I also found it useful the first time I tried to update the registers dynamically from C++, as I could set a breakpoint in C++ after updating the register, and then verify the value of that register using the "mp" command, etc, and thus verify that I was doing it right. Of course the registers values are in hexadecimal, and thus you need to know all the details of how to translate the values back and forth between decimal and hexadecimal (including negative numbers) and thus another reason for the first part of this post. Anyway, I thought I would include this info as well, so that maybe others who have not figured this out yet themselves, will not have to figure it out themselves.

Hope this is useful.
-Russ

Last edited by Russ; Mar 11, 2005 at 11:09 PM.
Russ is offline   Reply With Quote


Old Mar 7, 2005, 09:48 PM   #2
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Here is the info on converting from hexadecimal back to decimal. It is a little trickier becuase the same number in hex, can be used to represent an integer or a fractional number, so you will have to do which ever calculation fits the context.

First you need to check the sign bit. One way to do this, is to AND the number with 80000000 hex.
A result of 0 means that the numbers is positive, otherwise (result is 80000000), the number is negative.

Then you need to decide on the context (whether the number should be an integer or fractional number).

For a positive fractional number, you do as stated in the Dane programming guide.
Dec = Hex / (2^31+1)

For a negative fractional number:
Dec = -1 * ( ~(Hex) / (2^31+1) )
Again "~" is the one's compliment operator (invert all the bits in the number).

For a positive integer number, convert directly to decimal (i.e. just change calculator from hex mode to decimal mode).

For a negative integer:
Dec = -1 * ( ~(Hex) + 1 )

I think that should cover all the number conversions.
-Russ

BTW: With the Windows calculator (in Scientific mode) you can use the "Not" key to invert the bits of a number (where you see "~" above, but make sure if you are in any mode other than decimal, that the display size is set to Dword).

Last edited by Russ; Mar 7, 2005 at 10:19 PM.
Russ is offline   Reply With Quote
Old Mar 11, 2005, 05:47 PM   #3
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

I thought I would add the steps to do all the conversions using the Windows Calculator for clarity.

First some additional info:
Calculator should be in Scientific Mode (View -> Scientific)
Digit Grouping can be useful for checking the Sign bit (View -> Digit Grouping)
Display Size should be Dword (applicable to Hex, Oct, and Bin modes)

The sign bit is the 32nd bit (read from right to left in Bin mode)
Leading 0's are not shown in Bin mode, therefore you will either see a 1 (negative number) or nothing (positive number) at the location of the Sign bit.
This is where Digit Grouping can be useful, as the bits will be in groups of 4 (making it easier to count the number of bits to check the Sign bit).
i.e.
1100 0000 0000 0000 0000 0000 0000 0000
^
The Sign bit.

The conversions:

Decimal Integers to Hexadecimal:
  • Enter the number in Dec mode (without the sign, i.e. absolute value of the number).
  • If the number is positive, change to Hex mode for the result.
  • If the number is negative, change to Hex mode, click the "Not" key, and then add 1 for the result. (again, make sure display size is Dword before using the "Not" function, or the result will be wrong!)
Hexadecimal Integers to Decimal:
  • Enter the number in Hex mode.
  • Check the Sign bit.
  • If the number is positive, change to Dec mode for the result.
  • If the number is negative, click the "Not" key, add 1, change to Dec mode, and multiply by -1 for the result.
Fractional Decimal numbers to Hexadecimal:
  • Enter the number in Dec mode (without the sign, i.e. absolute value of the number).
  • If the number is positive, click on the "*" key, then the "(" key, then the "2" key, then the "x^y" key, then the "3" key, then the "1" key, then the "-" key, then the "1" key, then the ")" key, then "=" key, and then change to Hex mode for the result. (I wrote it out the long way to emphasize the use of the parenthesis in the formula: Hex = Dec * (2^31-1) )
  • If the number is negative, repeat the exact same steps as above, and after changing to Hex mode, click the "Not" key for the result.
Fractional Hexadecimal numbers to Decimal:
  • Enter the number in Hex mode.
  • Check the Sign bit.
  • If the number is positive, change to Dec mode, then click the "/" key, then the "(" key, then the "2" key, then the "x^y" key, then the "3" key, then the "1" key, then the "+" key, then the "1" key, then the ")" key, and then the "=" key for the result. (again written out the long way to emphasize the parenthesis in the formula: Dec = Hex / (2^31+1) ).
  • If the number is negative, first click the "Not" key, then repeat exact same steps as above, and then mutiply by -1 for the result.
Hopefully this helps explain the formulas given previously, and hopefully I didn't make any typos. This info isn't necessary to program plugins in Dane, but it is useful for checking results, etc.

-Russ
Russ is offline   Reply With Quote
Old Mar 11, 2005, 05:58 PM   #4
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

If you like you could make it a html and I could put it in the guide.
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 11, 2005, 06:11 PM   #5
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Ok, I will do that. I was considering asking about that, but I was hoping someone could verify my conclusions first. Addionally I was trying to determine the precision used. For example, I noticed Dane will recognize up to 20 decimal places (but not accuratley), and was trying to figure out how it handled numbers such as these (does it round it off at same place, if so where?, etc, so far I haven't been able to figure it out for sure).

-Russ
Russ is offline   Reply With Quote
Old Mar 11, 2005, 08:38 PM   #6
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Here is the test I was trying to use to determine the accuracy.
I converted 0x1 to decimal using Windows calculator.
0x2 = 0.000000000931322574615478515625 (this is exact)

I then tested this number in Dane and it translared as 0x1 (which is incorrect, although was expected, as a truncation at any of the decimal places would have a semi-accurate result of 0x1).

I then started from the last decimal place and started changing numbers trying to determine how many decimal places Dane used for it's translation, and to try and determine what is does with these numbers before translating (rounding, trucation, etc).

The first place I noticed a difference was at the 18th decimal place.
0.000000000931322574615478515625 (this is exact number again)
0.000000000931322574 (Dane translated it as 0x1 - semi-accurate)
0.000000000931322575 (Dane translated it as 0x1 - not accurate)
0.000000000931322576 (Dane translated it as 0x2 - semi-accurate)

The above result was confusing... If it was rounding off using the 18th decimal place, then the last 2 numbers should have had the same result, and if it was truncating the 18th decimal place then all 3 numbers should have had same result?

As it was recognizing a difference in the 18th decimal place, I decided to work with second number (as it was the changing point), and see if it would recognize further decimal places.
0.000000000931322575 (starting number)
0.0000000009313225754 (Dane translated it as 0x1 - not accurate but consistant if it was rounding off based on this decimal place)
0.0000000009313225755 (Dane translated it as 0x2 - semi-accurate and consistant if it was rounding off based on this decimal place)
0.00000000093132257504 (Dane translated it as 0x1 - not accurate and not consitant)
0.00000000093132257505 (Dane translated it as 0x2 - not accurate and not consitant)

I got as far as 22 decimal places:
0.0000000009313225750491 (translated to 0x1)
0.0000000009313225750492 (translated to 0x2)
At this point, I couldn't make any sense of the results (i.e. couldn't find any logic to why the results were different, and gave up. It may even recognize further decimal places).

When I say the result is semi-accuate, I mean that the result is correct, but it cannot be translated back to decimal accuratley. For this reason it is not important when using Dane (I usually only use 9 decimal places for entering numbers as Eyagos told me (in another thread) that DSP uses only 9 digits), but in trying to make a utility to mimic the translation that Dane uses I was trying to determine what it was doing, and obviously I have not figured it out as of yet. Anyway, that is what I meant when I mentioned precision above.
Russ is offline   Reply With Quote
Old Mar 11, 2005, 10:30 PM   #7
DriverHeaven Newbie
 
Join Date: Nov 2004
Posts: 7
Rep Power: 0
jumperX is on a distinguished road

hello.

Russ, could you please clarify one thing i can't understand:

in you first post you wrote:
"Fractional numbers (0 < number <= 1) works as listed in programmers guide. i.e.
Hex = Dec * (2^31-1)"

in the second ost you state that
"for a positive fractional number, you do as stated in the Dane programming guide.
Dec = Hex / (2^31+1)"

finally what scale is correct: '2^31-1' or '2^31+1' ?

Later you confused me even more:
"0x2 = 0.000000000931322574615478515625 (this is exact)"
But "0.000000000931322574615478515625 = 2 / (2^31+0)"

where i'm wrong?
jumperX is offline   Reply With Quote
Old Mar 11, 2005, 10:46 PM   #8
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Hi, that first line should read "Positive fractional numbers".

As for the scale, both are correct, depending on whether you are converting to hex or from hex. (One is the inverse of the other)

As for the last part, that is my fault, I apologize. I actually did not use the Windows Calculator for that. I used the PowerToy Calculator (because I can enter in Functions and thus do the calculations quicker), with the precision set to 32 bits, and that is why you are getting different results (different precision). That might also be why I was having problems figuring out Dane's precision. I will have to try some more tests using a higher precision setting.

Thanks for pointing that out.
-Russ

Last edited by Russ; Mar 11, 2005 at 11:22 PM.
Russ is offline   Reply With Quote
Old Mar 11, 2005, 11:04 PM   #9
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Another thing that might be confusing you, is that the conversions are not exact. This is because 1 cannot be represented exactly using this method.
i.e.
1 = 0x7FFFFFFF
0x7FFFFFFF = 0.99999999906867742581820235316725 = 0.999999999 (9 digits)

0.5 = 0x3FFFFFFF
0x3FFFFFFF = 0.49999999930150806936365176487544 = 0.499999999 (9 digits)

-Russ

Last edited by Russ; Mar 11, 2005 at 11:26 PM.
Russ is offline   Reply With Quote
Old Mar 11, 2005, 11:33 PM   #10
DriverHeaven Newbie
 
Join Date: Nov 2004
Posts: 7
Rep Power: 0
jumperX is on a distinguished road

>As for the scale, both are correct, depending on whether you are converting to hex or from hex.

I cannot agree. I think the scale should not depend on the direction of conversion.
if it was like this
then
{
H = D * (2^31-1);
D = H / (2^31+1);
}
causes
D = (D * (2^31-1)) / (2^31+1);
and then we get
(2^31+1) = (2^31-1);
- impossible.

------------------

I assume that Dane uses "(2^31-1)" for positive numbers and "(2^31+0)" for negative.

Then it becomes easy to explain inconsistency you mentioned above:

"0.00000000093132257504 (Dane translated it as 0x1 - not accurate and not consitant)
0.00000000093132257505 (Dane translated it as 0x2 - not accurate and not consitant)"

0.00000000093132257504 * (2^31-1) = 1.99999999998033; (Dane thinks it's 1)
0.00000000093132257505 * (2^31-1) = 2.00000000000181; (Dane thinks it's 2)

So it looks like it just uses truncation instead of more correct rounding.

-------------------
"1 = 0x7FFFFFFF
0x7FFFFFFF = 0.99999999906867742581820235316725"

Yep, that makes sense.... Otherwise both +1.0 and -1.0 must be represented as 0x80000000
(it seems to be a compromise for 32-bit fractionals)
jumperX is offline   Reply With Quote
Old Mar 11, 2005, 11:54 PM   #11
DriverHeaven Newbie
 
Join Date: Nov 2004
Posts: 7
Rep Power: 0
jumperX is on a distinguished road

btw. I think we can ask Eugene to post here the internal Dane's source code it uses for numeric conversions
(under persmission of Max probably).

So anyone can see it and then correct/improve it if there's something really wrong.
Is this possible? (finally, why should we conjecture?)
jumperX is offline   Reply With Quote
Old Mar 12, 2005, 12:25 AM   #12
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Yeah, I know that it trucates the decimal result, when it converts to hex, I was trying to find out what it did with the original decimal number before the conversion (where the rounding or truncation point was).

I figured out what my problem was with the PowerToy calculator. Something happened (not sure what), that changed the function definitions that I was using, so it was doing 2^31, instead of 2^31-1, and thats why my calculations were wrong as you noticed.
Quote:
But "0.000000000931322574615478515625 = 2 / (2^31+0)"
Using the correct functions, I am sure I will not have a problem figuring it out.

Quote:
I assume that Dane uses "(2^31-1)" for positive numbers and "(2^31+0)" for negative
Well it stores the numbers (the fractional number's anyway) in 2's Compliment form (integers in 1's compliment form, which the exception of "fractional 1"). Although you could convert a negative decimal number to hex using (2^31+0) using the Windows calculator, it would be hard to go back to the original number using just that formula.
i.e.
-0.4 * 2^31 = -858993459.2
The Windows calculator uses the sign when it converts it to hex, and shows the correct result of 0xCCCCCCCD.
But when you try to convert it back, the calculator does not use the sign bit, and converts it back as 3435973837, and then doing the division (3435973837 / 2^31), results in 1.6000000000931322574615478515625.
Russ is offline   Reply With Quote
Old Mar 12, 2005, 01:32 AM   #13
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Quote:
Originally Posted by jumperX
btw. I think we can ask Eugene to post here the internal Dane's source code it uses for numeric conversions
(under persmission of Max probably).

So anyone can see it and then correct/improve it if there's something really wrong.
Is this possible? (finally, why should we conjecture?)
I don't know, maybe.
I am pretty sure I have the formulas correct (and Dane doesn't actually convert the values back to decimal, so it wouldn't help with that). I did make a utility to test with using those formulas and it was producing the same results as Dane (I didn't test extensively as of yet). I figured Dane just stored the values as doubles (in C++) and did the calculations using doubles (so my utility using doubles would end up with the same results). Then I noticed that Dane rounded floating point values, using the 1st decimal place only (which C++ doesn't do, C++, truncates when converting to integer), so I thought I should look into how Dane handled fractional numbers, to see if it did anything different, and thus my testing (which turned out to be flawed). Anyway, when I have a chance, I will redo my tests using the correct functions in PowerToy calculator.

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 03:42 AM   #14
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Quote:
I cannot agree. I think the scale should not depend on the direction of conversion.
if it was like this
then
{
H = D * (2^31-1);
D = H / (2^31+1);
}
causes
D = (D * (2^31-1)) / (2^31+1);
and then we get
(2^31+1) = (2^31-1);
- impossible.
You bring up and interesting point. I am not really sure about that. Those formulas are taken from the as10k1 Manual. I am not sure if those are accurate or not, I figured that they (the emu10k1 project people) did all the research and came up with those numbers, so I wouldn't say they were wrong (or that Dane was doing it wrong) without doing a lot of reaserch (reading all the available information on the emu10k1 processor, looking at the patents, looking at the open source driver source code, etc) and testing. But looking at some of the available information on other DSP processors (where information is abundant), it seems common practice to do it differently (although I have only looked over some of that info briefly). i.e. using 10^31 (as opposed to 10^31+1 or 10^31-1) for 32 bit processor giving the range of (0x80000000) -1 to 0.9999999953 (0x7FFFFFFF). I am not sure what to think about that. The only place it would make a difference is when entering decimal numbers in Dane, and letting Dane translate them. I suppose it could be tested by entering the numbers in hex using whatever formula that you think is right, do the calculations based on 2's compliment arithmetic, and examine the registers to see if the result is the same as what you calcualted, etc (the processor is going to perform the calculations itself, so...). It is an interesting point, but at the moment I am just going by the info in the as10k1 manual, and examining the numbers as Dane translates them to figure out the rest.

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 04:58 AM   #15
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

I did a very quick test using both methods to compute 0.5 * 0.5:
0.5 * 0.5 = 0.25
0.5 ^ (2^31-1) = 0x3FFFFFFF
0.5 ^ (2^31) = 0x40000000

------------------
static a=0.5
static b=0x40000000
static c=0
static d=0

macs c, 0, a, a
macs d, 0, b, b
------------------


Here are the results:
; Registers
[8000]: 'a' p=3fffffff; translated: 100; current=3fffffff
[8001]: 'b' p=40000000; translated: 101; current=40000000
[8002]: 'c' p=0; translated: 102; current=1fffffff
[8003]: 'd' p=0; translated: 109; current=20000000

0x1FFFFFFF / (2^31+1) = 0.249999999 (0.24999999941792339113637647072953)
0x20000000 / (2^31) = 0.25 (this is exact)

-Russ

Anyway, that is all for now. I'll look at it more tomorrow...
Russ is offline   Reply With Quote
Old Mar 12, 2005, 08:14 AM   #16
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

For 0x7fffffff the correct formula is:
0x7fffffff/(2^31-1)=1
For other positive fractional values:
0x20000000/2^31 = 0.25
0x40000000/2^31 = 0.5
etc.

The conversion should be done after the hex value is converted to decimal (Powertoys calc does this automatically, windows default calc doesn't)
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 12, 2005, 04:07 PM   #17
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Quote:
The conversion should be done after the hex value is converted to decimal
Yeah, that is another reason why I added the steps to do the conversion using the Windows calc. You will notice that in that post I listed the steps along the lines of, Enter number in hex mode, check sign bit, change to dec mode ... etc.

Quote:
Originally Posted by Tiger M
For 0x7fffffff the correct formula is:
0x7fffffff/(2^31-1)=1
For other positive fractional values:
0x20000000/2^31 = 0.25
0x40000000/2^31 = 0.5
etc.
I am guessing it is an approximation of 1, but 1 does not really exist in this sense. (i.e. range is -1 to 0.9999999953, where -1 is included, but 1 is not (top end is one LSB less than 1)). So it would need to make a special case for 1 (but only 1). Dane converts all decimal numbers (fractional numbers) to hex using 2^31-1 (not just 1), and I am not sure that it should. 0x40000000 and 0x3FFFFFFF cannot both be 0.5 (granted the numbers are close, 1 LSB apart, but they are not equal).

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 05:15 PM   #18
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

BTW: As it turns out, negative fractional numbers on the other hand are being represented correctly, but I think that is just coincendental (although I cannot be sure how Dane is doing the conversion (whether it is using 2^31 or 2^31-1 for negatives).
i.e. -0.5
-0.5 * 2^31 = -1073741824
Then stored in 2's Compliment form: ~( abs(number)) + 1, for a negative number:
abs(-1073741824) = 1073741824 = 1000000000000000000000000000000 binary
~(1000000000000000000000000000000) = 10111111111111111111111111111111
10111111111111111111111111111111 + 1 = 11000000000000000000000000000000
11000000000000000000000000000000 = 0xC0000000

You can get the same result using (2^32-1) and storing number in 1's compliment form (the formula I showed in my first post in this thread), but doing it the above way makes more sense.

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 05:23 PM   #19
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

Here's how double is converted to dword in the SDK:
Code:
 inline dword _dbl_to_dspword(double x)
 {
	  double y = (x * 2147483647.5) - 0.25;
	  y += 6755399441055744.0;					  
	  return ((dword*) &y)[0];
 }
I'm not shure what that last line does, probably some bitwise operation.
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 12, 2005, 05:41 PM   #20
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

You will notice that fractional numbers (including -1, excluding 1) can be represented exactly using this method:

2's Compliment:
A Positive Number is represented as a simple unsigned binary.
A Negative Number
is represented as the binary number that when added to a positive number of the same magnitude equals zero. To form a negative number:
  • first compliment each bit of the positive number (i.e., change all of the 1's to 0's, and vice versa; this is called the "1's compliment"),
  • then add 1.

-1 * 2^31 = -2147483648 = ~(abs(-2147483648)) + 1 = 0x80000000
0x80000000 = ~(
0x80000000) + 1 = 2147483648 / 2^31 = 1 * -1 = -1

-.5 * 2^31 = -1073741824 = ~(abs(-1073741824)) + 1 = 0xC0000000
0xC0000000 = ~(0xC0000000) + 1 = 1073741824 / 2^31 = .5 * -1 = -.5

.5 * 2^31 = 1073741824 = 0x40000000
0x40000000 =
1073741824 / 2^31 = .5

This makes all the conversions accurate both ways (except 1 as it cannot be represented exactly, and thus we have to choose the closest representation possible for it: 0x7FFFFFFF).

-Russ

Last edited by Russ; Mar 12, 2005 at 05:48 PM.
Russ is offline   Reply With Quote
Old Mar 12, 2005, 06:09 PM   #21
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Quote:
Originally Posted by Tiger M
Here's how double is converted to dword in the SDK:
Code:
 inline dword _dbl_to_dspword(double x)
 {
	  double y = (x * 2147483647.5) - 0.25;
	 y += 6755399441055744.0;					 
	  return ((dword*) &y)[0];
 }
I'm not shure what that last line does, probably some bitwise operation.
Yeah, I am not sure what that line is doing either, I agree that it is probably some sort of shift. This result is the low 32 bits. This function is producing the same results (which again seem to be off by 1 LSB)..
i.e. 0.5 = 0x3FFFFFFF
Using the PowerToy Caculator with the function:
test(x)=((x*2147483647.5) - 0.25) + 6755399441055744.0
test(0.5) = 6755400514797567.5 = 0x1800003FFFFFFF.8

-Russ

Last edited by Russ; Mar 12, 2005 at 06:17 PM. Reason: should have read low 32 bits rahther than 16
Russ is offline   Reply With Quote
Old Mar 12, 2005, 06:59 PM   #22
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

I am not sure why that function was chosen (maybe it is what Creative uses?). Maybe it is to center the values more between -1 and 1. In any case, it makes the conversions confusing.

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 08:37 PM   #23
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

I think that the last line is the important one. I'm shure that the values are converted the way they should be. The values passed from c are always accurate - for instance if you test set_dsp_register("register", _dbl_to_dspword(1.0)); the value will always be 0x7fffffff and don't forget that for each control register in dane kx creates a fader, play around with it and you'll see that it is always accurate (move the fader and look at the dump, not the source).
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 12, 2005, 08:50 PM   #24
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Quote:
Originally Posted by Tiger M
for instance if you test set_dsp_register("register", _dbl_to_dspword(1.0)); the value will always be 0x7fffffff
1 isn't good to test with, as 1 is the special case. It the values betwen 0 and 1 that I am wondering about. (i.e. 0.5 = 0x3FFFFFFF as opposed to 0x40000000).
Try testing set_dsp_register("register", _dbl_to_dspword(0.5)); and see what the result is (0x3FFFFFFF or 0x40000000).

Currently my C++ is not setup to work with the Dane SDK, so I will have add all the libraries and stuff back in to test (I am using .NET, so if I want to do something that doesn't involve the kX SDK, I have to remove the VS 6.0 MFC files, etc).

I will check it out when I have a chance.

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 08:55 PM   #25
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

As I said in my previous post you can check the faders created for 'control' registers in dane, I'm shure the conversion formula is the same - the 'vol' effect for instance. Set it to 50% and you'll se that it has set the control register to 0x40000000.
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 12, 2005, 08:58 PM   #26
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Ahh, that's interesting because Dane does not do that when it does the conversion. I will check that out.

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 09:05 PM   #27
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

What do you mean that it does not do that, I don't see a reason why Eugene would use a different formula for dane and for the sdk.
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 12, 2005, 09:08 PM   #28
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 4,984
Rep Power: 44
Russ is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the roughRuss is a jewel in the rough

Type static a = 0.5 in Dane, save it, and then look at the Dump.
It stores 0.5 as 0x3FFFFFFF

-Russ
Russ is offline   Reply With Quote
Old Mar 12, 2005, 09:09 PM   #29
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

I just checked in the sdk and he uses the same formula, so again - the secret must be that last line of code in _dbl_to_dspword, I'll have to check my C++ books to see what's that line actually doing, I have forgotten many things since I read them, things that I have never used...
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Old Mar 12, 2005, 09:12 PM   #30
kX user
 
Join Date: Apr 2004
Posts: 851
Rep Power: 0
Tiger M is on a distinguished road

Quote:
Originally Posted by Russ
Type static a = 0.5 in Dane, save it, and then look at the Dump.
It stores 0.5 as 0x3FFFFFFF

-Russ
Strange, really... too bad kX isn't open source, so we could see what's exactly dane doing. In the dane header the formula used is the same
__________________
Miss you, Steve...
Tiger M is offline   Reply With Quote
Reply

Bookmarks

Thread Tools