Hi Jing,

I have finished most of the coding translation work of CELT, and now I am

testing several modules to make sure it works fine.

Good news

My result is worse than the result of the c code, whose snr is generally

around 140dB. And from the above results we can see, the longer the nfft is,

the worse snr it brings. So I guess this is caused by the error accumulate.

But my result is still OK, because from the author's mdct-test.c, the >60dB

result is correct.

Of course, being above the 'poor-ness' threshold is great, but it

would be even better if we can find out where this discrepancy comes

from !

I use float type during the algorithm, just exactly like the c. And as far

as I know, the format of float type in c and java is the same(IEEE 754). So

Technically speaking, IEEE 754 is also a container, somewhat like AVI

files can contain anything from raw images to xvid bitstream.

So IEEE 754 defines several formats, the most famous two being

'simple' and 'double' precision. They are respectively 32 and 64 bits

wide. In C language, float is IEEE 754's simple precision, and double

is IEEE 754's double precision. This can be easily checked, and it is

the case at least on my machines. For Java, as far as I know, it is

the same, as suggested here

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html

I don't understand why they have different errors. I remember both Lubo and

Jean metioned the floating point precition problem.

I wish I hadn't, because now that I have investigated the topic, I

feel pretty upset

Now I don't know how badly the float precision errors affect the codec.

Later I'll see.

So, why do the computation results differ ?! There is no easy answer,

however here is a quote :

"Java’s floating-point expression-evaluation turns into Numerical Junk".

Contrarily to popular (and Emil's) belief, I did not say that, William

Kahan did in [1]. And he's much more commendable than me. I suggest

that you do not read it now though, because it is 81 pages, but you

can put it on your bedside table....

And now it's time to talk about Java and IEEE-754 again. In the early

days, Java was going to take over the universe, and one of the

necessary things to achieve was reproducible results. This sounds fair

for almost all daily computations except floating points. Why ?

Because floating point units differ from one hardware to another. And

even though Apple has come back from the dark side of the chip and

joined the Intel/AMD/others/x86 conspiracy, there are still some

machines out there with FPU that do not run like Intel's x87. Just

think about all those arm cores for example.

Here comes IEEE-754, it is a standard after all. So we can safely say

that Java gives reproducible results on all standard conformant

systems. Unfortunately, as I told you earlier, there are several bit

types defined in IEEE-754 standards, one of them being 'long double'

which is at least 80 bits.

And this type is used internally by the x87 FPU to do *ANY* floating

point calculation. The result is then rounded to whatever bit format

you were asking for, by the compiler (see [2]).

But this behavior is not common place (although not a standard

violation either), so a result on a x86 differs from a result on, say,

SPARC, Alpha, MIPS, PPC, etc... What a mess. Fortunately you can issue

an assembly command to constrain the hardware to 'internal double'

precision only, instead of long double.

As a side note, [2] suggests that BSD systems activate this behavior

by default so I would be interested if someone with a BSD box

(possibly not a virtual one) could fetch libcelt and run the mdct-test

(from tests/ directory) for me. I will attach my results below for

comparison. Now that I think of it, darwin systems migh work like

BSDs, or they might not. I attached the results from a friend's

intel-mac, just for fun.

So, what should we do now ? My first suggestion is to convert

everything to double, to see if you get better results (this is

suggested by [1] because all-float calculations are rounded to float

thus losing precision and accuracy). This will have NO impact on the

processing because most of the hardware do the internal computations

using double anyway. I would do it but I seem to be missing the Config

class from your archive and am too lazy to investigate it, hehehe.

Sorry for that long email, and good luck with that FPU mess. By the

way, this is just an explanation attempt, which means I can be wrong,

or most likely just party true.

Jean

PS: java standard might have evolved and support long double, but I am

not aware of this fact, someone correct me if I'm wrong.

References :

[1] http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf

[2] http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html

Sample results for mdct-test from libcelt's mdct-test.c (dunno the

libcelt version, apparently fetched on April 9th)

nfft=32 inverse=0,snr = 145.219638

nfft=32 inverse=1,snr = 144.590286

nfft=256 inverse=0,snr = 141.993721

nfft=256 inverse=1,snr = 142.784441

nfft=512 inverse=0,snr = 141.123660

nfft=512 inverse=1,snr = 141.128761

nfft=40 inverse=0,snr = 143.958780

nfft=40 inverse=1,snr = 141.627641

nfft=56 inverse=0,snr = 142.992619

nfft=56 inverse=1,snr = 145.087616

nfft=120 inverse=0,snr = 140.111970

nfft=120 inverse=1,snr = 142.695879

nfft=240 inverse=0,snr = 139.789205

nfft=240 inverse=1,snr = 141.727412

nfft=480 inverse=0,snr = 140.229189

nfft=480 inverse=1,snr = 142.468349

with [2]'s -msse2 -mfpmath=sse compilation flags on same hardware

nfft=32 inverse=0,snr = 142.311990

nfft=32 inverse=1,snr = 144.019064

nfft=256 inverse=0,snr = 139.444941

nfft=256 inverse=1,snr = 138.041439

nfft=512 inverse=0,snr = 139.488676

nfft=512 inverse=1,snr = 139.153238

nfft=40 inverse=0,snr = 141.065740

nfft=40 inverse=1,snr = 139.050118

nfft=56 inverse=0,snr = 137.236628

nfft=56 inverse=1,snr = 141.151461

nfft=120 inverse=0,snr = 137.361481

nfft=120 inverse=1,snr = 140.720815

nfft=240 inverse=0,snr = 138.391179

nfft=240 inverse=1,snr = 139.046024

nfft=480 inverse=0,snr = 137.307414

nfft=480 inverse=1,snr = 138.920736

Processor info, model name :Intel(R) Core(TM)2 Duo CPU E4700 @ 2.60GHz

OS Info: Debian Linux, kernel 2.6.24, glibc 2.3.6, gcc 4.3.2

Sample results for mdct-test from libcelt's mdct-test.c (celt 0.7.1)

nfft=32 inverse=0,snr = 140.440378

nfft=32 inverse=1,snr = 143.876233

nfft=256 inverse=0,snr = 138.890405

nfft=256 inverse=1,snr = 138.232467

nfft=512 inverse=0,snr = 138.457512

nfft=512 inverse=1,snr = 139.477586

nfft=40 inverse=0,snr = 137.242465

nfft=40 inverse=1,snr = 140.650695

nfft=56 inverse=0,snr = 138.458400

nfft=56 inverse=1,snr = 140.707211

nfft=120 inverse=0,snr = 137.187369

nfft=120 inverse=1,snr = 140.710089

nfft=240 inverse=0,snr = 138.688972

nfft=240 inverse=1,snr = 138.796247

nfft=480 inverse=0,snr = 136.993939

nfft=480 inverse=1,snr = 138.320163

Changing compiler flags yields same results

Processor info, Intel Core 2 Duo @ 3.06GHz

OS Info : OSX 10.6.4, Darwin 10.4.0, gcc 4.2.1

## ···

Cheers

Jing

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

To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net

For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

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

To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net

For additional commands, e-mail: dev-help@sip-communicator.dev.java.net