示例#1
0
void MidiUartWinClass::midiSendShort(unsigned char status,
																		 unsigned char byte1, unsigned char byte2) {
	midiOutShortMsg(outHandle, MAKE_SHORT_MSG(status, byte1, byte2));
}
示例#2
0
void midi_Instrument(HMIDIOUT * midiout, int chn, int inst)
{
		if (inst<128) midiOutShortMsg(*midiout, 256*inst+191+chn);
		// 1-127: Instruments for noteOn,  128 - 255: Controller numbers
}
示例#3
0
文件: midi.c 项目: thomcom/wine
static void test_midiOut_device(UINT udev, HWND hwnd)
{
    HMIDIOUT hm;
    MMRESULT rc;
    MIDIOUTCAPSA capsA;
    DWORD ovolume;
    UINT  udevid;
    MIDIHDR mhdr;

    rc = midiOutGetDevCapsA(udev, &capsA, sizeof(capsA));
    ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (!rc) {
        trace("* %s: manufacturer=%d, product=%d, tech=%d, support=%X: %d voices, %d notes\n",
              capsA.szPname, capsA.wMid, capsA.wPid, capsA.wTechnology, capsA.dwSupport, capsA.wVoices, capsA.wNotes);
        ok(!((MIDIMAPPER==udev) ^ (MOD_MAPPER==capsA.wTechnology)), "technology %d on device %d\n", capsA.wTechnology, udev);
        if (MOD_MIDIPORT == capsA.wTechnology) {
            ok(capsA.wVoices == 0 && capsA.wNotes == 0, "external device with notes or voices\n");
            ok(capsA.wChannelMask == 0xFFFF, "external device channel mask %x\n", capsA.wChannelMask);
            ok(!(capsA.dwSupport & (MIDICAPS_VOLUME|MIDICAPS_LRVOLUME|MIDICAPS_CACHE)), "external device support=%X\n", capsA.dwSupport);
        }
    }

    if (hwnd)
        rc = midiOutOpen(&hm, udev, (DWORD_PTR)hwnd, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW);
    else
        rc = midiOutOpen(&hm, udev, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION);
    if (rc == MMSYSERR_NOTSUPPORTED)
    {
        skip( "MIDI out not supported\n" );
        return;
    }
    ok(!rc, "midiOutOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (rc) return;

    test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0);

    rc = midiOutGetVolume(hm, &ovolume);
    ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume rc=%s\n", mmsys_error(rc));
    /* The native mapper responds with FFFFFFFF initially,
     * real devices with the volume GUI SW-synth settings. */
    if (!rc) trace("Current volume %x on device %d\n", ovolume, udev);

    /* The W95 ESFM Synthesis device reports NOTENABLED although
     * GetVolume by handle works and music plays. */
    rc = midiOutGetVolume(UlongToHandle(udev), &ovolume);
    ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_NOTENABLED) : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume(dev=%d) rc=%s\n", udev, mmsys_error(rc));

    rc = midiOutGetVolume(hm, NULL);
    ok(rc==MMSYSERR_INVALPARAM, "midiOutGetVolume NULL rc=%s\n", mmsys_error(rc));

    /* Tests with midiOutSetvolume show that the midi mapper forwards
     * the value to the real device, but Get initially always reports
     * FFFFFFFF.  Therefore, a Get+SetVolume pair with the mapper is
     * not adequate to restore the value prior to tests.
     */
    if (winetest_interactive && (capsA.dwSupport & MIDICAPS_VOLUME)) {
        DWORD volume2 = (ovolume < 0x80000000) ? 0xC000C000 : 0x40004000;
        rc = midiOutSetVolume(hm, volume2);
        ok(!rc, "midiOutSetVolume rc=%s\n", mmsys_error(rc));
        if (!rc) {
            DWORD volume3;
            rc = midiOutGetVolume(hm, &volume3);
            ok(!rc, "midiOutGetVolume new rc=%s\n", mmsys_error(rc));
            if (!rc) trace("New volume %x on device %d\n", volume3, udev);
            todo_wine ok(volume2==volume3, "volume Set %x = Get %x\n", volume2, volume3);

            rc = midiOutSetVolume(hm, ovolume);
            ok(!rc, "midiOutSetVolume restore rc=%s\n", mmsys_error(rc));
        }
    }
    rc = midiOutGetDevCapsA((UINT_PTR)hm, &capsA, sizeof(capsA));
    ok(!rc, "midiOutGetDevCaps(dev=%d) by handle rc=%s\n", udev, mmsys_error(rc));
    rc = midiInGetDevCapsA((UINT_PTR)hm, (LPMIDIINCAPSA)&capsA, sizeof(DWORD));
    ok(rc==MMSYSERR_BADDEVICEID, "midiInGetDevCaps(dev=%d) by out handle rc=%s\n", udev, mmsys_error(rc));

    {   DWORD e = 0x006F4893; /* velocity, note (#69 would be 440Hz) channel */
        trace("ShortMsg type %x\n", LOBYTE(LOWORD(e)));
        rc = midiOutShortMsg(hm, e);
        ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc));
        if (!rc) Sleep(400); /* Hear note */
    }

    memset(&mhdr, 0, sizeof(mhdr));
    mhdr.dwFlags = MHDR_DONE;
    mhdr.dwUser   = 0x56FA552C;
    mhdr.dwOffset = 0xDEADBEEF;
    mhdr.dwBufferLength = 70000; /* > 64KB! */
    mhdr.lpData = HeapAlloc(GetProcessHeap(), 0 , mhdr.dwBufferLength);
    ok(mhdr.lpData!=NULL, "No %d bytes of memory!\n", mhdr.dwBufferLength);
    if (mhdr.lpData) {
        rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr));
        ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%x\n", mhdr.dwFlags);
        test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER);

        rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1);
        ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%x\n", mhdr.dwFlags);

        /* Since at least w2k, midiOutPrepare clears the DONE and INQUEUE flags.  w95 didn't. */
        /* mhdr.dwFlags |= MHDR_INQUEUE; would cause w95 to return STILLPLAYING from Unprepare */
        rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE)/*w9x*/ ||
           mhdr.dwFlags == MHDR_PREPARED, "dwFlags=%x\n", mhdr.dwFlags);
        trace("MIDIHDR flags=%x when unsent\n", mhdr.dwFlags);

        /* No flag is cleared when already prepared. */
        mhdr.dwFlags |= MHDR_DONE|MHDR_INQUEUE;
        rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE|MHDR_INQUEUE), "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags |= MHDR_INQUEUE;
        rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(rc==MIDIERR_STILLPLAYING, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE|MHDR_INQUEUE), "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags &= ~MHDR_INQUEUE;
        rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%x\n", mhdr.dwFlags);

        mhdr.dwFlags |= MHDR_INQUEUE;
        rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags == (MHDR_INQUEUE|MHDR_DONE), "dwFlags=%x\n", mhdr.dwFlags);

        HeapFree(GetProcessHeap(), 0, mhdr.lpData);
    }
    ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser);
    ok(mhdr.dwOffset==0xDEADBEEF, "MIDIHDR.dwOffset changed to %x\n", mhdr.dwOffset);

    rc = midiOutGetID(hm, &udevid);
    ok(!rc, "midiOutGetID rc=%s\n", mmsys_error(rc));
    if(!rc) ok(udevid==udev, "midiOutGetID gives %d, expect %d\n", udevid, udev);

    rc = midiOutReset(hm); /* Quiet everything */
    ok(!rc, "midiOutReset rc=%s\n", mmsys_error(rc));

    rc = midiOutClose(hm);
    ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc));
    test_notification(hwnd, "midiOutClose", MOM_CLOSE, 0);

    rc = midiOutOpen(&hm, udev, 0, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW);
    /* w95 broken(rc==MMSYSERR_INVALPARAM) see WINMM_CheckCallback */
    ok(!rc, "midiOutOpen(dev=%d) 0 CALLBACK_WINDOW rc=%s\n", udev, mmsys_error(rc));
    /* PostMessage(hwnd=0) redirects to PostThreadMessage(GetCurrentThreadId())
     * which PeekMessage((HWND)-1) queries. */
    test_notification((HWND)-1, "midiOutOpen WINDOW->THREAD", 0, WHATEVER);
    test_notification(hwnd, "midiOutOpen WINDOW", 0, WHATEVER);
    if (!rc) {
        rc = midiOutClose(hm);
        ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc));
        test_notification((HWND)-1, "midiOutClose WINDOW->THREAD", 0, WHATEVER);
        test_notification(hwnd, "midiOutClose", 0, WHATEVER);
    }
    test_notification(hwnd, "midiOut over", 0, WHATEVER);
}
示例#4
0
static void midi_win32short(CMMIDI midi, UINT32 msg) {

	waitlastexclusiveout(midi);
	midiOutShortMsg(midi->out.win32.hmidiout, (DWORD)msg);
}
示例#5
0
文件: midi.c 项目: 173210/px68k
// -----------------------------------------------------------------------
//   メッセージ判別
// -----------------------------------------------------------------------
void MIDI_Message(BYTE mes) {

	if (!hOut) {
		return;
	}

	switch(mes) {								// ここの対応はお好みで
		case MIDI_TIMING:
		case MIDI_START:
		case MIDI_CONTINUE:
		case MIDI_STOP:
		case MIDI_ACTIVESENSE:
			return;
		case MIDI_SYSTEMRESET:					// 一応イリーガル〜
			return;
	}

	if (MIDI_CTRL == MIDICTRL_READY) {			// 初回限定
		if (mes & 0x80) {
			// status
			MIDI_POS = 0;
			switch(mes & 0xf0) {
				case 0xc0:
				case 0xd0:
					MIDI_CTRL = MIDICTRL_2BYTES;
					break;
				case 0x80:
				case 0x90:
				case 0xa0:
				case 0xb0:
				case 0xe0:
					MIDI_LAST = mes;			// この方が失敗しないなり…
					MIDI_CTRL = MIDICTRL_3BYTES;
					break;
				default:
					switch(mes) {
						case MIDI_EXCLUSIVE:
							MIDI_CTRL = MIDICTRL_EXCLUSIVE;
							break;
						case MIDI_TIMECODE:
							MIDI_CTRL = MIDICTRL_TIMECODE;
							break;
						case MIDI_SONGPOS:
							MIDI_CTRL = MIDICTRL_SYSTEM;
							MIDI_SYSCOUNT = 3;
							break;
						case MIDI_SONGSELECT:
							MIDI_CTRL = MIDICTRL_SYSTEM;
							MIDI_SYSCOUNT = 2;
							break;
						case MIDI_TUNEREQUEST:
							MIDI_CTRL = MIDICTRL_SYSTEM;
							MIDI_SYSCOUNT = 1;
							break;
						default:
							return;
					}
					break;
			}
		}
		else {						// Key-onのみな気がしたんだけど忘れた…
			// running status
			MIDI_BUF[0] = MIDI_LAST;
			MIDI_POS = 1;
			MIDI_CTRL = MIDICTRL_3BYTES;
		}
	}
	else if ( (mes&0x80) && ((MIDI_CTRL!=MIDICTRL_EXCLUSIVE)||(mes!=MIDI_EOX)) )
	{			// メッセージのデータ部にコントロールバイトが出た時…(GENOCIDE2)
		// status
		MIDI_POS = 0;
		switch(mes & 0xf0) {
			case 0xc0:
			case 0xd0:
				MIDI_CTRL = MIDICTRL_2BYTES;
				break;
			case 0x80:
			case 0x90:
			case 0xa0:
			case 0xb0:
			case 0xe0:
				MIDI_LAST = mes;			// この方が失敗しないなり…
				MIDI_CTRL = MIDICTRL_3BYTES;
				break;
			default:
				switch(mes) {
					case MIDI_EXCLUSIVE:
						MIDI_CTRL = MIDICTRL_EXCLUSIVE;
						break;
					case MIDI_TIMECODE:
						MIDI_CTRL = MIDICTRL_TIMECODE;
						break;
					case MIDI_SONGPOS:
						MIDI_CTRL = MIDICTRL_SYSTEM;
						MIDI_SYSCOUNT = 3;
						break;
					case MIDI_SONGSELECT:
						MIDI_CTRL = MIDICTRL_SYSTEM;
						MIDI_SYSCOUNT = 2;
						break;
					case MIDI_TUNEREQUEST:
						MIDI_CTRL = MIDICTRL_SYSTEM;
						MIDI_SYSCOUNT = 1;
						break;
					default:
						return;
				}
				break;
		}
	}

	MIDI_BUF[MIDI_POS++] = mes;

	switch(MIDI_CTRL) {
		case MIDICTRL_2BYTES:
			if (MIDI_POS >= 2) {
				if (ENABLE_TONEMAP) {
					if (((MIDI_BUF[0] & 0xf0) == 0xc0) &&
						(TONE_CH[MIDI_BUF[0] & 0x0f] < MIMPI_RHYTHM)) {
						MIDI_BUF[1] = TONEMAP[ TONE_CH[MIDI_BUF[0] & 0x0f] ][ MIDI_BUF[1] & 0x7f ];
					}
				}
				MIDI_Waitlastexclusiveout();
				midiOutShortMsg(hOut, MIDIOUTS(MIDI_BUF[0], MIDI_BUF[1], 0));
				MIDI_CTRL = MIDICTRL_READY;
			}
			break;
		case MIDICTRL_3BYTES:
			if (MIDI_POS >= 3) {
				MIDI_Waitlastexclusiveout();
				midiOutShortMsg(hOut, 
							MIDIOUTS(MIDI_BUF[0], MIDI_BUF[1], MIDI_BUF[2]));
				MIDI_CTRL = MIDICTRL_READY;
			}
			break;
		case MIDICTRL_EXCLUSIVE:
			if (mes == MIDI_EOX) {
				MIDI_Waitlastexclusiveout();
				MIDI_Sendexclusive(MIDI_BUF, MIDI_POS);
				MIDI_CTRL = MIDICTRL_READY;
			}
			else if (MIDI_POS >= MIDIBUFFERS) {		// おーばーふろー
				MIDI_CTRL = MIDICTRL_READY;
			}
			break;
		case MIDICTRL_TIMECODE:
			if (MIDI_POS >= 2) {
				if ((mes == 0x7e) || (mes == 0x7f)) {
					// exclusiveと同じでいい筈…
					MIDI_CTRL = MIDICTRL_EXCLUSIVE;
				}
				else {
					MIDI_CTRL = MIDICTRL_READY;
				}
			}
			break;
		case MIDICTRL_SYSTEM:
			if (MIDI_POS >= MIDI_SYSCOUNT) {
				MIDI_CTRL = MIDICTRL_READY;
			}
			break;
	}
}
示例#6
0
static void midi_flush_current_buffer(void)
{
    MMRESULT rv;
    MIDIEVENT * evt;
    BOOL needsPrepare = FALSE;

    if (!currentMidiBuffer) {
        return;
    }

    evt = (MIDIEVENT *) currentMidiBuffer->hdr.lpData;

    if (!midiThread) {
        // immediate messages don't use a MIDIEVENT header so strip it off and
        // make some adjustments

        currentMidiBuffer->hdr.dwBufferLength = currentMidiBuffer->hdr.dwBytesRecorded - 12;
        currentMidiBuffer->hdr.dwBytesRecorded = 0;
        currentMidiBuffer->hdr.lpData = (LPSTR) &evt->dwParms[0];
        
        if (currentMidiBuffer->hdr.dwBufferLength > 0) {
            needsPrepare = TRUE;
        }
    } else {
        needsPrepare = TRUE;
    }
    
    if (needsPrepare) {
        // playing a file, or sending a sysex when not playing means
        // we need to prepare the buffer
        rv = midiOutPrepareHeader( (HMIDIOUT) midiStream, &currentMidiBuffer->hdr, sizeof(MIDIHDR) );
        if (rv != MMSYSERR_NOERROR) {
            midi_error(rv, "WinMM midi_flush_current_buffer midiOutPrepareHeader");
            return;
        }

        currentMidiBuffer->prepared = TRUE;
    }

    if (midiThread) {
        // midi file playing, so send events to the stream

        LL_Add( (MidiBuffer*) &activeMidiBuffers, currentMidiBuffer, next, prev );

        rv = midiStreamOut(midiStream, &currentMidiBuffer->hdr, sizeof(MIDIHDR));
        if (rv != MMSYSERR_NOERROR) {
            midi_error(rv, "WinMM midi_flush_current_buffer midiStreamOut");
            midi_dispose_buffer(currentMidiBuffer, "midi_flush_current_buffer");
            return;
        }

        //fprintf(stderr, "WinMM midi_flush_current_buffer queued buffer %p\n", currentMidiBuffer);
    } else {
        // midi file not playing, so send immediately
        
        if (currentMidiBuffer->hdr.dwBufferLength > 0) {
            rv = midiOutLongMsg( (HMIDIOUT) midiStream, &currentMidiBuffer->hdr, sizeof(MIDIHDR) );
            if (rv == MMSYSERR_NOERROR) {
                // busy-wait for Windows to be done with it
                while (!(currentMidiBuffer->hdr.dwFlags & MHDR_DONE)) ;
                
                //fprintf(stderr, "WinMM midi_flush_current_buffer sent immediate long\n");
            } else {
                midi_error(rv, "WinMM midi_flush_current_buffer midiOutLongMsg");
            }
        } else {
            rv = midiOutShortMsg( (HMIDIOUT) midiStream, evt->dwEvent );
            if (rv == MMSYSERR_NOERROR) {
                //fprintf(stderr, "WinMM midi_flush_current_buffer sent immediate short\n");
            } else {
                midi_error(rv, "WinMM midi_flush_current_buffer midiOutShortMsg");
            }
        }

        midi_dispose_buffer(currentMidiBuffer, "midi_flush_current_buffer");
    }
    
    currentMidiBuffer = 0;
}
示例#7
0
void WinMIDIDevice::PrecacheInstruments(const uint16_t *instruments, int count)
{
	// Setting snd_midiprecache to false disables this precaching, since it
	// does involve sleeping for more than a miniscule amount of time.
	if (!snd_midiprecache)
	{
		return;
	}
	uint8_t bank[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	int i, chan;

	for (i = 0, chan = 0; i < count; ++i)
	{
		int instr = instruments[i] & 127;
		int banknum = (instruments[i] >> 7) & 127;
		int percussion = instruments[i] >> 14;

		if (percussion)
		{
			if (bank[9] != banknum)
			{
				midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (banknum << 16));
				bank[9] = banknum;
			}
			midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | 9 | ((instruments[i] & 0x7f) << 8) | (1 << 16));
		}
		else
		{ // Melodic
			if (bank[chan] != banknum)
			{
				midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (banknum << 16));
				bank[chan] = banknum;
			}
			midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_PRGMCHANGE | chan | (instruments[i] << 8));
			midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_NOTEON | chan | (60 << 8) | (1 << 16));
			if (++chan == 9)
			{ // Skip the percussion channel
				chan = 10;
			}
		}
		// Once we've got an instrument playing on each melodic channel, sleep to give
		// the driver time to load the instruments. Also do this for the final batch
		// of instruments.
		if (chan == 16 || i == count - 1)
		{
			Sleep(250);
			for (chan = 15; chan-- != 0; )
			{
				// Turn all notes off
				midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | chan | (123 << 8));
			}
			// And now chan is back at 0, ready to start the cycle over.
		}
	}
	// Make sure all channels are set back to bank 0.
	for (i = 0; i < 16; ++i)
	{
		if (bank[i] != 0)
		{
			midiOutShortMsg((HMIDIOUT)MidiOut, MIDI_CTRLCHANGE | 9 | (0 << 8) | (0 << 16));
		}
	}
}
示例#8
0
Synthesizer::Synthesizer(int instrument)
{
	midiOutOpen(&device, -1, 0, 0, 0);
	// Set instrument to 0 = Acoustic Grand Piano
	midiOutShortMsg(device, DWORD(0x0C0 | 0 | (instrument << 8) | (0 << 16)));
}
示例#9
0
static DWORD modData(MIDIMAPDATA* mom, DWORD_PTR dwParam)
{
    BYTE	lb = LOBYTE(LOWORD(dwParam));
    WORD	chn = lb & 0x0F;
    DWORD	ret = MMSYSERR_NOERROR;

    if (MIDIMAP_IsBadData(mom))
	return MMSYSERR_ERROR;

    if (!mom->ChannelMap[chn]) return MMSYSERR_NOERROR;

    switch (lb & 0xF0)
    {
    case 0x80:
    case 0x90:
    case 0xA0:
    case 0xB0:
    case 0xC0:
    case 0xD0:
    case 0xE0:
	if (mom->ChannelMap[chn]->loaded == 0)
	{
	    if (midiOutOpen(&mom->ChannelMap[chn]->hMidi, mom->ChannelMap[chn]->uDevID,
			    0L, 0L, CALLBACK_NULL) == MMSYSERR_NOERROR)
		mom->ChannelMap[chn]->loaded = 1;
	    else
		mom->ChannelMap[chn]->loaded = -1;
	    /* FIXME: should load here the IDF midi data... and allow channel and
	     * patch mappings
	     */
	}
	if (mom->ChannelMap[chn]->loaded > 0)
	{
	    /* change channel */
	    dwParam &= ~0x0F;
	    dwParam |= mom->ChannelMap[chn]->aChn[chn];

	    if ((LOBYTE(LOWORD(dwParam)) & 0xF0) == 0xC0 /* program change */ &&
		mom->ChannelMap[chn]->lpbPatch)
	    {
		BYTE patch = HIBYTE(LOWORD(dwParam));

		/* change patch */
		dwParam &= ~0x0000FF00;
		dwParam |= mom->ChannelMap[chn]->lpbPatch[patch];
	    }
	    ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam);
	}
	break;
    case 0xF0:
	for (chn = 0; chn < 16; chn++)
	{
	    if (mom->ChannelMap[chn]->loaded > 0)
		ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam);
	}
	break;
    default:
	FIXME("ooch %lx\n", dwParam);
    }

    return ret;
}
示例#10
0
void midiSendShort(unsigned char status, unsigned char byte1, unsigned char byte2) {
  debugPrintf(2, "midiSendShort %x %x %x\n", status, byte1, byte2);
  midiOutShortMsg(outHandle, MAKE_SHORT_MSG(status, byte1, byte2));
}
示例#11
0
void CMidiDevice::Out (WORD wPort_, BYTE bVal_)
{
    // Protect against very long System Exclusive blocks
    if ((m_nOut == (sizeof(m_abOut)-1)) && bVal_ != 0xf7)
    {
        TRACE("!!! MIDI: System Exclusive buffer overflow, discarding %#02x\n", bVal_);
        return;
    }

    // Do we have the start of a message while an incomplete message remains?
    if (m_nOut && (bVal_ & 0x80))
    {
        TRACE("!!! MIDI: Discarding incomplete %d byte message\n", m_nOut);
        m_nOut = 0;
    }

    // Is the start of the message a non-status byte?
    else if (!m_nOut && !(bVal_ & 0x80))
    {
        // Use the previous status byte if there is one
        if (m_abOut[0] & 0x80)
            m_nOut = 1;

        // Discard the byte as there isn't much we can do with it
        else
        {
            TRACE("!!! MIDI: Discarding leading non-status byte: %#02x\n", bVal_);
            return;
        }
    }

    // Add the new byte to the message we're building up
    m_abOut[m_nOut++] = bVal_;

    // Spot the end of a System Exclusive variable length block (we don't do anything with it yet)
    if (m_abOut[0] == 0xf0 && bVal_ == 0xf7)
        TRACE("MIDI: Variable block of %d bytes\n", m_nOut - 2);

    // Break out if the command we're building up hasn't got the required number of parameters yet
    else if (((m_abOut[0] & 0xfd) == 0xf1) || ((m_abOut[0] & 0xe0) == 0xc0))    // 1 byte
    {
        if (m_nOut != 2)
            return;
    }
    else if ((m_abOut[0] & 0xf0) == 0xf0)   // 0 bytes
    {
        if (m_nOut != 1)
            return;
    }
    else
    {
        if (m_nOut != 3)
            return;
    }

#ifdef _DEBUG
    switch (m_nOut)
    {
        case 1:     TRACE("MIDI: Sending 1 byte message from: %02x\n", m_abOut[0]);                                                         break;
        case 2:     TRACE("MIDI: Sending 2 byte message from: %02x %02x\n", m_abOut[0], m_abOut[1]);                                            break;
        case 3:     TRACE("MIDI: Sending 3 byte message from: %02x %02x %02x\n", m_abOut[0], m_abOut[1], m_abOut[2]);                               break;
        case 4:     TRACE("MIDI: Sending 4 byte message from: %02x %02x %02x %02x\n", m_abOut[0], m_abOut[1], m_abOut[2], m_abOut[3]);              break;
        default:    TRACE("MIDI: Sending %d byte message from: %02x %02x %02x %02x ...\n", m_nOut, m_abOut[0], m_abOut[1], m_abOut[2], m_abOut[3]); break;
    }
#endif

    // Output the MIDI message
    if (m_hMidiOut)
        midiOutShortMsg(m_hMidiOut, *reinterpret_cast<DWORD*>(&m_abOut));

    // Prepare for the next message, clearing out
    m_nOut = m_abOut[1] = m_abOut[2] = m_abOut[3] = 0;
}