home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vbmidi / midihook.frm (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1995-02-04  |  15.6 KB  |  284 lines

  1. VERSION 2.00
  2. Begin Form frmMidiHook 
  3.    BackColor       =   &H00C0C0C0&
  4.    BorderStyle     =   3  'Fixed Double
  5.    Caption         =   "Midi Hook"
  6.    ClientHeight    =   615
  7.    ClientLeft      =   645
  8.    ClientTop       =   7725
  9.    ClientWidth     =   2010
  10.    ControlBox      =   0   'False
  11.    Height          =   1020
  12.    Left            =   585
  13.    LinkTopic       =   "Form1"
  14.    MaxButton       =   0   'False
  15.    MinButton       =   0   'False
  16.    ScaleHeight     =   615
  17.    ScaleWidth      =   2010
  18.    Top             =   7380
  19.    Width           =   2130
  20.    Begin MsgHook MidiHook 
  21.       Left            =   690
  22.       Top             =   120
  23.    End
  24. Option Explicit
  25. Dim iLoNibble As Integer
  26. Dim iHiNibble As Integer
  27. Dim iMtcHours As Integer
  28. Dim iMtcMinutes As Integer
  29. Dim iMtcSeconds As Integer
  30. Dim iMtcFrames  As Integer
  31. Sub MidiHook_Message (iMsg As Integer, iRet1 As Integer, lMidiMessage As Long, iRet2 As Integer, lRet3 As Long)
  32.  Dim iMidiStatus As Integer
  33.     Dim iMidiData1 As Integer
  34.     Dim iMidiData2 As Integer
  35.     Dim iMtcData As Integer
  36.     Dim lTotalFrames As Long
  37.     'The code inside this Procedure must be selfcontained
  38.     'without calling any other Procedure or DoEvents or Refresh...
  39.     '
  40.     'The whole Procedure execution should not take longer than 8ms.
  41.     '
  42.     'This version seems very long but the program
  43.     'actually only executes a few lines of it
  44.     'based on the Ifs.. and Select Cases... decissions
  45.     If iMsg <> MIM_DATA Then Exit Sub    'just for safety
  46.     'Unpack lMidiMessage
  47.     iMidiStatus = lMidiMessage And &HFF&            'First byte
  48.     iMidiData1 = (lMidiMessage And &HFF00&) / 256   'Second byte
  49.     iMidiData2 = (lMidiMessage And &HFF0000) / 65536'Third byte
  50.     'Filter RealTime Midi Messages except MTC
  51.     If iMidiStatus >= &HF0 And iMidiStatus <> MTC_QFRAME Then Exit Sub
  52.     'Filter here any other Status if necessary.
  53.     '(i.e. PITCH_BEND, CHANNEL_PRESSURE, POLY_KEY_PRESS, etc.)
  54.     If iMidiStatus = MTC_QFRAME Then    'Hooked message is a MTC quarter frame message
  55.        'You may show here a screen representation of MTC In.
  56.        '********************************************
  57.        'SPECIFIC TO THIS APPLICATION
  58.         If bVisualMtc = True Then
  59.             If frmVBSeq.picMtcIn.BackColor = LED_OFF Then  'If MTC In led is off
  60.                 frmVBSeq.picMtcIn.BackColor = LED_ON       'Switch MTC In led on
  61.             End If
  62.             lMtcInTime = timeGetTime()   'Save current system time for switch off calculations
  63.         End If
  64.        '********************************************
  65.         If bMTCThru = True Then         'Global Flag
  66.             If hMidiOut <> NO_HANDLE Then    'If iOutDevice Opened...
  67.                 vntRet = midiOutShortMsg(hMidiOut, lMidiMessage)   'send it out
  68.                'You may show here a screen representation of MTC Out.
  69.                '**********************************************
  70.                'SPECIFIC TO THIS APPLICATION
  71.                 If bVisualMtc = True Then
  72.                     If frmVBSeq.picMtcOut.BackColor = LED_OFF Then  'If MTC Out led is off
  73.                         frmVBSeq.picMtcOut.BackColor = LED_ON       'Switch MTC Out led on
  74.                     End If
  75.                     lMtcOutTime = timeGetTime()  'Save current system time for switch off calculations
  76.                 End If
  77.                '**********************************************
  78.             End If
  79.         End If
  80.         'We're only interested in decoding MTC while we are in external sync
  81.         If nSyncMode = SYNC_EXTERNAL Then
  82.             'MTC Data=Second Byte of lMidiMessage
  83.             iMtcData = iMidiData1
  84.             'Quarter Frame Message Identifier=hiNibble of iMtcData
  85.             Select Case (iMtcData And &HF0)
  86.                 Case &H0:       'Quarter Frame Message indicating Frames loNibble
  87.                     If nQfIdExpected <> &H0 Then   'Discontinous MTC
  88.                         bInSync = False            'Out of sync
  89.                         nQfIdExpected = &H0        'start over
  90.                     Else
  91.                         'Frames loNibble=loNibble of iMtcData
  92.                         iLoNibble = (iMtcData And &HF)
  93.                         'If we're in sync, increase Time Counter (milliseconds per quarter frame)
  94.                         If bInSync = True Then lMtcTime = lMtcTime + fMsPerQF
  95.                         nQfIdExpected = &H10    'Expected next Quarter Frame Message
  96.                     End If
  97.                 Case &H10:        'Quarter Frame Message indicating Frames hiNibble
  98.                     If nQfIdExpected <> &H10 Then   'Discontinous MTC
  99.                         bInSync = False             'Out of sync
  100.                         nQfIdExpected = &H0         'start over
  101.                     Else
  102.                         'Frames hiNibble=Bit 0 of iMtcData
  103.                         iHiNibble = (iMtcData And &H1)
  104.                         iMtcFrames = (iHiNibble * 16) + iLoNibble   'Pack Frame Number
  105.                         'If we're in sync, increase Time Counter
  106.                         If bInSync = True Then lMtcTime = lMtcTime + fMsPerQF
  107.                         nQfIdExpected = &H20     'Expected next Quarter Frame Message
  108.                     End If
  109.                 Case &H20:          'Quarter Frame Message indicating seconds loNibble
  110.                     If nQfIdExpected <> &H20 Then   'Discontinous MTC -> resync
  111.                         bInSync = False             'Out of sync
  112.                         nQfIdExpected = &H0         'start over
  113.                     Else
  114.                         'Seconds LoNibble=LoNibble of iMtcData
  115.                         iLoNibble = (iMtcData And &HF)
  116.                         'If we're in sync, increase Time Counter
  117.                         If bInSync = True Then lMtcTime = lMtcTime + fMsPerQF
  118.                         nQfIdExpected = &H30    'Expected next Quarter Frame Message
  119.                     End If
  120.                 Case &H30:          'Quarter Frame Message indicating seconds hiNibble
  121.                     If nQfIdExpected <> &H30 Then     'Discontinous MTC -> resync
  122.                         bInSync = False               'Out of sync
  123.                         nQfIdExpected = &H0           'start over
  124.                     Else
  125.                         'Seconds HiNibble=bits 0 & 1 of iMtcData
  126.                         iHiNibble = (iMtcData And &H3)
  127.                         iMtcSeconds = (iHiNibble * 16) + iLoNibble  'pack Seconds Number
  128.                         'If we're in sync...
  129.                         If bInSync = True Then
  130.                             'increase Time Counter
  131.                             lMtcTime = lMtcTime + fMsPerQF
  132.                             '4th quarter frame->Increase Frame Counter
  133.                             nMtcTotalFrames = nMtcTotalFrames + 1
  134.                         End If
  135.                         nQfIdExpected = &H40    'Expected next Quarter Frame Message
  136.                     End If
  137.                 Case &H40:           'Quarter Frame Message indicating Minutes iLoNibble
  138.                     If nQfIdExpected <> &H40 Then      'Discontinous MTC -> resync
  139.                         bInSync = False                'Out of sync
  140.                         nQfIdExpected = &H0            'start over
  141.                     Else
  142.                         'Minutes LoNibble=LoNibble of iMtcData
  143.                         iLoNibble = (iMtcData And &HF)
  144.                         'If we're in sync, increase Time Counter
  145.                         If bInSync = True Then lMtcTime = lMtcTime + fMsPerQF
  146.                         nQfIdExpected = &H50    'Expected next Quarter Frame Message
  147.                     End If
  148.                 Case &H50:           'Quarter Frame Message indicating Minutes hiNibble
  149.                     If nQfIdExpected <> &H50 Then        'Discontinous MTC -> resync
  150.                         bInSync = False                  'Out of sync
  151.                         nQfIdExpected = &H0              'start over
  152.                     Else
  153.                         'Minutes HiNibble=Bits 0 & 1 of iMtcData
  154.                         iHiNibble = (iMtcData And &H3)
  155.                         iMtcMinutes = (iHiNibble * 16) + iLoNibble  'pack Minutes Number
  156.                         'If we're in sync, increase Time Counter
  157.                         If bInSync = True Then lMtcTime = lMtcTime + fMsPerQF
  158.                         nQfIdExpected = &H60             'Expected next Quarter Frame Message
  159.                     End If
  160.                 Case &H60:            'Quarter Frame Message indicating Hours loNibble
  161.                     If nQfIdExpected <> &H60 Then       'Discontinous MTC -> resync
  162.                         bInSync = False                 'Out of sync
  163.                         nQfIdExpected = &H0             'start over
  164.                     Else
  165.                         iLoNibble = (iMtcData And &HF)  'Hours iLoNibble
  166.                         'If we're in sync, increase Time Counter
  167.                         If bInSync = True Then lMtcTime = lMtcTime + fMsPerQF
  168.                         nQfIdExpected = &H70            'Expected next Quarter Frame Message
  169.                     End If
  170.                 Case &H70:           'Quarter Frame Message indicating Hours hiNibble
  171.                     If nQfIdExpected <> &H70 Then       'Discontinous MTC -> resync
  172.                         bInSync = False                 'Out of sync
  173.                         nQfIdExpected = &H0             'start over
  174.                     Else
  175.                         'Hours HiNibble=Bit 0 of iMtcData
  176.                         iHiNibble = (iMtcData And &H1)
  177.                         iMtcHours = (iHiNibble * 16) + iLoNibble  'pack Hours Number
  178.                         'Set bDebug = True to test arriving MTC in Debug Window
  179.                         'Only works in Visual Basic environement
  180.                         If bDebug = True Then
  181.                             Debug.Print iMtcHours; ":"; iMtcMinutes; ":";
  182.                             Debug.Print iMtcSeconds; ":"; iMtcFrames
  183.                         End If
  184.                         'nMtcMode is packed in Bits 1 & 2 of iMtcData
  185.                         'Test if received MTC is in the expected frame mode
  186.                         If (iMtcData And &H6) / 2 <> nMtcMode Then
  187.                             bMtcModeError = True   'poll this flag if necessary
  188.                             bInSync = False        'Out of sync
  189.                             nQfIdExpected = &H0    'start over
  190.                             Exit Sub
  191.                         End If
  192.                         'We are two frames late because we've spent 8 Quarter Frames (2 Frames)
  193.                         'to read and pack a complete MTC message, thus...
  194.                         iMtcFrames = iMtcFrames + 2
  195.                         If bInSync = True Then
  196.                             'Is new MTC message continuous with the previous one?
  197.                             lTotalFrames = nFramesPerSecond * (iMtcHours * 3600& + iMtcMinutes * 60& + iMtcSeconds) + iMtcFrames
  198.                             If lTotalFrames - nMtcTotalFrames <> 1 Then
  199.                                 'Wrap from 23:59:59:24 to 00:00:00:00 not implemented!
  200.                                 'Dropped frames in 30 f/s drop frame mode also not implemented
  201.                                 bInSync = False   'Discontinous MTC -> Out of sync
  202.                                 nQfIdExpected = &H0 'start over
  203.                             Else
  204.                                 'Actualize Time Counter
  205.                                 lMtcTime = CLng(CSng(lTotalFrames) * fMsPerFrame)
  206.                                 '8th Quarter Frame Message->Increase Frame Counter
  207.                                 nMtcTotalFrames = nMtcTotalFrames + 1
  208.                             End If
  209.                         Else
  210.                             'We were out of sync but...
  211.                             'a new complete valid MTC message has been received !!
  212.                             nNewMTC = nNewMTC + 1   'Increase New MTC counter
  213.                             'Calculate new Frame Counter (long integer operation).
  214.                             nMtcTotalFrames = (iMtcHours * 3600& + iMtcMinutes * 60& + iMtcSeconds) * nFramesPerSecond + iMtcFrames
  215.                             'Calculate new milliseconds Time Counter (float operation).
  216.                             lMtcTime = CLng(CSng(nMtcTotalFrames) * fMsPerFrame)
  217.                             'Now we are in sync
  218.                             bInSync = True
  219.                         End If
  220.                         nQfIdExpected = &H0    'ID of expected next Quarter Frame Message
  221.                     End If
  222.             End Select
  223.         End If
  224.     Else   'Received Midi Message is Midi Data  (not MTC)
  225.        'You may show here a screen representation of MidiData In.
  226.        '*********************************************
  227.        'SPECIFIC TO THIS APPLICATION
  228.         If bVisualData = True Then
  229.             If frmVBSeq.picDataIn.BackColor = LED_OFF Then
  230.                 frmVBSeq.picDataIn.BackColor = LED_ON
  231.             End If
  232.             lDataInTime = timeGetTime()
  233.         End If
  234.        '*********************************************
  235.         If bMidiThru = True Then            'Global Flag
  236.             If hMidiOut <> NO_HANDLE Then
  237.                 vntRet = midiOutShortMsg(hMidiOut, lMidiMessage)   'send it out
  238.                'You may show here a screen representation of Midi Data Out.
  239.                '*********************************************
  240.                'SPECIFIC TO THIS APPLICATION
  241.                 If bVisualData = True Then
  242.                     If frmVBSeq.picDataOut.BackColor = LED_OFF Then
  243.                         frmVBSeq.picDataOut.BackColor = LED_ON
  244.                     End If
  245.                     lDataOutTime = timeGetTime()
  246.                 End If
  247.                '**********************************************
  248.             End If
  249.         End If
  250.         'Here you may save the Midi Data just received (or do whatever with it...)
  251.        '***********************************************************************************
  252.         'SPECIFIC TO THIS APPLICATION
  253.         'Save Midi Data only if we are in recording mode
  254.         If bRec = True Then
  255.             'Increase RecBuffer Size 1K if needed
  256.             If (nRecCounter Mod 1024) = 0 Then
  257.                 ReDim Preserve aRecBuffer(nRecCounter + 1024)
  258.             End If
  259.             If nSyncMode = SYNC_INTERNAL Then
  260.                 'Save packed Midi Message
  261.                 aRecBuffer(nRecCounter).MidiData = lMidiMessage
  262.                 'Time = Initial Offset + milliseconds ellapsed since Start Recording
  263.                 aRecBuffer(nRecCounter).TimeStamp = lOffsetTime + (timeGetTime() - lInitTime)
  264.                 'increase recorded messages counter
  265.                 nRecCounter = nRecCounter + 1
  266.             Else    'external sync
  267.                 'save only if we're in sync with MTC
  268.                 If bInSync = True Then
  269.                     aRecBuffer(nRecCounter).MidiData = lMidiMessage
  270.                     'Time=current MTC time in milliseconds
  271.                     aRecBuffer(nRecCounter).TimeStamp = lMtcTime
  272.                     nRecCounter = nRecCounter + 1
  273.                 Else
  274.                     'An incoming Midi Data message is lost
  275.                     'because it was received while we were out of sync
  276.                     nRecErrors = nRecErrors + 1
  277.                     'You may inform the user, but not in this procedure!!!!
  278.                 End If
  279.             End If
  280.         End If
  281.        '**************************************************************************************
  282.     End If
  283. End Sub
  284.