Annotation of hatari/src/dmaSnd.c, revision 1.1.1.7

1.1       root        1: /*
                      2:   Hatari - dmaSnd.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   STE DMA sound emulation. Does not seem to be very hard at first glance,
                      8:   but since the DMA sound has to be mixed together with the PSG sound and
                      9:   the output frequency of the host computer differs from the DMA sound
                     10:   frequency, the copy function is a little bit complicated.
1.1.1.7 ! root       11:   For reducing copy latency, we set a cycle-interrupt event with
        !            12:   CycInt_AddRelativeInterrupt to occur just after a sound frame should be
        !            13:   finished. There we update the sound.
        !            14:   The update function also triggers the ST interrupts (Timer A and MFP-i7)
        !            15:   which are often used in ST programs for setting a new sound frame after
        !            16:   the old one has finished.
        !            17: 
        !            18:   Falcon sound emulation is all taken into account in crossbar.c
1.1       root       19: 
                     20: 
                     21:   Hardware I/O registers:
                     22: 
                     23:     $FF8900 (word) : DMA sound control register
                     24:     $FF8903 (byte) : Frame Start Hi
                     25:     $FF8905 (byte) : Frame Start Mi
                     26:     $FF8907 (byte) : Frame Start Lo
                     27:     $FF8909 (byte) : Frame Count Hi
                     28:     $FF890B (byte) : Frame Count Mi
                     29:     $FF890D (byte) : Frame Count Lo
                     30:     $FF890F (byte) : Frame End Hi
                     31:     $FF8911 (byte) : Frame End Mi
                     32:     $FF8913 (byte) : Frame End Lo
                     33:     $FF8920 (word) : Sound Mode Control (frequency, mono/stereo)
                     34:     $FF8922 (byte) : Microwire Data Register
                     35:     $FF8924 (byte) : Microwire Mask Register
1.1.1.7 ! root       36: 
        !            37:   
        !            38:   The Microwire and LMC 1992 commands :
        !            39:     
        !            40:     a command looks like: 10 CCC DDD DDD
        !            41:     
        !            42:     chipset address : 10
        !            43:     command : 
        !            44:        000 XXX XDD Mixing
        !            45:                00 : DMA and (YM2149 - 12dB) mixing
        !            46:                01 : DMA and YM2149 mixing
        !            47:                10 : DMA only
        !            48:                11 : Reserved
        !            49: 
        !            50:        001 XXD DDD Bass
        !            51:                0 000 : -12 dB
        !            52:                0 110 :   0 dB
        !            53:                1 100 : +12 dB
        !            54:       
        !            55:        002 XXD DDD Treble
        !            56:                0 000 : -12 dB
        !            57:                0 110 :   0 dB
        !            58:                1 100 : +12 dB
        !            59: 
        !            60:        003 DDD DDD Master volume
        !            61:                000 000 : -80 dB
        !            62:                010 100 : -40 dB
        !            63:                101 XXX :   0 dB
        !            64:        
        !            65:        004 XDD DDD Right channel volume
        !            66:                00 000 : -40 dB
        !            67:                01 010 : -20 dB
        !            68:                10 1XX :   0 dB
        !            69: 
        !            70:        005 XDD DDD  Left channel volume
        !            71:                00 000 : -40 dB
        !            72:                01 010 : -20 dB
        !            73:                10 1XX :   0 dB
        !            74:              
        !            75:        Other : undefined
        !            76: 
        !            77:        LMC1992 IIR code Copyright by David Savinkoff 2010
        !            78: 
        !            79:        A first order bass filter is multiplied with a
        !            80:        first order treble filter to make a single
        !            81:        second order IIR shelf filter.
        !            82: 
        !            83:        Sound is stereo filtered by Boosting or Cutting
        !            84:        the Bass and Treble by +/-12dB in 2dB steps.
        !            85: 
        !            86:        This filter sounds exactly as the Atari TT or STE.
        !            87:        Sampling frequency = selectable
        !            88:        Bass turnover = 118.276Hz    (8.2nF on LM1992 bass)
        !            89:        Treble turnover = 8438.756Hz (8.2nF on LM1992 treble)
1.1       root       90: */
1.1.1.7 ! root       91: 
        !            92: 
1.1.1.5   root       93: const char DmaSnd_fileid[] = "Hatari dmaSnd.c : " __DATE__ " " __TIME__;
1.1       root       94: 
                     95: #include "main.h"
                     96: #include "audio.h"
1.1.1.3   root       97: #include "configuration.h"
1.1       root       98: #include "dmaSnd.h"
1.1.1.7 ! root       99: #include "cycInt.h"
1.1       root      100: #include "ioMem.h"
1.1.1.6   root      101: #include "log.h"
1.1       root      102: #include "memorySnapShot.h"
                    103: #include "mfp.h"
                    104: #include "sound.h"
1.1.1.3   root      105: #include "stMemory.h"
1.1.1.7 ! root      106: 
        !           107: #define TONE_STEPS 13
        !           108: 
        !           109: 
        !           110: /* Global variables that can be changed/read from other parts of Hatari */
        !           111: void DmaSnd_Init_Bass_and_Treble_Tables(void);
        !           112: 
        !           113: static void DmaSnd_Set_Tone_Level(int set_bass, int set_treb);
        !           114: static float DmaSnd_IIRfilterL(float xn);
        !           115: static float DmaSnd_IIRfilterR(float xn);
        !           116: static struct first_order_s *DmaSnd_Treble_Shelf(float g, float fc, float Fs);
        !           117: static struct first_order_s *DmaSnd_Bass_Shelf(float g, float fc, float Fs);
        !           118: static Sint8 DmaSnd_LowPassFilterLeft(Sint8 in);
        !           119: static Sint8 DmaSnd_LowPassFilterMono(Sint8 in);
        !           120: static Sint8 DmaSnd_LowPassFilterRight(Sint8 in);
1.1       root      121: 
                    122: 
                    123: Uint16 nDmaSoundControl;                /* Sound control register */
                    124: 
1.1.1.7 ! root      125: struct first_order_s  { float a1, b0, b1; };
        !           126: struct second_order_s { float a1, a2, b0, b1, b2; };
        !           127: 
        !           128: struct dma_s {
        !           129:        Uint16 soundMode;               /* Sound mode register */
        !           130:        Uint32 frameStartAddr;          /* Sound frame start */
        !           131:        Uint32 frameEndAddr;            /* Sound frame end */
        !           132:        Uint32 frameCounter_int;        /* Counter in current sound frame, integer part */
        !           133:        Uint32 frameCounter_dec;        /* Counter in current sound frame, decimal part */
        !           134:        Uint32 frameLen;                /* Length of the frame */
        !           135: };
        !           136: 
        !           137: struct microwire_s {
        !           138:        Uint16 data;                    /* Microwire Data register */
        !           139:        Uint16 mask;                    /* Microwire Mask register */
        !           140:        int mwTransferSteps;            /* Microwire shifting counter */
        !           141:        Uint16 mixing;                  /* Mixing command */
        !           142:        Uint16 bass;                    /* Bass command */
        !           143:        Uint16 treble;                  /* Treble command */
        !           144:        Uint16 masterVolume;            /* Master volume command */
        !           145:        Uint16 leftVolume;              /* Left channel volume command */
        !           146:        Uint16 rightVolume;             /* Right channel volume command */
        !           147: };
        !           148: 
        !           149: struct lmc1992_s {
        !           150:        struct first_order_s bass_table[TONE_STEPS];
        !           151:        struct first_order_s treb_table[TONE_STEPS];
        !           152:        float coef[5];                  /* IIR coefs */
        !           153:        /*float gain;*/                 /* IIR gain*/
        !           154: };
        !           155: 
        !           156: static struct dma_s dma;
        !           157: static struct microwire_s microwire;
        !           158: static struct lmc1992_s lmc1992;
        !           159: 
        !           160: /* dB = 20log(gain)  :  gain = antilog(dB/20)                                */
        !           161: /* Table gain values = (int)(powf(10.0, dB/20.0)*65536.0 + 0.5)  2dB steps   */
        !           162: 
        !           163: 
        !           164: /* Values for LMC1992 Master volume control (*65536) */
        !           165: static const Uint16 LMC1992_Master_Volume_Table[64] =
        !           166: {
        !           167:            7,     8,    10,    13,    16,    21,    26,    33,    41,    52,  /* -80dB */
        !           168:           66,    83,   104,   131,   165,   207,   261,   328,   414,   521,  /* -60dB */
        !           169:          655,   825,  1039,  1308,  1646,  2072,  2609,  3285,  4135,  5206,  /* -40dB */
        !           170:         6554,  8250, 10387, 13076, 16462, 20724, 26090, 32846, 41350, 52057,  /* -20dB */
        !           171:        65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,  /*   0dB */
        !           172:        65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,  /*   0dB */
        !           173:        65535, 65535, 65535, 65535                                             /*   0dB */
        !           174: };
1.1.1.6   root      175: 
1.1.1.7 ! root      176: /* Values for LMC1992 Left and right volume control (*65536) */
        !           177: static const Uint16 LMC1992_LeftRight_Volume_Table[32] =
        !           178: {
        !           179:          655,   825,  1039,  1308,  1646,  2072,  2609,  3285,  4135,  5206,  /* -40dB */
        !           180:         6554,  8250, 10387, 13076, 16462, 20724, 26090, 32846, 41350, 52057,  /* -20dB */
        !           181:        65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,  /*   0dB */
        !           182:        65535, 65535                                                           /*   0dB */
1.1       root      183: };
                    184: 
1.1.1.7 ! root      185: /* Values for LMC1992 BASS and TREBLE */
        !           186: static const Sint16 LMC1992_Bass_Treble_Table[16] =
        !           187: {
        !           188:        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12, 12
        !           189: };
1.1       root      190: 
1.1.1.7 ! root      191: static const int DmaSndSampleRates[4] =
1.1.1.3   root      192: {
1.1.1.7 ! root      193:        CPU_FREQ / 1280,        /* 6258  Hz */
        !           194:        CPU_FREQ / 640,         /* 12517 Hz */
        !           195:        CPU_FREQ / 320,         /* 25033 Hz */
        !           196:        CPU_FREQ / 160          /* 50066 Hz */
1.1.1.3   root      197: };
                    198: 
                    199: 
1.1       root      200: /*-----------------------------------------------------------------------*/
1.1.1.3   root      201: /**
1.1.1.7 ! root      202:  * Init DMA sound variables.
        !           203:  */
        !           204: void DmaSnd_Init(void)
        !           205: {
        !           206:        DmaSnd_Reset(1);
        !           207: }
        !           208: 
        !           209: /**
1.1.1.3   root      210:  * Reset DMA sound variables.
                    211:  */
1.1.1.4   root      212: void DmaSnd_Reset(bool bCold)
1.1       root      213: {
                    214:        nDmaSoundControl = 0;
                    215: 
                    216:        if (bCold)
                    217:        {
1.1.1.7 ! root      218:                dma.soundMode = 3;
        !           219:                microwire.masterVolume = 65535;
        !           220:                microwire.leftVolume = 65535;
        !           221:                microwire.rightVolume = 65535;
        !           222:                microwire.mixing = 0;
        !           223:                microwire.bass = 6;
        !           224:                microwire.treble = 6;
1.1       root      225:        }
1.1.1.4   root      226: 
1.1.1.7 ! root      227:        /* Initialise microwire LMC1992 IIR filter parameters */
        !           228:        DmaSnd_Init_Bass_and_Treble_Tables();
1.1.1.6   root      229: 
1.1.1.7 ! root      230:        microwire.mwTransferSteps = 0;
1.1       root      231: }
                    232: 
                    233: /*-----------------------------------------------------------------------*/
1.1.1.3   root      234: /**
                    235:  * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
                    236:  */
1.1.1.4   root      237: void DmaSnd_MemorySnapShot_Capture(bool bSave)
1.1       root      238: {
                    239:        /* Save/Restore details */
                    240:        MemorySnapShot_Store(&nDmaSoundControl, sizeof(nDmaSoundControl));
1.1.1.7 ! root      241:        MemorySnapShot_Store(&dma, sizeof(dma));
        !           242:        MemorySnapShot_Store(&microwire, sizeof(microwire));
        !           243:        MemorySnapShot_Store(&lmc1992, sizeof(lmc1992));
1.1       root      244: }
                    245: 
                    246: 
1.1.1.7 ! root      247: static int DmaSnd_DetectSampleRate(void)
1.1.1.3   root      248: {
1.1.1.7 ! root      249:        return DmaSndSampleRates[dma.soundMode & 3];
1.1.1.3   root      250: }
                    251: 
                    252: 
1.1       root      253: /*-----------------------------------------------------------------------*/
1.1.1.3   root      254: /**
                    255:  * This function is called when a new sound frame is started.
                    256:  * It copies the start and end address from the I/O registers, calculates
                    257:  * the sample length, etc.
                    258:  */
1.1       root      259: static void DmaSnd_StartNewFrame(void)
                    260: {
                    261:        int nCyclesForFrame;
1.1.1.4   root      262: 
1.1.1.7 ! root      263:        dma.frameStartAddr = (IoMem[0xff8903] << 16) | (IoMem[0xff8905] << 8) | (IoMem[0xff8907] & ~1);
        !           264:        dma.frameEndAddr = (IoMem[0xff890f] << 16) | (IoMem[0xff8911] << 8) | (IoMem[0xff8913] & ~1);
1.1       root      265: 
1.1.1.7 ! root      266:        dma.frameCounter_int = 0;
        !           267:        dma.frameCounter_dec = 0;
        !           268:        
        !           269:        dma.frameLen = dma.frameEndAddr - dma.frameStartAddr;
1.1       root      270: 
1.1.1.7 ! root      271:        if (dma.frameEndAddr <= dma.frameStartAddr)
1.1.1.6   root      272:        {
                    273:                Log_Printf(LOG_WARN, "DMA snd: Illegal buffer size (from 0x%x to 0x%x)\n",
1.1.1.7 ! root      274:                          dma.frameStartAddr, dma.frameEndAddr);
        !           275:                dma.frameLen = 0;
1.1.1.6   root      276:                return;
                    277:        }
                    278: 
1.1       root      279:        /* To get smooth sound, set an "interrupt" for the end of the frame that
                    280:         * updates the sound mix buffer. */
1.1.1.7 ! root      281:        nCyclesForFrame = dma.frameLen * (CPU_FREQ / DmaSnd_DetectSampleRate());
        !           282:        if (!(dma.soundMode & DMASNDMODE_MONO))  /* Is it stereo? */
1.1       root      283:                nCyclesForFrame = nCyclesForFrame / 2;
1.1.1.7 ! root      284:        CycInt_AddRelativeInterrupt(nCyclesForFrame, INT_CPU_CYCLE, INTERRUPT_DMASOUND);
1.1       root      285: }
                    286: 
                    287: 
                    288: /*-----------------------------------------------------------------------*/
1.1.1.3   root      289: /**
1.1.1.7 ! root      290:  * End-of-frame has been reached. Raise interrupts if needed.
1.1.1.6   root      291:  * Returns true if DMA sound processing should be stopped now and false
1.1.1.7 ! root      292:  * if it continues (DMA PLAYLOOP mode).
1.1.1.3   root      293:  */
1.1.1.7 ! root      294: static inline int DmaSnd_EndOfFrameReached(void)
1.1       root      295: {
1.1.1.7 ! root      296:        /* Raise end-of-frame interrupts (MFP-i7 and Time-A) */
        !           297:        MFP_InputOnChannel(MFP_TIMER_GPIP7_BIT, MFP_IERA, &MFP_IPRA);
        !           298:        if (MFP_TACR == 0x08)       /* Is timer A in Event Count mode? */
        !           299:                MFP_TimerA_EventCount_Interrupt();
1.1       root      300: 
1.1.1.7 ! root      301:        if (nDmaSoundControl & DMASNDCTRL_PLAYLOOP)
        !           302:        {
        !           303:                DmaSnd_StartNewFrame();
1.1       root      304:        }
1.1.1.7 ! root      305:        else
1.1.1.6   root      306:        {
1.1.1.7 ! root      307:                nDmaSoundControl &= ~DMASNDCTRL_PLAY;
        !           308:                return true;
1.1.1.6   root      309:        }
                    310: 
1.1.1.7 ! root      311:        return false;
1.1       root      312: }
                    313: 
                    314: 
                    315: /*-----------------------------------------------------------------------*/
1.1.1.3   root      316: /**
                    317:  * Mix DMA sound sample with the normal PSG sound samples.
1.1.1.6   root      318:  * Note: We adjust the volume level of the 8-bit DMA samples to factor
1.1.1.7 ! root      319:  * 0.75 compared to the PSG sound samples.
1.1.1.3   root      320:  */
1.1       root      321: void DmaSnd_GenerateSamples(int nMixBufIdx, int nSamplesToGenerate)
                    322: {
1.1.1.7 ! root      323:        Uint32 FreqRatio;
        !           324:        int i, intPart;
        !           325:        int nBufIdx;
        !           326:        Sint8 *pFrameStart, FrameMono = 0, FrameLeft = 0, FrameRight = 0;
        !           327:        unsigned n;
1.1.1.6   root      328: 
1.1       root      329:        if (!(nDmaSoundControl & DMASNDCTRL_PLAY))
                    330:                return;
                    331: 
1.1.1.7 ! root      332:        pFrameStart = (Sint8 *)&STRam[dma.frameStartAddr];
1.1       root      333: 
1.1.1.7 ! root      334:        /* Compute ratio between hatari's sound frequency and host computer's sound frequency */
        !           335:        FreqRatio = (Uint32)(DmaSnd_DetectSampleRate() / (double)nAudioFrequency * 65536.0 + 0.5);
        !           336: 
        !           337:        if (dma.soundMode & DMASNDMODE_MONO)
1.1.1.3   root      338:        {
                    339:                /* Mono 8-bit */
1.1.1.7 ! root      340: 
        !           341:                n = dma.frameCounter_int;
        !           342: 
1.1       root      343:                for (i = 0; i < nSamplesToGenerate; i++)
                    344:                {
1.1.1.7 ! root      345:                        /* Is end of DMA buffer reached ? */
        !           346:                        if (dma.frameCounter_int >= dma.frameLen) {
        !           347:                                if (DmaSnd_EndOfFrameReached())
        !           348:                                        break;
        !           349:                                else
        !           350:                                {       n = dma.frameCounter_int;
        !           351:                                        pFrameStart = (Sint8 *)&STRam[dma.frameStartAddr];
        !           352:                                }
        !           353:                        }
        !           354: 
        !           355:                        /* Apply anti-aliasing low pass filter ? (mono) */
        !           356:                        for ( ; n <= dma.frameCounter_int; n++) {
        !           357:                                FrameMono = DmaSnd_LowPassFilterMono(pFrameStart[n]);
        !           358:                        }
        !           359: 
1.1       root      360:                        nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.7 ! root      361: 
        !           362:                        switch (microwire.mixing) {
        !           363:                                case 1:
        !           364:                                        /* DMA and YM2149 mixing */
        !           365:                                        MixBuffer[nBufIdx][0] = MixBuffer[nBufIdx][0] + (Sint16)FrameMono * -(256*3/4)/4;       
        !           366:                                        break;
        !           367:                                case 2:
        !           368:                                        /* DMA sound only */
        !           369:                                        MixBuffer[nBufIdx][0] = (Sint16)FrameMono * -(256*3/4)/4;
        !           370:                                        break;
        !           371:                                default:
        !           372:                                        /* DMA and (YM2149 - 12dB) mixing */
        !           373:                                        /* instead of 16462 (-12dB), we approximate by 16384 */
        !           374:                                        MixBuffer[nBufIdx][0] = ((Sint16)FrameMono * -(256*3/4)/4) +
        !           375:                                                                (((Sint32)MixBuffer[nBufIdx][0] * 16384)/65536);
        !           376:                                        break;
        !           377:                        }
        !           378:                        MixBuffer[nBufIdx][1] = MixBuffer[nBufIdx][0];  
        !           379: 
        !           380:                        /* Increase ratio pointer to next DMA sample */
        !           381:                        dma.frameCounter_dec += FreqRatio;
        !           382:                        if (dma.frameCounter_dec >= 65536) {
        !           383:                                intPart = dma.frameCounter_dec >> 16;
        !           384:                                dma.frameCounter_int += intPart;
        !           385:                                dma.frameCounter_dec -= intPart* 65536;
        !           386:                        }
1.1       root      387:                }
                    388:        }
                    389:        else
                    390:        {
1.1.1.3   root      391:                /* Stereo 8-bit */
1.1.1.7 ! root      392: 
        !           393:                FreqRatio *= 2;
        !           394:                n = dma.frameCounter_int & ~1;
        !           395: 
1.1       root      396:                for (i = 0; i < nSamplesToGenerate; i++)
                    397:                {
1.1.1.7 ! root      398:                        /* Is end of DMA buffer reached ? */
        !           399:                        if ((dma.frameCounter_int | 1) >= dma.frameLen) {
        !           400:                                if (DmaSnd_EndOfFrameReached())
        !           401:                                        break;
        !           402:                                else
        !           403:                                {       n = dma.frameCounter_int & ~1;
        !           404:                                        pFrameStart = (Sint8 *)&STRam[dma.frameStartAddr];
        !           405:                                }
        !           406:                        }
        !           407: 
        !           408:                        /* Apply anti-aliasing low pass filter ? (stereo) */
        !           409:                        for ( ; n <= (dma.frameCounter_int & ~1); n += 2) {
        !           410:                                FrameLeft  = DmaSnd_LowPassFilterLeft(pFrameStart[n]);
        !           411:                                FrameRight = DmaSnd_LowPassFilterRight(pFrameStart[n+1]);
        !           412:                        }
        !           413: 
1.1       root      414:                        nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.7 ! root      415:                        
        !           416:                        switch (microwire.mixing) {
        !           417:                                case 1:
        !           418:                                        /* DMA and YM2149 mixing */
        !           419:                                        MixBuffer[nBufIdx][0] = MixBuffer[nBufIdx][0] + (Sint16)FrameLeft * -(256*3/4)/4;       
        !           420:                                        MixBuffer[nBufIdx][1] = MixBuffer[nBufIdx][1] + (Sint16)FrameRight * -(256*3/4)/4;      
        !           421:                                        break;
        !           422:                                case 2:
        !           423:                                        /* DMA sound only */
        !           424:                                        MixBuffer[nBufIdx][0] = (Sint16)FrameLeft * -(256*3/4)/4;
        !           425:                                        MixBuffer[nBufIdx][1] = (Sint16)FrameRight * -(256*3/4)/4;
        !           426:                                        break;
        !           427:                                default:
        !           428:                                        /* DMA and (YM2149 - 12dB) mixing */
        !           429:                                        /* instead of 16462 (-12dB), we approximate by 16384 */
        !           430:                                        MixBuffer[nBufIdx][0] = ((Sint16)FrameLeft * -(256*3/4)/4) +
        !           431:                                                                (((Sint32)MixBuffer[nBufIdx][0] * 16384)/65536);
        !           432:                                        MixBuffer[nBufIdx][1] = ((Sint16)FrameRight * -(256*3/4)/4) +
        !           433:                                                                (((Sint32)MixBuffer[nBufIdx][1] * 16384)/65536);
        !           434:                                        break;
        !           435:                        }
        !           436: 
        !           437:                        /* Increase ratio pointer to next DMA sample */
        !           438:                        dma.frameCounter_dec += FreqRatio;
        !           439:                        if (dma.frameCounter_dec >= 65536) {
        !           440:                                intPart = dma.frameCounter_dec >> 16;
        !           441:                                dma.frameCounter_int += intPart;
        !           442:                                dma.frameCounter_dec -= intPart* 65536;
        !           443:                        }
1.1       root      444:                }
                    445:        }
1.1.1.7 ! root      446: 
        !           447:        /* Apply LMC1992 sound modifications (Bass and Treble) 
        !           448:           The Bass and Treble get samples at nAudioFrequency rate.
        !           449:           The tone control's sampling frequency must be at least 22050 Hz to sound good. 
        !           450:        */
        !           451:        for (i = 0; i < nSamplesToGenerate; i++) {
        !           452:                nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
        !           453:                MixBuffer[nBufIdx][0] = 0.5 + DmaSnd_IIRfilterL(MixBuffer[nBufIdx][0]);
        !           454:                MixBuffer[nBufIdx][1] = 0.5 + DmaSnd_IIRfilterR(MixBuffer[nBufIdx][1]);
        !           455:        }
        !           456: 
        !           457:        /* Apply LMC1992 sound modifications (Left, Right and Master Volume) */
        !           458:        for (i = 0; i < nSamplesToGenerate; i++) {
        !           459:                nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
        !           460:                MixBuffer[nBufIdx][0] = (((MixBuffer[nBufIdx][0] * microwire.leftVolume) >> 16) * microwire.masterVolume) >> 16;
        !           461:                MixBuffer[nBufIdx][1] = (((MixBuffer[nBufIdx][1] * microwire.rightVolume) >> 16) * microwire.masterVolume) >> 16;
        !           462:        }
1.1       root      463: }
                    464: 
                    465: 
                    466: /*-----------------------------------------------------------------------*/
1.1.1.3   root      467: /**
                    468:  * DMA sound end of frame "interrupt". Used for updating the sound after
                    469:  * a frame has been finished.
                    470:  */
1.1       root      471: void DmaSnd_InterruptHandler(void)
                    472: {
                    473:        /* Remove this interrupt from list and re-order */
1.1.1.7 ! root      474:        CycInt_AcknowledgeInterrupt();
1.1       root      475: 
                    476:        /* Update sound */
                    477:        Sound_Update();
                    478: }
                    479: 
                    480: 
                    481: /*-----------------------------------------------------------------------*/
1.1.1.3   root      482: /**
                    483:  * Create actual position for frame count registers.
                    484:  */
1.1       root      485: static Uint32 DmaSnd_GetFrameCount(void)
                    486: {
                    487:        Uint32 nActCount;
                    488: 
                    489:        if (nDmaSoundControl & DMASNDCTRL_PLAY)
1.1.1.7 ! root      490:                nActCount = dma.frameStartAddr + (int)dma.frameCounter_int;
1.1       root      491:        else
                    492:                nActCount = (IoMem[0xff8903] << 16) | (IoMem[0xff8905] << 8) | IoMem[0xff8907];
                    493: 
                    494:        nActCount &= ~1;
                    495: 
                    496:        return nActCount;
                    497: }
                    498: 
                    499: 
                    500: /*-----------------------------------------------------------------------*/
1.1.1.3   root      501: /**
                    502:  * Read word from sound control register (0xff8900).
                    503:  */
1.1       root      504: void DmaSnd_SoundControl_ReadWord(void)
                    505: {
                    506:        IoMem_WriteWord(0xff8900, nDmaSoundControl);
1.1.1.6   root      507: 
1.1.1.7 ! root      508:        LOG_TRACE(TRACE_DMASND, "DMA snd control read: 0x%04x\n", nDmaSoundControl);
1.1       root      509: }
                    510: 
                    511: 
                    512: /*-----------------------------------------------------------------------*/
1.1.1.3   root      513: /**
                    514:  * Read word from sound frame count high register (0xff8909).
                    515:  */
1.1       root      516: void DmaSnd_FrameCountHigh_ReadByte(void)
                    517: {
                    518:        IoMem_WriteByte(0xff8909, DmaSnd_GetFrameCount() >> 16);
                    519: }
                    520: 
                    521: 
                    522: /*-----------------------------------------------------------------------*/
1.1.1.3   root      523: /**
                    524:  * Read word from sound frame count medium register (0xff890b).
                    525:  */
1.1       root      526: void DmaSnd_FrameCountMed_ReadByte(void)
                    527: {
                    528:        IoMem_WriteByte(0xff890b, DmaSnd_GetFrameCount() >> 8);
                    529: }
                    530: 
                    531: 
                    532: /*-----------------------------------------------------------------------*/
1.1.1.3   root      533: /**
                    534:  * Read word from sound frame count low register (0xff890d).
                    535:  */
1.1       root      536: void DmaSnd_FrameCountLow_ReadByte(void)
                    537: {
                    538:        IoMem_WriteByte(0xff890d, DmaSnd_GetFrameCount());
                    539: }
                    540: 
                    541: 
                    542: /*-----------------------------------------------------------------------*/
1.1.1.3   root      543: /**
1.1.1.7 ! root      544:  * Read word from sound mode register (0xff8921).
1.1.1.3   root      545:  */
1.1.1.7 ! root      546: void DmaSnd_SoundModeCtrl_ReadByte(void)
1.1       root      547: {
1.1.1.7 ! root      548:        IoMem_WriteByte(0xff8921, dma.soundMode);
1.1.1.6   root      549: 
1.1.1.7 ! root      550:        LOG_TRACE(TRACE_DMASND, "DMA snd mode read: 0x%02x\n", dma.soundMode);
1.1       root      551: }
                    552: 
                    553: 
                    554: /*-----------------------------------------------------------------------*/
1.1.1.3   root      555: /**
1.1.1.7 ! root      556:  * Write word to sound mode register (0xff8921).
1.1.1.3   root      557:  */
1.1.1.7 ! root      558: void DmaSnd_SoundModeCtrl_WriteByte(void)
1.1       root      559: {
1.1.1.7 ! root      560:        LOG_TRACE(TRACE_DMASND, "DMA snd mode write: 0x%02x\n", IoMem_ReadWord(0xff8921));
1.1.1.3   root      561: 
1.1.1.7 ! root      562:        /* STE or TT - hopefully STFM emulation never gets here :)
        !           563:         * We maskout to only hit bits that exist on a real STE
        !           564:         */
        !           565:        dma.soundMode = (IoMem_ReadByte(0xff8921) & 0x8f);
        !           566:        /* we also write the masked value back into the emulated hw registers so we have a correct value there */
        !           567:        IoMem_WriteByte(0xff8921, dma.soundMode);
1.1       root      568: }
                    569: 
1.1.1.6   root      570: /* ---------------------- Microwire / LMC 1992  ---------------------- */
                    571: 
1.1.1.3   root      572: /**
1.1.1.4   root      573:  * Handle the shifting/rotating of the microwire registers
                    574:  * The microwire regs should be done after 16 usec = 32 NOPs = 128 cycles.
                    575:  * That means we have to shift 16 times with a delay of 8 cycles.
1.1.1.3   root      576:  */
1.1.1.4   root      577: void DmaSnd_InterruptHandler_Microwire(void)
1.1       root      578: {
1.1.1.7 ! root      579:        Uint8 i, bit;
        !           580:        Uint16 saveData;
        !           581:        
1.1.1.4   root      582:        /* Remove this interrupt from list and re-order */
1.1.1.7 ! root      583:        CycInt_AcknowledgeInterrupt();
1.1.1.4   root      584: 
1.1.1.7 ! root      585:        --microwire.mwTransferSteps;
1.1.1.4   root      586: 
                    587:        /* Shift data register until it becomes zero. */
1.1.1.7 ! root      588:        if (microwire.mwTransferSteps > 1)
1.1       root      589:        {
1.1.1.7 ! root      590:                IoMem_WriteWord(0xff8922, microwire.data<<(16-microwire.mwTransferSteps));
1.1       root      591:        }
                    592:        else
                    593:        {
1.1.1.4   root      594:                /* Paradox XMAS 2004 demo continuesly writes to the data
                    595:                 * register, but still expects to read a zero inbetween,
                    596:                 * so we have to output a zero before we're really done
                    597:                 * with the transfer. */
1.1       root      598:                IoMem_WriteWord(0xff8922, 0);
                    599:        }
1.1.1.4   root      600: 
                    601:        /* Rotate mask register */
1.1.1.7 ! root      602:        IoMem_WriteWord(0xff8924, (microwire.mask<<(16-microwire.mwTransferSteps))
        !           603:                                  |(microwire.mask>>microwire.mwTransferSteps));
1.1.1.4   root      604: 
1.1.1.7 ! root      605:        if (microwire.mwTransferSteps > 0)
1.1.1.4   root      606:        {
1.1.1.7 ! root      607:                CycInt_AddRelativeInterrupt(8, INT_CPU_CYCLE, INTERRUPT_DMASOUND_MICROWIRE);
1.1.1.4   root      608:        }
1.1.1.7 ! root      609:        else {
        !           610:                /* Decode the address + command word according to the binary mask */
        !           611:                bit = 0;
        !           612:                saveData = microwire.data;
        !           613:                microwire.data = 0;
        !           614:                for (i=0; i<16; i++) {
        !           615:                        if ((microwire.mask >> i) & 1) {
        !           616:                                microwire.data += ((saveData >> i) & 1) << bit;
        !           617:                                bit ++;
        !           618:                        }
        !           619:                }
1.1.1.4   root      620: 
1.1.1.7 ! root      621:                /* The LMC 1992 address should be 10 xxx xxx xxx */
        !           622:                if ((microwire.data & 0x600) != 0x400)
        !           623:                        return;
        !           624: 
        !           625:                /* Update the LMC 1992 commands */
        !           626:                switch ((microwire.data >> 6) & 0x7) {
        !           627:                        case 0:
        !           628:                                /* Mixing command */
        !           629:                                microwire.mixing = microwire.data & 0x3;
        !           630:                                break;
        !           631:                        case 1:
        !           632:                                /* Bass command */
        !           633:                                microwire.bass = microwire.data & 0xf;
        !           634:                                DmaSnd_Set_Tone_Level(LMC1992_Bass_Treble_Table[microwire.bass], 
        !           635:                                                      LMC1992_Bass_Treble_Table[microwire.treble]);
        !           636:                                break;
        !           637:                        case 2: 
        !           638:                                /* Treble command */
        !           639:                                microwire.treble = microwire.data & 0xf;
        !           640:                                DmaSnd_Set_Tone_Level(LMC1992_Bass_Treble_Table[microwire.bass], 
        !           641:                                                      LMC1992_Bass_Treble_Table[microwire.treble]);
        !           642:                                break;
        !           643:                        case 3:
        !           644:                                /* Master volume command */
        !           645:                                microwire.masterVolume = LMC1992_Master_Volume_Table[microwire.data & 0x3f];
        !           646:                                break;
        !           647:                        case 4:
        !           648:                                /* Right channel volume */
        !           649:                                microwire.rightVolume = LMC1992_LeftRight_Volume_Table[microwire.data & 0x1f];
        !           650:                                break;
        !           651:                        case 5:
        !           652:                                /* Left channel volume */
        !           653:                                microwire.leftVolume = LMC1992_LeftRight_Volume_Table[microwire.data & 0x1f];
        !           654:                                break;
        !           655:                        default:
        !           656:                                /* Do nothing */
        !           657:                                break;
        !           658:                }
        !           659:        }
        !           660: }
1.1.1.4   root      661: 
                    662: /**
                    663:  * Read word from microwire data register (0xff8922).
                    664:  */
                    665: void DmaSnd_MicrowireData_ReadWord(void)
                    666: {
                    667:        /* Shifting is done in DmaSnd_InterruptHandler_Microwire! */
1.1.1.6   root      668:        LOG_TRACE(TRACE_DMASND, "Microwire data read: 0x%x\n", IoMem_ReadWord(0xff8922));
1.1       root      669: }
                    670: 
                    671: 
1.1.1.3   root      672: /**
                    673:  * Write word to microwire data register (0xff8922).
                    674:  */
1.1       root      675: void DmaSnd_MicrowireData_WriteWord(void)
                    676: {
1.1.1.4   root      677:        /* Only update, if no shift is in progress */
1.1.1.7 ! root      678:        if (!microwire.mwTransferSteps)
1.1.1.4   root      679:        {
1.1.1.7 ! root      680:                microwire.data = IoMem_ReadWord(0xff8922);
1.1.1.4   root      681:                /* Start shifting events to simulate a microwire transfer */
1.1.1.7 ! root      682:                microwire.mwTransferSteps = 16;
        !           683:                CycInt_AddRelativeInterrupt(8, INT_CPU_CYCLE, INTERRUPT_DMASOUND_MICROWIRE);
1.1.1.4   root      684:        }
                    685: 
1.1.1.6   root      686:        LOG_TRACE(TRACE_DMASND, "Microwire data write: 0x%x\n", IoMem_ReadWord(0xff8922));
1.1       root      687: }
                    688: 
                    689: 
1.1.1.3   root      690: /**
                    691:  * Read word from microwire mask register (0xff8924).
                    692:  */
1.1       root      693: void DmaSnd_MicrowireMask_ReadWord(void)
                    694: {
1.1.1.4   root      695:        /* Same as with data register, but mask is rotated, not shifted. */
1.1.1.6   root      696:        LOG_TRACE(TRACE_DMASND,  "Microwire mask read: 0x%x\n", IoMem_ReadWord(0xff8924));
1.1       root      697: }
                    698: 
                    699: 
1.1.1.3   root      700: /**
                    701:  * Write word to microwire mask register (0xff8924).
                    702:  */
1.1       root      703: void DmaSnd_MicrowireMask_WriteWord(void)
                    704: {
1.1.1.4   root      705:        /* Only update, if no shift is in progress */
1.1.1.7 ! root      706:        if (!microwire.mwTransferSteps)
1.1.1.4   root      707:        {
1.1.1.7 ! root      708:                microwire.mask = IoMem_ReadWord(0xff8924);
1.1.1.4   root      709:        }
                    710: 
1.1.1.6   root      711:        LOG_TRACE(TRACE_DMASND, "Microwire mask write: 0x%x\n", IoMem_ReadWord(0xff8924));
                    712: }
                    713: 
                    714: 
1.1.1.7 ! root      715: /*-----------------------------------------------------------------------*/
        !           716: /**
        !           717:  * Write word to sound control register (0xff8900).
        !           718:  */
        !           719: void DmaSnd_SoundControl_WriteWord(void)
1.1.1.6   root      720: {
1.1.1.7 ! root      721:        Uint16 nNewSndCtrl;
1.1.1.6   root      722: 
1.1.1.7 ! root      723:        LOG_TRACE(TRACE_DMASND, "DMA snd control write: 0x%04x\n", IoMem_ReadWord(0xff8900));
1.1.1.6   root      724: 
1.1.1.7 ! root      725:        nNewSndCtrl = IoMem_ReadWord(0xff8900) & 3;
1.1.1.6   root      726: 
1.1.1.7 ! root      727:        if (!(nDmaSoundControl & DMASNDCTRL_PLAY) && (nNewSndCtrl & DMASNDCTRL_PLAY))
1.1.1.6   root      728:        {
1.1.1.7 ! root      729:                //fprintf(stderr, "Turning on DMA sound emulation.\n");
        !           730:                DmaSnd_StartNewFrame();
1.1.1.6   root      731:        }
1.1.1.7 ! root      732:        else if ((nDmaSoundControl & DMASNDCTRL_PLAY) && !(nNewSndCtrl & DMASNDCTRL_PLAY))
1.1.1.6   root      733:        {
1.1.1.7 ! root      734:                //fprintf(stderr, "Turning off DMA sound emulation.\n");
        !           735:                /* Create samples up until this point with current values */
        !           736:                Sound_Update();
1.1.1.6   root      737: 
1.1.1.7 ! root      738:        }
1.1.1.6   root      739: 
1.1.1.7 ! root      740:        nDmaSoundControl = nNewSndCtrl;
1.1.1.6   root      741: }
                    742: 
                    743: 
1.1.1.7 ! root      744: /*-------------------Bass / Treble filter ---------------------------*/
1.1.1.6   root      745: 
1.1.1.7 ! root      746: /**
        !           747:  * Left voice Filter for Bass/Treble.
        !           748:  */
        !           749: static float DmaSnd_IIRfilterL(float xn)
        !           750: {
        !           751:        static float data[2] = { 0.0, 0.0 };
        !           752:        float a, yn;
1.1.1.6   root      753: 
1.1.1.7 ! root      754:        /* Input coefficients */
        !           755:        /* biquad1  Note: 'a' coefficients are subtracted */
        !           756:        a  = /*lmc1992.gain * */ xn;            /* a=g*xn;               */
        !           757:        a -= lmc1992.coef[0] * data[0];         /* a1;  wn-1             */
        !           758:        a -= lmc1992.coef[1] * data[1];         /* a2;  wn-2             */
        !           759:                                                /* If coefficient scale  */
        !           760:                                                /* factor = 0.5 then     */
        !           761:                                                /* multiply by 2         */
        !           762:        /* Output coefficients */
        !           763:        yn  = lmc1992.coef[2] * a;              /* b0;                   */
        !           764:        yn += lmc1992.coef[3] * data[0];        /* b1;                   */
        !           765:        yn += lmc1992.coef[4] * data[1];        /* b2;                   */
1.1.1.6   root      766: 
1.1.1.7 ! root      767:        data[1] = data[0];                      /* wn-1 -> wn-2;         */
        !           768:        data[0] = a;                            /* wn -> wn-1            */
        !           769:        return yn;
1.1.1.6   root      770: }
                    771: 
                    772: 
                    773: /**
1.1.1.7 ! root      774:  * Right voice Filter for Bass/Treble.
1.1.1.6   root      775:  */
1.1.1.7 ! root      776: static float DmaSnd_IIRfilterR(float xn)
1.1.1.6   root      777: {
1.1.1.7 ! root      778:        static float data[2] = { 0.0, 0.0 };
        !           779:        float a, yn;
        !           780: 
        !           781:        /* Input coefficients */
        !           782:        /* biquad1  Note: 'a' coefficients are subtracted */
        !           783:        a  = /*lmc1992.gain * */ xn;            /* a=g*xn;               */
        !           784:        a -= lmc1992.coef[0]*data[0];           /* a1;  wn-1             */
        !           785:        a -= lmc1992.coef[1]*data[1];           /* a2;  wn-2             */
        !           786:                                                /* If coefficient scale  */
        !           787:                                                /* factor = 0.5 then     */
        !           788:                                                /* multiply by 2         */
        !           789:        /* Output coefficients */
        !           790:        yn  = lmc1992.coef[2]*a;                /* b0;                   */
        !           791:        yn += lmc1992.coef[3]*data[0];          /* b1;                   */
        !           792:        yn += lmc1992.coef[4]*data[1];          /* b2;                   */
        !           793: 
        !           794:        data[1] = data[0];                      /* wn-1 -> wn-2;         */
        !           795:        data[0] = a;                            /* wn -> wn-1            */
        !           796:        return yn;
1.1.1.6   root      797: }
                    798: 
                    799: /**
1.1.1.7 ! root      800:  * LowPass Filter Mono
1.1.1.6   root      801:  */
1.1.1.7 ! root      802: static Sint8 DmaSnd_LowPassFilterMono(Sint8 in)
1.1.1.6   root      803: {
1.1.1.7 ! root      804:        static int lowPassFilter[2] = { 0, 0 };
        !           805:        Sint8 out;
1.1.1.6   root      806: 
1.1.1.7 ! root      807:        out = ((lowPassFilter[0]>>1) + (lowPassFilter[1]) + (in>>1)) >> 1;
        !           808:        lowPassFilter[0] = lowPassFilter[1];
        !           809:        lowPassFilter[1] = in;
1.1.1.6   root      810: 
1.1.1.7 ! root      811:        return out;
1.1.1.6   root      812: }
                    813: 
                    814: /**
1.1.1.7 ! root      815:  * LowPass Filter Left
1.1.1.6   root      816:  */
1.1.1.7 ! root      817: static Sint8 DmaSnd_LowPassFilterLeft(Sint8 in)
1.1.1.6   root      818: {
1.1.1.7 ! root      819:        static int lowPassFilter[2] = { 0, 0 };
        !           820:        Sint8 out;
1.1.1.6   root      821: 
1.1.1.7 ! root      822:        out = ((lowPassFilter[0]>>1) + (lowPassFilter[1]) + (in>>1)) >> 1;
        !           823:        lowPassFilter[0] = lowPassFilter[1];
        !           824:        lowPassFilter[1] = in;
1.1.1.6   root      825: 
1.1.1.7 ! root      826:        return out;
1.1.1.6   root      827: }
                    828: 
                    829: /**
1.1.1.7 ! root      830:  * LowPass Filter Right
1.1.1.6   root      831:  */
1.1.1.7 ! root      832: static Sint8 DmaSnd_LowPassFilterRight(Sint8 in)
1.1.1.6   root      833: {
1.1.1.7 ! root      834:        static int lowPassFilter[2] = { 0, 0 };
        !           835:        Sint8 out;
1.1.1.6   root      836: 
1.1.1.7 ! root      837:        out = ((lowPassFilter[0]>>1) + (lowPassFilter[1]) + (in>>1)) >> 1;
        !           838:        lowPassFilter[0] = lowPassFilter[1];
        !           839:        lowPassFilter[1] = in;
1.1.1.6   root      840: 
1.1.1.7 ! root      841:        return out;
1.1.1.6   root      842: }
                    843: 
                    844: 
                    845: /**
1.1.1.7 ! root      846:  * Set Bass and Treble tone level
1.1.1.6   root      847:  */
1.1.1.7 ! root      848: static void DmaSnd_Set_Tone_Level(int set_bass, int set_treb)
        !           849: { 
        !           850:        /* 13 levels; 0 through 12 correspond with -12dB to 12dB in 2dB steps */
        !           851:        lmc1992.coef[0] = lmc1992.treb_table[set_treb].a1 + lmc1992.bass_table[set_bass].a1;
        !           852:        lmc1992.coef[1] = lmc1992.treb_table[set_treb].a1 * lmc1992.bass_table[set_bass].a1;
        !           853:        lmc1992.coef[2] = lmc1992.treb_table[set_treb].b0 * lmc1992.bass_table[set_bass].b0;
        !           854:        lmc1992.coef[3] = lmc1992.treb_table[set_treb].b0 * lmc1992.bass_table[set_bass].b1 +
        !           855:                          lmc1992.treb_table[set_treb].b1 * lmc1992.bass_table[set_bass].b0;
        !           856:        lmc1992.coef[4] = lmc1992.treb_table[set_treb].b1 * lmc1992.bass_table[set_bass].b1;
1.1.1.6   root      857: }
                    858: 
                    859: 
                    860: /**
1.1.1.7 ! root      861:  * Compute the first order bass shelf
1.1.1.6   root      862:  */
1.1.1.7 ! root      863: static struct first_order_s *DmaSnd_Bass_Shelf(float g, float fc, float Fs)
1.1.1.6   root      864: {
1.1.1.7 ! root      865:        static struct first_order_s bass;
        !           866:        float  a1;
1.1.1.6   root      867: 
1.1.1.7 ! root      868:        /* g, fc, Fs must be positve real numbers > 0.0 */
        !           869:        if (g < 1.0)
        !           870:                bass.a1 = a1 = (tanf(M_PI*fc/Fs) - g  ) / (tanf(M_PI*fc/Fs) + g  );
        !           871:        else
        !           872:                bass.a1 = a1 = (tanf(M_PI*fc/Fs) - 1.0) / (tanf(M_PI*fc/Fs) + 1.0);
1.1.1.6   root      873: 
1.1.1.7 ! root      874:        bass.b0 = (1.0 + a1) * (g - 1.0) / 2.0 + 1.0;
        !           875:        bass.b1 = (1.0 + a1) * (g - 1.0) / 2.0 + a1;
1.1.1.6   root      876: 
1.1.1.7 ! root      877:        return &bass;
1.1.1.6   root      878: }
                    879: 
                    880: 
                    881: /**
1.1.1.7 ! root      882:  * Compute the first order treble shelf
1.1.1.6   root      883:  */
1.1.1.7 ! root      884: static struct first_order_s *DmaSnd_Treble_Shelf(float g, float fc, float Fs)
1.1.1.6   root      885: {
1.1.1.7 ! root      886:        static struct first_order_s treb;
        !           887:        float  a1;
1.1.1.6   root      888: 
1.1.1.7 ! root      889:        /* g, fc, Fs must be positve real numbers > 0.0 */
        !           890:        if (g < 1.0)
        !           891:                treb.a1 = a1 = (g*tanf(M_PI*fc/Fs) - 1.0) / (g*tanf(M_PI*fc/Fs) + 1.0);
        !           892:        else
        !           893:                treb.a1 = a1 =   (tanf(M_PI*fc/Fs) - 1.0) /   (tanf(M_PI*fc/Fs) + 1.0);
1.1.1.6   root      894: 
1.1.1.7 ! root      895:        treb.b0 = 1.0 + (1.0 - a1) * (g - 1.0) / 2.0;
        !           896:        treb.b1 = a1  + (a1 - 1.0) * (g - 1.0) / 2.0;
        !           897: 
        !           898:        return &treb;
1.1.1.6   root      899: }
                    900: 
1.1.1.7 ! root      901: 
1.1.1.6   root      902: /**
1.1.1.7 ! root      903:  * Compute the bass and treble tables (nAudioFrequency)
1.1.1.6   root      904:  */
1.1.1.7 ! root      905: void DmaSnd_Init_Bass_and_Treble_Tables(void)
1.1.1.6   root      906: {
1.1.1.7 ! root      907:        struct first_order_s *bass;
        !           908:        struct first_order_s *treb;
        !           909: 
        !           910:        float  dB, g, fc_bt, fc_tt, Fs;
        !           911:        int    n;
        !           912: 
        !           913:        fc_bt = 118.2763;
        !           914:        fc_tt = 8438.756;
        !           915:        Fs = (float)nAudioFrequency;
        !           916: 
        !           917:        if ((Fs < 8000.0) || (Fs > 96000.0))
        !           918:                Fs = 44100.0;
        !           919: 
        !           920:        for (dB = 12.0, n = TONE_STEPS; n--; dB -= 2.0)
        !           921:        {
        !           922:                g = powf(10.0, dB/20.0);        /* 12dB to -12dB */
        !           923: 
        !           924:                bass = DmaSnd_Bass_Shelf(g, fc_bt, Fs);
        !           925: 
        !           926:                lmc1992.bass_table[n].a1 = bass->a1;
        !           927:                lmc1992.bass_table[n].b0 = bass->b0;
        !           928:                lmc1992.bass_table[n].b1 = bass->b1;
        !           929: 
        !           930:                treb = DmaSnd_Treble_Shelf(g, fc_tt, Fs);
        !           931: 
        !           932:                lmc1992.treb_table[n].a1 = treb->a1;
        !           933:                lmc1992.treb_table[n].b0 = treb->b0;
        !           934:                lmc1992.treb_table[n].b1 = treb->b1;
        !           935:        }
        !           936: 
        !           937:        DmaSnd_Set_Tone_Level(LMC1992_Bass_Treble_Table[microwire.bass & 0xf], 
        !           938:                              LMC1992_Bass_Treble_Table[microwire.treble & 0xf]);
1.1       root      939: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.