MIDI In 处理流程

1.        枚举所有MIDI In设备

UINT nInCount = midiInGetNumDevs();
    for(int i = 0; i < (int)nInCount; i++)
    {
        MIDIINCAPS midiInCaps = { 0 };
        midiInGetDevCaps(i,&midiInCaps,sizeof(MIDIINCAPS));
        int nIndex = m_midiInCombo.InsertString(i,midiInCaps.szPname);
        if(i == 0 )
            m_midiInCombo.SetCurSel(0);
    }
2.        打开设备

MMRESULT mmResult = midiInOpen(&m_hMidiIn,nID,(DWORD_PTR)IDPMidiInProc,(DWORD_PTR)m_hWnd,CALLBACK_FUNCTION);

3.        准备

            int nSize = sizeof(MIDIHDR);
            memset(&m_midiInHdr,0,nSize);
            m_midiInHdr.dwBytesRecorded = m_midiInHdr.dwBufferLength = 20;
            m_midiInHdr.lpData = new CHAR[20];
            midiInPrepareHeader( m_hMidiIn, &m_midiInHdr, nSize);
            mmResult = midiInAddBuffer(m_hMidiIn,&m_midiInHdr,sizeof(MIDIHDR));
            if(mmResult != 0)
            {
                TCHAR szError[MAX_PATH] = { 0 };
                midiInGetErrorText( mmResult, szError, MAX_PATH);
                TRACE(_T("Error:%s"), szError);
            }

            //midiInUnprepareHeader(m_hMidiIn,&m_midiInHdr,sizeof(MIDIHDR));

            midiInStart(m_hMidiIn);

4.        回调函数

void CALLBACK IDPMidiInProc(HMIDIIN hMidiIn, UINT wMsg,DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
    TRACE(_T("Msg: %d Data: 0x%08x, %d\n"),wMsg,dwParam1,dwParam2);
    HWND hWnd = (HWND)dwInstance;
    switch(wMsg)
    {
    case MIM_OPEN:
        break;
    case MIM_CLOSE:
        break;
    case MIM_DATA:        // Quarter Time code  
        {
            PostMessage(hWnd,WM_CHANGE_MIDI_MTC,dwParam1,0);
        }
        break;
    case MIM_LONGDATA:        // Full Time Code 
        {
            //  dwParam1 is the lpMidiHdr
            //  dwParam2 is the event time in ms since the start of midi in
            LPMIDIHDR hdr = (LPMIDIHDR) dwParam1;
            // sysex: (byte*)hdr->lpData, (int)hdr->dwBytesRecorded
            PostMessage(hWnd,WM_CHANGE_MIDI_MTC,dwParam1,1); // Full TimeCode

            MMRESULT res = ::midiInAddBuffer(hMidiIn, hdr, sizeof(MIDIHDR));
            if(res != 0)
            {
                TCHAR szError[MAX_PATH] = { 0 };
                midiInGetErrorText( res, szError, MAX_PATH);
                TRACE(_T("Error:%s"), szError);
            }
            int a = 0;
        }
        break;
    case MIM_ERROR:
        break;
    case MIM_LONGERROR:
        break;
    case MIM_MOREDATA:
        break;
    }
}

5.        处理消息

LRESULT CMIDITestDlg::OnMidiInChange(WPARAM wParam, LPARAM lParam)
{
    DWORD dwMidiMessage = wParam;
    DWORD dwCmd = lParam;
    if(dwCmd == 0)
    {
        BYTE bState = BYTE(dwMidiMessage);
        if(bState == 0xf1)
        {
            BYTE bData1 = (dwMidiMessage & 0x0000ff00) >> 8;
            BYTE bPos = (bData1 & 0xf0);
            BYTE bNum = (bData1 & 0x0f);
            DWORD dwNum = bNum;
            switch(bPos)
            {
            case TC_FRAME_LS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xfffffff0) | dwNum;
                break;
            case TC_FRAME_MS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xffffff0f) | (dwNum << 4);
                break;
            case TC_SECOND_LS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xfffff0ff) | (dwNum << 8);
                break;
            case TC_SECOND_MS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xffff0fff) | (dwNum << 12);
                break;
            case TC_MINUTE_LS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xfff0ffff) | (dwNum << 16);
                break;
            case TC_MINUTE_MS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xff0fffff) | (dwNum << 20);
                break;
            case TC_HOUR_LS:
                m_dwMIDIIn =  (m_dwMIDIIn & 0xf0ffffff) | (dwNum << 24);
                break;
            case TC_HOUR_MS:
                {
                    BYTE bType = (bNum & 0x06 );
                    if(bType == FRAME24)
                        m_strType = _T("24fps");
                    else if(bType == FRAME25)
                        m_strType = _T("25fps");
                    else if(bType == FRAME30D)
                        m_strType = _T("29.97fps");
                    else if(bType == FRAME30)
                        m_strType = _T("30fps");

                    bNum = bNum & 0x01;

                    dwNum = bNum;
                    m_dwMIDIIn =  (m_dwMIDIIn & 0x0fffffff) | (dwNum << 28);

                    m_strTimeCodeIn.Format(_T("%02d:%02d:%02d:%02d"),
                        ((m_dwMIDIIn &0xff000000)>> 24),((m_dwMIDIIn & 0x00ff0000) >> 16),
                        ((m_dwMIDIIn & 0x0000ff00) >> 8),((m_dwMIDIIn & 0x000000ff) >> 0));
                    GetDlgItem(IDC_MIDI_MTC)->SetWindowText(m_strTimeCodeIn);
                    GetDlgItem(IDC_MIDI_MTC2)->SetWindowText(m_strType);
                }
                break;
            }
        }
    }
    else if(dwCmd == 1)
    {
        LPMIDIHDR hdr = (LPMIDIHDR)wParam;
        UINT nHour = 0, nMinute = 0, nSecond = 0, nFrame = 0, nType = 0;
        if(hdr->dwBytesRecorded >= 10 && CMIDICtrl::ParseCmdTimeCode((BYTE*)hdr->lpData, hdr->dwBytesRecorded, nHour, nMinute, nSecond, nFrame, nType))
        {
            int a = 0;
            m_dwMIDIIn = (nHour << 24) | (nMinute << 16) | (nSecond << 8) | (nFrame << 0);

            if(nType == FRAME24)
                m_strType = _T("24fps");
            else if(nType == FRAME25)
                m_strType = _T("25fps");
            else if(nType == FRAME30D)
                m_strType = _T("29.97fps");
            else if(nType == FRAME30)
                m_strType = _T("30fps");

            m_strTimeCodeIn.Format(_T("%02d:%02d:%02d:%02d"),
                ((m_dwMIDIIn &0xff000000)>> 24),((m_dwMIDIIn & 0x00ff0000) >> 16),
                ((m_dwMIDIIn & 0x0000ff00) >> 8),((m_dwMIDIIn & 0x000000ff) >> 0));
            GetDlgItem(IDC_MIDI_MTC)->SetWindowText(m_strTimeCodeIn);
            GetDlgItem(IDC_MIDI_MTC2)->SetWindowText(m_strType);

        }
    }
    return 1;
}

#define SOX                                0xF0        // Command Head Flag
#define EOX                                0xF7        // Command End Flag

#define SUBID1_NON_RT                    0x7E        // Non-Realtime SUBID1
#define SUBID1_RT                        0x7F        // RealTime SUBID1
// Frame Format for Timecode hr mn sc fr ff
#define FRAME24                            0x00
#define FRAME25                            0x20
#define FRAME30D                        0x40
#define FRAME30                            0x60

BOOL ParseCmdTimeCode(BYTE * pData, UINT nSize, UINT &nHour, UINT &nMinute, UINT &nSecond, UINT &nFrame, UINT &nType)
{

        // SOX = 0xF0

        // EOX = 0xF7
    if(pData[0] == SOX && pData[1] == SUBID1_RT && pData[3] == 0x01 && pData[4] == 0x01 && pData[9] == EOX)
    {
        nType = (pData[5] & 0x60);
        nHour = pData[5] & 0x1f;
        nMinute = pData[6];
        nSecond = pData[7];
        nFrame = pData[8];
        return TRUE;
    }
    return FALSE;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值