**
**
** $VER: CalcPermissibleNoise.asm 1.1 (28.08.2000)
**
** 27.8.2000 :
**      - psy_adRNorm[] n'est jamais nul (=> optimisation)
**      - "ecb" n'est jamais nul.
**

        OPT P=68030/68882,ALINK,NOWARN


        INCLUDE "Exec/Types.i"
        INCLUDE "Exec.i"


*----------------------------------------------------------------------------------------------------*
*======================================= Définitions diverses =======================================*
*----------------------------------------------------------------------------------------------------*

* La version 68020 n'utilise pas le FPU

    STRUCTURE   PsychoAnal
        DOUBLE  psy_adToneMaskingNoise,63
        DOUBLE  psy_adNB,63
        BYTE    psy_abCBands,2*64
        DOUBLE  psy_adGroupedValues,63*2
        UBYTE   psy_adCenterBarkVal,64
        DOUBLE  psy_adRNorm,63
        CPTR    psy_pdSpreading
        UWORD   psy_wCBands
    ENDSTRUCT   PsychoAnal

*----------------------------------------------------------------------------------------------------*
*======================================= Fonctions optimisées =======================================*
*----------------------------------------------------------------------------------------------------*

        IFNE CPU_TYPE-68020

                SECTION "CalcPermissibleNoise:0",CODE

bmax:
        dc.s    $41A00000,$41A00000,$41A00000,$41A00000,$41A00000,$41880000,$41700000,$41200000,$40E00000
        dc.s    $408CCCCC,$40900000,$40900000,$40900000,$40900000,$40900000,$40900000,$40900000,$40900000
        dc.s    $40900000,$40900000,$40900000,$40900000,$40900000,$40900000,$40600000,$40600000,$40600000

bmax_exp:
        dc.d    $3F847AE147AE147B,$3F847AE147AE147B,$3F847AE147AE147B,$3F847AE147AE147B,$3F847AE147AE147B,$3F946E75DF96DDF0
        dc.d    $3FA030DC4EA0384C,$3FB999999999999A,$3FC98A13577C9402,$3FD73CABBCC88106,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF
        dc.d    $3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF
        dc.d    $3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF,$3FD6B54337BC3BAF
        dc.d    $3FDC9676C6FCAEE1,$3FDC9676C6FCAEE1,$3FDC9676C6FCAEE1


                XDEF    _CalcPermissibleNoise
                XREF    _log10__r
                XREF    _exp__r

; void CalcPermissibleNoise(void *dataBase)

_CalcPermissibleNoise
                PUSH    d2-d5/a2-a4/a6,CalcPermNoise
                fmovem.x fp2/fp3,-(a7)

                DEFINE  CalcPermNoise
                LONG    FPU_REGS,2*3
                CPTR    DataBase

                move.l  DataBase(a7),a3
                lea     psy_adToneMaskingNoise(a3),a2   ; register REAL  *pdTMN = psy_adToneMaskingNoise;
                lea     psy_adNB(a3),a4         ; register REAL  *pdNB  = psy_adNB;
                lea     psy_abCBands(a3),a6     ; register BYTE  *pbCB  = &psy_abCBands[0][0];
                move.w  psy_wCBands(a3),d4

        ; for (j = 0; j <= psy_wCBands; j++)
                moveq   #0,d2

.j_loop         fmove.s #0.0,fp0
                moveq   #0,d0
                move.b  $40(a6),d1              ; l = pbCB[64];
                move.l  d2,d5
                move.b  (a6)+,d0                ; k = *pbCB++;
                asl.l   #6,d5
                move.l  d0,d3
                sub.l   d2,d5                   ; = d2 * 63
                add.l   d0,d3
                fmove.x fp0,fp2                 ; cb = ecb = 0.0;
                add.l   d0,d5

                lea     (psy_adGroupedValues,a3,d3.l*8),a0
                                                ; pGrp = &psy_adGroupedValues[k][0];
                asl.l   #3,d5                   ; = (j * 63 + k) * 8
                move.l  psy_pdSpreading(a3),a1
                add.l   d5,a1                   ; pSpreading = &(*psy_pdSpreading)[j][k];

        ; for (; k <= l; k++) {

.k_loop         fmove.d (a1)+,fp1               ; temp = *pSpreading++;
                fmove.d (a0)+,fp3
                fmul.x  fp1,fp3
                fadd.x  fp3,fp2                 ; ecb += temp * *pGrp++;
                fmul.d  (a0)+,fp1
                fadd.x  fp1,fp0                 ; cb  += temp * *pGrp++;
                addq.b  #1,d0
                cmp.b   d1,d0
                ble.b   .k_loop

                fdiv.x  fp2,fp0                 ; cb = cb / ecb;
                moveq   #0,d3
                move.b  (psy_adCenterBarkVal,a3,d2.l),d3        ; k  = psy_abCenterBarkVal[j];
                tst.l   (psy_adRNorm,a3,d2.l*8) ; Le FPU est encore occupé...

        ; if (cb < 0.05)
                fcmp.s  #0.05,fp0
                fboge.w .check_cb_1

.cb_neg1        fmove.s #-1.0,fp0
                bra.b   .compute

        ; else if (cb > 0.5)

.check_cb_1     fcmp.s  #0.5,fp0
                fbole.w .check_cb_2

                fmove.s #0.0,fp0
                bra.b   .compute

        ; else

.check_cb_2
        IFEQ    CPU_TYPE-68030
                flog10.x fp0
        ELSE
                fmove.d fp0,-(a7)
                jsr     _log10__r
                addq.w  #$8,a7
        ENDC
                fadd.d  #$3FD34413509F7B4C,fp0

.compute        fmul.d  (a2)+,fp0
                fmove.s #5.5,fp1
                fsub.x  fp0,fp1                         ; cb = 5.5 - cb * *pdTMN++;

                ; cb = (cb < bmax[k]) ? bmax_exp[k] : exp(cb * (-LN_TO

                fcmp.s  (bmax,pc,d3.l*4),fp1
                fboge.w .L256

                fmove.d (bmax_exp,pc,d3.l*8),fp0
                bra.b   .L257

.L256           fmul.d  #$BFCD791C5F88877A,fp1          ; == -log(10)/10
        IFEQ CPU_TYPE-68030
                fetox.x fp1,fp0
        ELSE
                fmove.d fp1,-(a7)
                jsr     _exp__r
                addq.w  #$8,a7
        ENDC

.L257           fmul.x  fp0,fp2
                fmul.d  (psy_adRNorm,a3,d2.l*8),fp2
                addq.l  #1,d2
                fmove.d fp2,(a4)+
                cmp.w   d4,d2
                ble     .j_loop

                fmovem.x (a7)+,fp2/fp3
                POP     CalcPermNoise
                rts

        ENDC    ; MC68030+

        END

