Annotation of ntddk/src/mmedia/synth/dll/midi.c, revision 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.