Annotation of ntddk/src/mmedia/synth/dll/midi.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *
                      3:  * Copyright (c) 1992 Microsoft Corporation
                      4:  *
                      5:  */
                      6: 
                      7: /*
                      8:  * midi.c
                      9:  *
                     10:  * Midi FM Synthesis routines. converts midi messages into calls to
                     11:  * FM Synthesis functions  - currently supports base adlib (in adlib.c)
                     12:  * and opl3 synthesisers (in opl3.c).
                     13:  *
                     14:  * 15 Dec 92 Geraint Davies - based on a combination of the adlib
                     15:  *                           and WSS midi drivers.
                     16:  */
                     17: 
                     18: 
                     19: #include <windows.h>
                     20: #include <mmsystem.h>
                     21: 
                     22: #include "mmddk.h"
                     23: #include "driver.h"
                     24: 
                     25: #include "adlib.h"
                     26: #include "opl3.h"
                     27: 
                     28: 
                     29: /***********************************************************
                     30: global memory */
                     31: 
                     32: 
                     33: PORTALLOC gMidiInClient;     // input client information structure
                     34: DWORD dwRefTime;             // time when midi input was opened
                     35: 
                     36: DWORD dwMsgTime;             // timestamp (in ms) of current msg
                     37: DWORD dwMsg = 0L;            // short midi message
                     38: BYTE  bBytesLeft = 0;        // number of bytes needed to complete message
                     39: BYTE  bBytePos = 0;          // position in short message buffer
                     40: DWORD dwCurData = 0L;        // position in long message buffer
                     41: BOOL  fSysex = FALSE;        // are we in sysex mode?
                     42: BYTE  status = 0;
                     43: BYTE    fMidiInStarted = 0;     /* has the midi been started */
                     44: LPMIDIHDR      lpMIQueue = NULL;
                     45: BYTE   gbMidiInUse = 0;                /* if MIDI is in use */
                     46: 
                     47: static WORD  wMidiOutEntered = 0;    // reentrancy check
                     48: static PORTALLOC gMidiOutClient;     // client information
                     49: 
                     50: /* transformation of linear velocity value to
                     51:        logarithmic attenuation */
                     52: BYTE gbVelocityAtten[32] = {
                     53:        40, 36, 32, 28, 23, 21, 19, 17,
                     54:        15, 14, 13, 12, 11, 10, 9, 8,
                     55:        7, 6, 5, 5, 4, 4, 3, 3,
                     56:        2, 2, 1, 1, 1, 0, 0, 0 };
                     57: 
                     58: short   giBend[NUMCHANNELS];    /* bend for each channel */
                     59: BYTE    gbPatch[NUMCHANNELS];   /* patch number mapped to */
                     60: 
                     61: /* --- interface functions ---------------------------------- */
                     62: 
                     63: /*
                     64:  * the functions in this section call out to adlib.c or opl3.c
                     65:  * depending on which device we have installed.
                     66:  */
                     67: 
                     68: 
                     69: /***************************************************************
                     70: MidiNoteOn - This turns a note on. (Including drums, with
                     71:        a patch # of the drum Note + 128)
                     72: 
                     73: inputs
                     74:        BYTE    bPatch - MIDI patch number
                     75:        BYTE    bNote - MIDI note number
                     76:        BYTE    bChannel - MIDI channel #
                     77:        BYTE    bVelocity - Velocity #
                     78:        short   iBend - current pitch bend from -32768, to 32767
                     79: returns
                     80:        WORD - note slot #, or 0xffff if its inaudible
                     81: */
                     82: VOID NEAR PASCAL MidiNoteOn (BYTE bPatch,
                     83:        BYTE bNote, BYTE bChannel, BYTE bVelocity,
                     84:        short iBend)
                     85: {
                     86:     switch(gMidiType) {
                     87:     case TYPE_OPL3:
                     88:        Opl3_NoteOn(bPatch, bNote, bChannel, bVelocity, iBend);
                     89:        break;
                     90: 
                     91:     case TYPE_ADLIB:
                     92:        Adlib_NoteOn(bPatch, bNote, bChannel, bVelocity, iBend);
                     93:        break;
                     94:     }
                     95:     return;
                     96: }
                     97: 
                     98: 
                     99: /**************************************************************
                    100: MidiNoteOff - This turns a note off. (Including drums,
                    101:        with a patch # of the drum note + 128)
                    102: 
                    103: inputs
                    104:        BYTE    bPatch - MIDI patch #
                    105:        BYTE    bNote - MIDI note number
                    106:        BYTE    bChannel - MIDI channel #
                    107: returns
                    108:        none
                    109: */
                    110: VOID FAR PASCAL MidiNoteOff (BYTE bPatch,
                    111:        BYTE bNote, BYTE bChannel)
                    112: {
                    113:     switch (gMidiType) {
                    114:     case TYPE_OPL3:
                    115:        Opl3_NoteOff(bPatch, bNote, bChannel);
                    116:        break;
                    117: 
                    118:     case TYPE_ADLIB:
                    119:        Adlib_NoteOff(bPatch, bNote, bChannel);
                    120:        break;
                    121:     }
                    122: }
                    123: 
                    124: /**************************************************************
                    125: MidiAllNotesOff - switch off all active voices.
                    126: 
                    127: inputs - none
                    128: returns - none
                    129: */
                    130: VOID MidiAllNotesOff(void)
                    131: {
                    132:     switch (gMidiType) {
                    133:     case TYPE_OPL3:
                    134:        Opl3_AllNotesOff();
                    135:        break;
                    136: 
                    137:     case TYPE_ADLIB:
                    138:        Adlib_AllNotesOff();
                    139:        break;
                    140:     }
                    141: }
                    142: 
                    143: 
                    144: /**************************************************************
                    145: MidiNewVolume - This should be called if a volume level
                    146:        has changed. This will adjust the levels of all the playing
                    147:        voices.
                    148: 
                    149: inputs
                    150:        WORD    wLeft   - left attenuation (1.5 db units)
                    151:        WORD    wRight  - right attenuation (ignore if mono)
                    152: returns
                    153:        none
                    154: */
                    155: VOID FAR PASCAL MidiNewVolume (WORD wLeft, WORD wRight)
                    156: {
                    157:     switch (gMidiType) {
                    158:     case TYPE_OPL3:
                    159:        Opl3_NewVolume(wLeft, wRight);
                    160:        break;
                    161: 
                    162:     case TYPE_ADLIB:
                    163:        Adlib_NewVolume(wLeft, wRight);
                    164:        break;
                    165:     }
                    166: 
                    167: }
                    168: 
                    169: /***************************************************************
                    170: MidiChannelVolume - set the volume level for an individual channel.
                    171: 
                    172: inputs
                    173:        BYTE    bChannel - channel number to change
                    174:        WORD    wAtten  - attenuation in 1.5 db units
                    175: 
                    176: returns
                    177:        none
                    178: */
                    179: VOID FAR PASCAL MidiChannelVolume(BYTE bChannel, WORD wAtten)
                    180: {
                    181: 
                    182:     switch (gMidiType) {
                    183:     case TYPE_OPL3:
                    184:        Opl3_ChannelVolume(bChannel, wAtten);
                    185:        break;
                    186: 
                    187:     case TYPE_ADLIB:
                    188:        Adlib_ChannelVolume(bChannel, wAtten);
                    189:        break;
                    190:     }
                    191: 
                    192: }
                    193:        
                    194: 
                    195: 
                    196: /***************************************************************
                    197: MidiSetPan - set the left-right pan position.
                    198: 
                    199: inputs
                    200:        BYTE    bChannel  - channel number to alter
                    201:        BYTE    bPan   - 0 for left, 127 for right or somewhere in the middle.
                    202: 
                    203: returns - none
                    204: */
                    205: VOID FAR PASCAL MidiSetPan(BYTE bChannel, BYTE bPan)
                    206: {
                    207:     switch (gMidiType) {
                    208:     case TYPE_OPL3:
                    209:        Opl3_SetPan(bChannel, bPan);
                    210:        break;
                    211: 
                    212:     case TYPE_ADLIB:
                    213:        Adlib_SetPan(bChannel, bPan);
                    214:        break;
                    215:     }
                    216: 
                    217: }
                    218: 
                    219: /***************************************************************
                    220: MidiPitchBend - This pitch bends a channel.
                    221: 
                    222: inputs
                    223:        BYTE    bChannel - channel
                    224:        short   iBend - Values from -32768 to 32767, being
                    225:                        -2 to +2 half steps
                    226: returns
                    227:        none
                    228: */
                    229: VOID NEAR PASCAL MidiPitchBend (BYTE bChannel,
                    230:        short iBend)
                    231: {
                    232:     switch (gMidiType) {
                    233:     case TYPE_OPL3:
                    234:        Opl3_PitchBend(bChannel, iBend);
                    235:        break;
                    236: 
                    237:     case TYPE_ADLIB:
                    238:        Adlib_PitchBend(bChannel, iBend);
                    239:        break;
                    240:     }
                    241: 
                    242: }
                    243: 
                    244: /***************************************************************
                    245: MidiBoardInit - initialise board and load patches as necessary.
                    246: 
                    247: * inputs - none
                    248: * returns - 0 for success or the error code
                    249: */
                    250: WORD MidiBoardInit(void)
                    251: {
                    252:     /*
                    253:      * load patch tables and reset board
                    254:      */
                    255: 
                    256:     switch (gMidiType) {
                    257:     case TYPE_OPL3:
                    258:        return( Opl3_BoardInit());
                    259:        break;
                    260: 
                    261:     case TYPE_ADLIB:
                    262:        return (Adlib_BoardInit());
                    263:        break;
                    264:     }
                    265:     return(MMSYSERR_ERROR);
                    266: }
                    267: 
                    268: /*
                    269:  * MidiBoardReset - silence the board and set all voices off.
                    270:  */
                    271: VOID MidiBoardReset(void)
                    272: {
                    273:     BYTE i;
                    274: 
                    275:     /*
                    276:      * switch off pitch bend (we own this, not the opl3/adlib code)
                    277:      */
                    278:     for (i = 0; i < NUMCHANNELS; i++)
                    279:        giBend[i] = 0;
                    280: 
                    281:     /*
                    282:      * set all voices off, set channel atten to default,
                    283:      * & silence board.
                    284:      */
                    285:     switch (gMidiType) {
                    286:     case TYPE_OPL3:
                    287:        Opl3_BoardReset();
                    288:        break;
                    289: 
                    290:     case TYPE_ADLIB:
                    291:        Adlib_BoardReset();
                    292:        break;
                    293:     }
                    294: }
                    295: 
                    296: 
                    297: 
                    298: /* --- midi interpretation -------------------------------------*/
                    299: 
                    300: 
                    301: /***************************************************************
                    302: MidiMessage - This handles a MIDI message. This
                    303:        does not do running status.
                    304: 
                    305: inputs
                    306:        DWORD dwData - up to 4 bytes of MIDI data
                    307:                depending upon the message.
                    308: returns
                    309:        none
                    310: */
                    311: VOID NEAR PASCAL MidiMessage (DWORD dwData)
                    312: {
                    313:     BYTE    bChannel, bVelocity, bNote;
                    314:     WORD    wTemp;
                    315: 
                    316:     // D1("\nMidiMessage");
                    317:     bChannel = (BYTE) dwData & (BYTE)0x0f;
                    318:     bVelocity = (BYTE) (dwData >> 16) & (BYTE)0x7f;
                    319:     bNote = (BYTE) ((WORD) dwData >> 8) & (BYTE)0x7f;
                    320: 
                    321:     switch ((BYTE)dwData & 0xf0) {
                    322:        case 0x90:
                    323: #ifdef DEBUG
                    324:        {
                    325:                char szTemp[4];
                    326:                szTemp[0] = "0123456789abcdef"[bNote >> 4];
                    327:                szTemp[1] = "0123456789abcdef"[bNote & 0x0f];
                    328:                szTemp[2] = ' ';
                    329:                szTemp[3] = 0;
                    330:                if ((bChannel == 9) && bVelocity) D1(szTemp);
                    331:        }
                    332: #endif
                    333:                /* turn key on, or key off if volume == 0 */
                    334:                if (bVelocity) {
                    335:                        MidiNoteOn (
                    336:                                (BYTE) ((bChannel == DRUMCHANNEL) ?
                    337:                                        (BYTE) (bNote + 128) : (BYTE) gbPatch[bChannel]),
                    338:                                bNote, bChannel, bVelocity, (short) giBend[bChannel]);
                    339:                        break;
                    340:                };
                    341: 
                    342:                /* else, continue through and turn key off */
                    343:        case 0x80:
                    344:                /* turn key off */
                    345:                MidiNoteOff (
                    346:                        (BYTE) ((bChannel == DRUMCHANNEL) ?
                    347:                                (BYTE) (bNote + 128) : (BYTE) gbPatch[bChannel]),
                    348:                                bNote, bChannel);
                    349:                break;
                    350: 
                    351:        case 0xb0:
                    352:                // D1("\nChangeControl");
                    353:                /* change control */
                    354:                switch (bNote) {
                    355:                        case 7:
                    356:                                /* change channel volume */
                    357:                                MidiChannelVolume(
                    358:                                    gbVelocityAtten[(bVelocity & 0x7f) >> 2],
                    359:                                    bChannel);
                    360: 
                    361:                                break;
                    362:                        case 8:
                    363:                        case 10:
                    364:                                /* change the pan level */
                    365:                                MidiSetPan(bChannel, bVelocity);
                    366:                                break;
                    367:                        };
                    368:                break;
                    369: 
                    370:        case 0xc0:
                    371:                /* program change */
                    372: 
                    373: #if DBG
                    374:                if (wDebugLevel > 1) {
                    375:                    char szTemp[64];
                    376: 
                    377:                    wsprintfA(szTemp, "0x%x: patch chan %d>%d\n",dwData, bChannel, bNote);
                    378:                    OutputDebugStringA(szTemp);
                    379: 
                    380:                }
                    381: #endif
                    382: 
                    383:                /* change patch */
                    384:                gbPatch[bChannel] = bNote;
                    385:                break;
                    386: 
                    387:        case 0xe0:
                    388:                // D1("\nBend");
                    389:                /* pitch bend */
                    390:                wTemp = ((WORD) bVelocity << 9) | ((WORD) bNote << 2);
                    391:                giBend[bChannel] = (short) (WORD) (wTemp + 0x8000);
                    392:                MidiPitchBend (bChannel, giBend[bChannel]);
                    393: 
                    394:                break;
                    395:     };
                    396: 
                    397:     return;
                    398: }
                    399: 
                    400: /****************************************************************************
                    401:  * @doc INTERNAL
                    402:  *
                    403:  * @api void | midiCallback | This calls DriverCallback for a midi device.
                    404:  *
                    405:  * @parm NPPORTALLOC| pPort | Pointer to the PORTALLOC.
                    406:  *
                    407:  * @parm WORD | msg | The message to send.
                    408:  *
                    409:  * @parm DWORD | dw1 | Message-dependent parameter.
                    410:  *
                    411:  * @parm DWORD | dw2 | Message-dependent parameter.
                    412:  *
                    413:  * @rdesc There is no return value.
                    414:  ***************************************************************************/
                    415: void NEAR PASCAL midiCallback(NPPORTALLOC pPort, WORD msg, DWORD dw1, DWORD dw2)
                    416: {
                    417: 
                    418:     // invoke the callback function, if it exists.  dwFlags contains driver-
                    419:     // specific flags in the LOWORD and generic driver flags in the HIWORD
                    420:     if (pPort->dwCallback)
                    421:        DriverCallback(pPort->dwCallback,       // client's callback DWORD
                    422:            HIWORD(pPort->dwFlags) | DCB_NOSWITCH,  // callback flags
                    423:            pPort->hMidi,            // handle to the wave device
                    424:            msg,                     // the message
                    425:            pPort->dwInstance,       // client's instance data
                    426:            dw1,                     // first DWORD
                    427:            dw2);                    // second DWORD
                    428: }
                    429: 
                    430: /****************************************************************************
                    431:  * @doc INTERNAL
                    432:  *
                    433:  * @api void | midBufferWrite | This function writes a byte into the long
                    434:  *     message buffer.  If the buffer is full or a SYSEX_ERROR or
                    435:  *     end-of-sysex byte is received, the buffer is marked as 'done' and
                    436:  *     it's owner is called back.
                    437:  *
                    438:  * @parm BYTE | byte | The byte received.
                    439:  *
                    440:  * @rdesc There is no return value
                    441:  ***************************************************************************/
                    442: static void NEAR PASCAL midBufferWrite(BYTE byte)
                    443: {
                    444:     LPMIDIHDR  lpmh;
                    445:     WORD       msg;
                    446: 
                    447:     // if no buffers, nothing happens
                    448:     if (lpMIQueue == NULL)
                    449:        return;
                    450: 
                    451:     lpmh = lpMIQueue;
                    452: 
                    453:     if (byte == SYSEX_ERROR) {
                    454:        D2("sysexerror");
                    455:        msg = MIM_LONGERROR;
                    456:        }
                    457:     else {
                    458:        D2("bufferwrite");
                    459:        msg = MIM_LONGDATA;
                    460:        *((HPSTR)(lpmh->lpData) + dwCurData++) = byte;
                    461:        }
                    462: 
                    463:     // if end of sysex, buffer full or error, send them back the buffer
                    464:     if ((byte == SYSEX_ERROR) || (byte == 0xF7) || (dwCurData >= lpmh->dwBufferLength)) {
                    465:        D2("bufferdone");
                    466:        lpMIQueue = lpMIQueue->lpNext;
                    467:        lpmh->dwBytesRecorded = dwCurData;
                    468:        dwCurData = 0L;
                    469:        lpmh->dwFlags |= MHDR_DONE;
                    470:        lpmh->dwFlags &= ~MHDR_INQUEUE;
                    471:        midiCallback(&gMidiInClient, msg, (DWORD)lpmh, dwMsgTime);
                    472:     }
                    473: 
                    474:     return;
                    475: }
                    476: 
                    477: 
                    478: 
                    479: /****************************************************************************
                    480: 
                    481:     This function conforms to the standard MIDI output driver message proc
                    482:     modMessage, which is documented in mmddk.d.
                    483: 
                    484:  ***************************************************************************/
                    485: DWORD FAR PASCAL _loadds modMessage(UINT id,
                    486:        UINT msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
                    487: {
                    488:     LPMIDIHDR    lpHdr;
                    489: #ifdef FOGHORN
                    490:     WORD            wTemp1, wTemp2;
                    491: #endif
                    492:     LPSTR           lpBuf;          /* current spot in the long msg buf */
                    493:     DWORD           dwBytesRead;    /* how far are we in the buffer */
                    494:     DWORD           dwMsg = 0;      /* short midi message sent to synth */
                    495:     BYTE            bBytePos=0;     /* shift current byte by dwBytePos*s */
                    496:     BYTE            bBytesLeft = 0; /* how many dat bytes needed */
                    497:     BYTE            curByte;        /* current byte in long buffer */
                    498:     UINT            mRc;            /* Return code */
                    499: 
                    500: #ifdef WIN16
                    501:     if (!fEnabled || gfMidiSuspended) {
                    502:        D1("modMessage called while disabled");
                    503:     } else {
                    504:        if (msg == MODM_GETNUMDEVS)
                    505:        else
                    506:            return MMSYSERR_NOTENABLED;
                    507:     }
                    508: #endif // WIN16
                    509: 
                    510: 
                    511:     // this driver only supports one device
                    512:     if (id != 0) {
                    513:        D1("invalid midi device id");
                    514:        return MMSYSERR_BADDEVICEID;
                    515:     }
                    516: 
                    517:     switch (msg) {
                    518:        case MODM_GETNUMDEVS:
                    519:            D1("MODM_GETNUMDEVS");
                    520: #ifdef WIN16
                    521:         mRc = 1L;
                    522: #else
                    523:         //
                    524:        // Check if the kernel driver got loaded OK
                    525:        //
                    526:        {
                    527:            HANDLE hDevice;
                    528:            if (MidiOpenDevice(&hDevice, FALSE) == MMSYSERR_NOERROR) {
                    529:                 CloseHandle(hDevice);
                    530:                mRc = 1L;
                    531:            } else {
                    532:                mRc = 0L;
                    533:            }
                    534:        }
                    535: #endif // WIN16
                    536:                break;
                    537: 
                    538:        case MODM_GETDEVCAPS:
                    539:            D1("MODM_GETDEVCAPS");
                    540:            modGetDevCaps((LPBYTE)dwParam1, (WORD)dwParam2);
                    541:            mRc = 0L;
                    542:            break;
                    543: 
                    544:        case MODM_OPEN:
                    545:            D1("MODM_OPEN");
                    546: 
                    547:            /* open the midi */
                    548:            if (MidiOpen())
                    549:                return MMSYSERR_ALLOCATED;
                    550: 
                    551:            /* call up the volume control */
                    552: #ifdef WIN16
                    553:            VolSendMsg (FH_MIDI_BEGIN);
                    554: #endif // WIN16
                    555: 
                    556:            // save client information
                    557:            gMidiOutClient.dwCallback = ((LPMIDIOPENDESC)dwParam1)->dwCallback;
                    558:            gMidiOutClient.dwInstance = ((LPMIDIOPENDESC)dwParam1)->dwInstance;
                    559:            gMidiOutClient.hMidi      = ((LPMIDIOPENDESC)dwParam1)->hMidi;
                    560:            gMidiOutClient.dwFlags    = dwParam2;
                    561: 
                    562:            // notify client
                    563:            midiCallback(&gMidiOutClient, MOM_OPEN, 0L, 0L);
                    564: 
                    565:            /* were in use */
                    566:            gbMidiInUse = TRUE;
                    567: 
                    568:            mRc = 0L;
                    569:                break;
                    570: 
                    571:        case MODM_CLOSE:
                    572:            D1("MODM_CLOSE");
                    573: 
                    574:            /* shut up the FM synthesizer */
                    575:            MidiClose();
                    576: 
                    577:            /* tell volume about this */
                    578: #ifdef WIN16
                    579:            VolSendMsg (FH_MIDI_END);
                    580: #endif // WIN16
                    581: 
                    582:            // notify client
                    583:            midiCallback(&gMidiOutClient, MOM_CLOSE, 0L, 0L);
                    584: 
                    585:            /* were not used any more */
                    586:            gbMidiInUse = FALSE;
                    587: 
                    588:            mRc = 0L;
                    589:                break;
                    590: 
                    591:        case MODM_RESET:
                    592:            D1("MODM_RESET");
                    593: 
                    594:             //
                    595:             //  turn off FM synthesis
                    596:             //
                    597:             //  note that we increment our 're-entered' counter so that a
                    598:             //  background interrupt handler doesn't mess up our resetting
                    599:             //  of the synth by calling midiOut[Short|Long]Msg.. just
                    600:             //  practicing safe midi. NOTE: this should never be necessary
                    601:             //  if a midi app is PROPERLY written!
                    602:             //
                    603:            wMidiOutEntered++;
                    604:             {
                    605:                 if (wMidiOutEntered == 1)
                    606:                 {
                    607:                     MidiReset();
                    608:                     dwParam1 = 0L;
                    609:                 }
                    610:                 else
                    611:                 {
                    612:                     D1("MODM_RESET reentered!");
                    613:                     dwParam1 = MIDIERR_NOTREADY;
                    614:                 }
                    615:             }
                    616:            wMidiOutEntered--;
                    617:            mRc = (dwParam1);
                    618:                break;
                    619: 
                    620:        case MODM_DATA:                    // message is in dwParam1
                    621: #ifndef WIN16
                    622:                MidiCheckVolume();                         // See if the volume has changed
                    623: #endif // WIN16
                    624: 
                    625:            // make sure we're not being reentered
                    626:            wMidiOutEntered++;
                    627:            if (wMidiOutEntered > 1) {
                    628:                        D1("MODM_DATA reentered!");
                    629:                        wMidiOutEntered--;
                    630:                        return MIDIERR_NOTREADY;
                    631:                    }
                    632: 
                    633:            /* if have repeated messages */
                    634:            if (dwParam1 & 0x00000080)  /* status byte */
                    635:                        status = LOBYTE(LOWORD(dwParam1));
                    636:            else
                    637:                        dwParam1 = (dwParam1 << 8) | ((DWORD) status);
                    638: 
                    639:            /* if not, have an FM synthesis message */
                    640:            MidiMessage (dwParam1);
                    641: 
                    642:            wMidiOutEntered--;
                    643:            mRc = 0L;
                    644:                break;
                    645: 
                    646:        case MODM_LONGDATA:      // far pointer to header in dwParam1
                    647: 
                    648: #ifndef WIN16
                    649:                MidiCheckVolume();                         // See if the volume has changed
                    650: #endif // WIN16
                    651: 
                    652:            // make sure we're not being reentered
                    653:            wMidiOutEntered++;
                    654:            if (wMidiOutEntered > 1) {
                    655:                        D1("MODM_LONGDATA reentered!");
                    656:                        wMidiOutEntered--;
                    657:                        return MIDIERR_NOTREADY;
                    658:                        }
                    659: 
                    660:            // check if it's been prepared
                    661:            lpHdr = (LPMIDIHDR)dwParam1;
                    662:            if (!(lpHdr->dwFlags & MHDR_PREPARED)) {
                    663:                        wMidiOutEntered--;
                    664:                        return MIDIERR_UNPREPARED;
                    665:                        }
                    666: 
                    667:            lpBuf = lpHdr->lpData;
                    668:            dwBytesRead = 0;
                    669:            curByte = *lpBuf;
                    670: 
                    671:            while (TRUE) {
                    672:                        /* if its a system realtime message send it and continue
                    673:                                this does not affect the running status */
                    674: 
                    675:                        if (curByte >= 0xf8)
                    676:                                MidiMessage (0x000000ff & curByte);
                    677:                        else if (curByte >= 0xf0) {
                    678:                                status = 0;     /* kill running status */
                    679:                                dwMsg = 0L;     /* throw away any incomplete data */
                    680:                                bBytePos = 0;   /* start at beginning of message */
                    681: 
                    682:                                switch (curByte) {
                    683:                                        case 0xf0:      /* sysex - ignore */
                    684:                                        case 0xf7:
                    685:                                                break;
                    686:                                        case 0xf4:      /* system common, no data */
                    687:                                        case 0xf5:
                    688:                                        case 0xf6:
                    689:                                                MidiMessage (0x000000ff & curByte);
                    690:                                                break;
                    691:                                        case 0xf1:      /* system common, one data byte */
                    692:                                        case 0xf3:
                    693:                                                dwMsg |= curByte;
                    694:                                                bBytesLeft = 1;
                    695:                                                bBytePos = 1;
                    696:                                                break;
                    697:                                        case 0xf2:      /* system common, 2 data bytes */
                    698:                                                dwMsg |= curByte;
                    699:                                                bBytesLeft = 2;
                    700:                                                bBytePos = 1;
                    701:                                                break;
                    702:                                        };
                    703:                                }
                    704:                    /* else its a channel message */
                    705:                    else if (curByte >= 0x80) {
                    706:                                status = curByte;
                    707:                                dwMsg = 0L;
                    708: 
                    709:                                switch (curByte & 0xf0) {
                    710:                                        case 0xc0:      /* channel message, one data */
                    711:                                        case 0xd0:
                    712:                                                dwMsg |= curByte;
                    713:                                                bBytesLeft = 1;
                    714:                                                bBytePos = 1;
                    715:                                                break;
                    716:                                        case 0x80:      /* two bytes */
                    717:                                        case 0x90:
                    718:                                        case 0xa0:
                    719:                                        case 0xb0:
                    720:                                        case 0xe0:
                    721:                                                dwMsg |= curByte;
                    722:                                                bBytesLeft = 2;
                    723:                                                bBytePos = 1;
                    724:                                                break;
                    725:                                        };
                    726:                                }
                    727: 
                    728:                        /* else if its an expected data byte */
                    729:                    else if (bBytePos != 0) {
                    730:                                dwMsg |= ((DWORD)curByte) << (bBytePos++ * 8);
                    731:                                if (--bBytesLeft == 0) {
                    732: 
                    733:                                                MidiMessage (dwMsg);
                    734: 
                    735:                                        if (status) {
                    736:                                                dwMsg |= status;
                    737:                                                bBytesLeft = bBytePos - (BYTE)1;
                    738:                                                bBytePos = 1;
                    739:                                                }
                    740:                                        else {
                    741:                                                dwMsg = 0L;
                    742:                                                bBytePos = 0;
                    743:                                                };
                    744:                                        };
                    745:                                };
                    746: 
                    747:            /* read the next byte if there is one */
                    748:            /* remember we have already read and processed one byte that
                    749:             * we have not yet counted- so we need to pre-inc, not post-inc
                    750:             */
                    751:            if (++dwBytesRead >= lpHdr->dwBufferLength) break;
                    752:                curByte = *++lpBuf;
                    753:            };      /* while TRUE */
                    754: 
                    755:            /* return buffer to client */
                    756:            lpHdr->dwFlags |= MHDR_DONE;
                    757:            midiCallback (&gMidiOutClient, MOM_DONE, dwParam1, 0L);
                    758: 
                    759:            wMidiOutEntered--;
                    760:            mRc = 0L;
                    761:                break;
                    762: 
                    763: #ifdef WIN16
                    764:        case MODM_SETVOLUME:
                    765:                gwLinVol[VOL_MIDI][VOL_LEFT] = LOWORD(dwParam1);
                    766:                gwLinVol[VOL_MIDI][VOL_RIGHT] = HIWORD(dwParam1);
                    767:                VolSetMidiVolume (VolLinearToLog ((WORD)dwParam1),
                    768:                        VolLinearToLog ((WORD) (dwParam1 >> 16) ));
                    769:                mRc = 0L;
                    770:                mRc = MidiSetVolume(LOWORD(dwParam1) << 16, HIWORD(dwParam1) << 16);
                    771:                break;
                    772: 
                    773:        case MODM_GETVOLUME:
                    774:                *((DWORD FAR *)dwParam1) =
                    775:                        MAKELONG (
                    776:                                gwLinVol[VOL_MIDI][VOL_LEFT],
                    777:                                gwLinVol[VOL_MIDI][VOL_RIGHT]);
                    778:                mRc = 0L;
                    779:                break;
                    780: #else
                    781:        case MODM_SETVOLUME:
                    782:                mRc = MidiSetVolume(LOWORD(dwParam1) << 16, HIWORD(dwParam1) << 16);
                    783:                break;
                    784: 
                    785:        case MODM_GETVOLUME:
                    786:                mRc = MidiGetVolume((LPDWORD)dwParam1);
                    787:                break;
                    788: #endif // WIN16
                    789: 
                    790: 
                    791: #ifdef FOGHORN
                    792:        case MODM_VUMETER:
                    793:                /* there is a duplicate in auxil.c which must be
                    794:                        kept up to date */
                    795:                /* if we're out of range then 0 volume */
                    796:                if (dwParam1 >= 16) {
                    797:                        *((DWORD FAR *)dwParam2) = 0;
                    798:                        return 0;
                    799:                        };
                    800: 
                    801:                if (!gbMidiInUse) {
                    802:                        *((DWORD FAR *) dwParam2) = 0;
                    803:                        return MMSYSERR_ALLOCATED;
                    804:                        };
                    805: 
                    806:                /* find out what the values are */
                    807:                wTemp1 = (WORD) gbLeftLevel[dwParam1] << 9;
                    808:                wTemp2 = (WORD) gbRightLevel[dwParam1] << 9;
                    809:                gbLeftLevel[dwParam1] = gbRightLevel[dwParam1] = 0;
                    810:                *((DWORD FAR *) dwParam2) = ((DWORD) wTemp2 << 16) | wTemp1;
                    811:                mRc = 0L;
                    812:                break;
                    813: 
                    814:        case MODM_SETPATCH:
                    815:                /* there is a duplicate in auxil.c which must be
                    816:                        kept up to date */
                    817:                wTemp1 = (LOWORD(dwParam2));
                    818:                if (wTemp1 >= 256)
                    819:                        wTemp1 = 0;
                    820:                MidiSetPatch ((BYTE) wTemp1, (LPSTR) dwParam1, HIWORD(dwParam2));
                    821:                mRc = 0L;
                    822:                break;
                    823: 
                    824:        case MODM_GETPATCH:
                    825:                /* there is a duplicate in auxil.c which must be
                    826:                        kept up to date */
                    827:                wTemp1 = (LOWORD(dwParam2));
                    828:                if (wTemp1 >= 256)
                    829:                        wTemp1 = 0;
                    830:                MidiGetPatch ((BYTE) wTemp1, (LPSTR) dwParam1, HIWORD(dwParam2));
                    831:                mRc = 0L;
                    832:                break;
                    833: #endif
                    834:        default:
                    835:            return MMSYSERR_NOTSUPPORTED;
                    836:     }
                    837: #ifndef WIN16
                    838:        MidiFlush();
                    839: #endif // WIN16
                    840: 
                    841:        return mRc;
                    842: 
                    843: 
                    844: // should never get here...
                    845: return MMSYSERR_NOTSUPPORTED;
                    846: }
                    847: 
                    848: 
                    849: static TCHAR BCODE gszDefPatchLib[]          = TEXT("SYNTH.PAT");
                    850: static TCHAR BCODE gszIniKeyPatchLib[]       = INI_STR_PATCHLIB;
                    851: static TCHAR BCODE gszIniDrvSection[]        = INI_DRIVER;
                    852: static TCHAR BCODE gszIniDrvFile[]           = INI_SOUND;
                    853: static TCHAR BCODE gszSysIniSection[]        = TEXT("synth.dll");
                    854: static TCHAR BCODE gszSysIniFile[]           = TEXT("System.Ini");
                    855: 
                    856: 
                    857: 
                    858: 
                    859: /****************************************************************
                    860: MidiInit - Initializes the FM synthesis chip and internal
                    861:         variables. This assumes that HwInit() has been called
                    862:         and that a card location has been found. This loads in
                    863:         the patch information.
                    864: 
                    865: inputs
                    866:         none
                    867: returns
                    868:         WORD - 0 if successful, else error
                    869: */
                    870: WORD FAR PASCAL MidiInit (VOID)
                    871: {
                    872: //    WORD        i;
                    873: 
                    874:     D1 ("\nMidiInit");
                    875: 
                    876: // don't reset the patch map - it will be initialised at loadtime to 0
                    877: // (because its static data) and we should not change it after that
                    878: // since the mci sequencer will not re-send patch change messages.
                    879: //
                    880: //
                    881: //    /* reset all channels to patch 0 */
                    882: //    for (i = 0; i < NUMCHANNELS; i++) {
                    883: //     gbPatch[i] = 0;
                    884: //    }
                    885: 
                    886:     /* initialise the h/w specific patch tables */
                    887:     return MidiBoardInit();
                    888: }
                    889: 
                    890: 
                    891: /*****************************************************************
                    892: MidiOpen - This should be called when a midi file is opened.
                    893:         It initializes some variables and locks the patch global
                    894:         memories.
                    895: 
                    896: inputs
                    897:         none
                    898: returns
                    899:         UINT - 0 if succedes, else error
                    900: */
                    901: UINT FAR PASCAL MidiOpen (VOID)
                    902: {
                    903:     MMRESULT mRc;
                    904: 
                    905:     D1("\nMidiOpen");
                    906: 
                    907: 
                    908:     //
                    909:     // For 32-bit we must open our kernel device
                    910:     //
                    911: 
                    912:     mRc = MidiOpenDevice(&MidiDeviceHandle, TRUE);
                    913: 
                    914:     if (mRc != MMSYSERR_NOERROR) {
                    915:            return mRc;
                    916:     }
                    917: 
                    918: 
                    919:     /*
                    920:      * reset the device (set default channel attenuation etc)
                    921:      */
                    922:     MidiBoardReset();
                    923: 
                    924:     return 0;
                    925: }
                    926: 
                    927: /***************************************************************
                    928: MidiClose - This kills the playing midi voices and closes the kernel driver
                    929: 
                    930: inputs
                    931:         none
                    932: returns
                    933:         none
                    934: */
                    935: VOID FAR PASCAL MidiClose (VOID)
                    936: {
                    937: 
                    938:     D1("\nMidiClose");
                    939: 
                    940:     /* make sure all notes turned off */
                    941:     MidiAllNotesOff();
                    942: 
                    943:     MidiCloseDevice(MidiDeviceHandle);
                    944: }
                    945: 
                    946: /** void FAR PASCAL MidiReset(void)
                    947:  *
                    948:  *  DESCRIPTION:
                    949:  *
                    950:  *
                    951:  *  ARGUMENTS:
                    952:  *      (void)
                    953:  *
                    954:  *  RETURN (void FAR PASCAL):
                    955:  *
                    956:  *
                    957:  *  NOTES:
                    958:  *
                    959:  ** cjp */
                    960: 
                    961: void FAR PASCAL MidiReset(void)
                    962: {
                    963: 
                    964:     D1("\nMidiReset");
                    965: 
                    966:     /* make sure all notes turned off */
                    967:     MidiAllNotesOff();
                    968: 
                    969:     /* silence the board and reset board-specific variables */
                    970:     MidiBoardReset();
                    971: 
                    972: 
                    973: } /* MidiReset() */
                    974: 
                    975: 
                    976: /*****************************************************************************
                    977:  * @doc INTERNAL
                    978:  *
                    979:  * @api void | modGetDevCaps | Get the capabilities of the port.
                    980:  *
                    981:  * @parm LPBYTE | lpCaps | Far pointer to a MIDIOUTCAPS structure.
                    982:  *
                    983:  * @parm UINT | wSize | Size of the MIDIOUTCAPS structure.
                    984:  *
                    985:  * @rdesc There is no return value.
                    986:  ****************************************************************************/
                    987: void FAR PASCAL modGetDevCaps(LPBYTE lpCaps, UINT wSize)
                    988: {
                    989:     MIDIOUTCAPS mc;
                    990: 
                    991:     mc.wMid = MM_MICROSOFT;
                    992:     mc.wPid = MM_ADLIB;
                    993:     mc.wTechnology = MOD_FMSYNTH;
                    994:     mc.wVoices = 128;
                    995: 
                    996:     mc.wChannelMask = 0xffff;                       // all channels
                    997:     mc.vDriverVersion = 0x100;
                    998:     if (gMidiType == TYPE_OPL3) {
                    999:        mc.wNotes = 12;
                   1000:        mc.dwSupport = MIDICAPS_VOLUME | MIDICAPS_LRVOLUME;
                   1001:     } else {
                   1002:        mc.wNotes = 11;
                   1003:        mc.dwSupport = MIDICAPS_VOLUME;
                   1004:     }
                   1005:     LoadString(ghModule, SR_STR_DRIVERMIDIOUT, mc.szPname, sizeof(mc.szPname));
                   1006: 
                   1007:     AsMemCopy(lpCaps, &mc, min(wSize,sizeof(mc)));
                   1008: }
                   1009: 

unix.superglobalmegacorp.com

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