Browse Source

cmDspSys.c: Incoming MIDI messages are now dispatched to DSP objects via

broadcast message mechanism.

cmDspBuiltIn.c:Added _cmMidiInDC and _cmMidiOutDC.

cmDspPgm.c: Added _cmDspSysPgm_Test_Midi().
master
kevin 11 years ago
parent
commit
f4448e99b6
3 changed files with 298 additions and 6 deletions
  1. 240
    3
      dsp/cmDspBuiltIn.c
  2. 36
    1
      dsp/cmDspPgm.c
  3. 22
    2
      dsp/cmDspSys.c

+ 240
- 3
dsp/cmDspBuiltIn.c View File

40
 #include "cmMidi.h"
40
 #include "cmMidi.h"
41
 #include "cmProc2.h"
41
 #include "cmProc2.h"
42
 #include "cmVectOpsTemplateMain.h"
42
 #include "cmVectOpsTemplateMain.h"
43
+#include "cmMidiPort.h"
43
 
44
 
44
 /*
45
 /*
45
 About variables:
46
 About variables:
982
 //==========================================================================================================================================
983
 //==========================================================================================================================================
983
 enum
984
 enum
984
 {
985
 {
986
+  kDeviceMiId,
987
+  kPortMiId,
988
+  kSmpIdxMiId,
989
+  kStatusMiId,
990
+  kD0MiId,
991
+  kD1MiId
992
+};
993
+
994
+
995
+cmDspClass_t _cmMidiInDC;
996
+
997
+typedef struct
998
+{
999
+  cmDspInst_t inst;
1000
+  unsigned midiSymId;
1001
+  unsigned prevSmpIdx;
1002
+} cmDspMidiIn_t;
1003
+
1004
+cmDspInst_t*  _cmDspMidiInAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
1005
+{
1006
+  cmDspVarArg_t args[] =
1007
+  {
1008
+    { "device", kDeviceMiId, 0,  0,  kOutDsvFl | kUIntDsvFl, "MIDI device" },
1009
+    { "port",   kPortMiId,   0,  0,  kOutDsvFl | kUIntDsvFl, "MIDI device port"},
1010
+    { "smpidx", kSmpIdxMiId, 0,  0,  kOutDsvFl | kUIntDsvFl, "Message time tag as sample index."},
1011
+    { "status", kStatusMiId, 0,  0,  kOutDsvFl | kUIntDsvFl, "MIDI status" },
1012
+    { "d0",     kD0MiId,     0,  0,  kOutDsvFl | kUIntDsvFl, "MIDI channel message d0" },
1013
+    { "d1",     kD1MiId,     0,  0,  kOutDsvFl | kUIntDsvFl, "MIDI channel message d1" },
1014
+    { NULL, 0, 0, 0, 0 }
1015
+  };
1016
+
1017
+  cmDspMidiIn_t* p = cmDspInstAlloc(cmDspMidiIn_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
1018
+
1019
+ p->midiSymId =  cmDspSysAssignInstAttrSymbolStr( ctx->dspH, &p->inst, "_midi" );
1020
+
1021
+  return &p->inst;
1022
+}
1023
+
1024
+cmDspRC_t _cmDspMidiInReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
1025
+{
1026
+  cmDspRC_t      rc = kOkDspRC;
1027
+  cmDspMidiIn_t* p  = (cmDspMidiIn_t*)inst;
1028
+  cmDspApplyAllDefaults(ctx,inst);
1029
+  p->prevSmpIdx = 0;
1030
+  return rc;
1031
+} 
1032
+
1033
+cmDspRC_t  _cmDspMidiInRecvFunc(   cmDspCtx_t* ctx, struct cmDspInst_str* inst,  unsigned attrSymId, const cmDspValue_t* value )
1034
+{
1035
+  cmDspMidiIn_t* p = (cmDspMidiIn_t*)inst;
1036
+
1037
+  if( attrSymId == p->midiSymId )
1038
+  {
1039
+    cmMidiPacket_t* pkt = (cmMidiPacket_t*)(value->u.m.u.vp);
1040
+    unsigned i;
1041
+
1042
+    cmDspSetUInt(ctx, inst, kDeviceMiId, pkt->devIdx);
1043
+    cmDspSetUInt(ctx, inst, kPortMiId,   pkt->portIdx); 
1044
+
1045
+    for(i=0; i<pkt->msgCnt; ++i)
1046
+    {
1047
+      cmMidiMsg* m = pkt->msgArray + i;
1048
+      unsigned   deltaSmpCnt = floor((m->deltaUs * cmDspSampleRate(ctx)) / 1000000.0);
1049
+
1050
+      if( p->prevSmpIdx == 0 )
1051
+        p->prevSmpIdx = ctx->cycleCnt * cmDspSamplesPerCycle(ctx);
1052
+      else
1053
+        p->prevSmpIdx += deltaSmpCnt;
1054
+
1055
+      cmDspSetUInt(ctx, inst, kSmpIdxMiId, p->prevSmpIdx );
1056
+      cmDspSetUInt(ctx, inst, kD1MiId,     m->d1 );
1057
+      cmDspSetUInt(ctx, inst, kD0MiId,     m->d0 );
1058
+      cmDspSetUInt(ctx, inst, kStatusMiId, m->status );
1059
+    }
1060
+  }
1061
+
1062
+  return kOkDspRC;
1063
+}
1064
+
1065
+struct cmDspClass_str* cmMidiInClassCons( cmDspCtx_t* ctx )
1066
+{
1067
+  cmDspClassSetup(&_cmMidiInDC,ctx,"MidiIn",
1068
+    NULL,
1069
+    _cmDspMidiInAlloc,
1070
+    NULL,
1071
+    _cmDspMidiInReset,
1072
+    NULL,
1073
+    NULL,
1074
+    NULL,
1075
+    _cmDspMidiInRecvFunc,
1076
+    "Midi input port");
1077
+
1078
+  return &_cmMidiInDC;
1079
+}
1080
+
1081
+//==========================================================================================================================================
1082
+enum
1083
+{
1084
+  kDeviceMoId,
1085
+  kPortMoId,
1086
+  kStatusMoId,
1087
+  kD0MoId,
1088
+  kD1MoId
1089
+};
1090
+
1091
+cmDspClass_t _cmMidiOutDC;
1092
+
1093
+typedef struct
1094
+{
1095
+  cmDspInst_t inst;
1096
+  unsigned    devIdx;
1097
+  unsigned    portIdx;
1098
+} cmDspMidiOut_t;
1099
+
1100
+cmDspRC_t _cmDspMidiOutSetDevice( cmDspCtx_t* ctx, cmDspMidiOut_t* p, const cmChar_t* deviceStr )
1101
+{
1102
+  cmDspRC_t rc = kOkDspRC;
1103
+
1104
+  if( deviceStr != NULL )
1105
+    if((p->devIdx = cmMpDeviceNameToIndex(deviceStr)) == cmInvalidIdx )
1106
+      rc = cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"The MIDI device '%s' could not be found.",cmStringNullGuard(deviceStr));
1107
+
1108
+  return rc;
1109
+}
1110
+
1111
+cmDspRC_t _cmDspMidiOutSetPort( cmDspCtx_t* ctx, cmDspMidiOut_t* p, const cmChar_t* portStr )
1112
+{
1113
+  cmDspRC_t rc = kOkDspRC;
1114
+
1115
+  if( portStr == NULL )
1116
+    return rc;
1117
+
1118
+  if( p->devIdx == cmInvalidIdx )
1119
+    rc = cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"The MIDI port cannot be set until the MIDI device is set.");
1120
+  else
1121
+  {
1122
+    if((p->portIdx = cmMpDevicePortNameToIndex(p->devIdx,kOutMpFl,portStr)) == cmInvalidIdx )
1123
+      rc = cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"The MIDI port '%s' could not be found on device '%s'.",cmStringNullGuard(portStr),cmStringNullGuard(cmMpDeviceName(p->devIdx)));
1124
+  }
1125
+
1126
+  return rc;
1127
+}
1128
+
1129
+cmDspInst_t*  _cmDspMidiOutAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
1130
+{
1131
+  cmDspVarArg_t args[] =
1132
+  {
1133
+    { "device", kDeviceMoId, 0,  0,  kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "MIDI device name"},
1134
+    { "port",   kPortMoId,   0,  0,  kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "MIDI port name"},
1135
+    { "status", kStatusMoId, 0,  0,  kInDsvFl | kUIntDsvFl, "MIDI status" },
1136
+    { "d0",     kD0MoId,     0,  0,  kInDsvFl | kUIntDsvFl, "MIDI channel message d0" },
1137
+    { "d1",     kD1MoId,     0,  0,  kInDsvFl | kUIntDsvFl, "MIDI channel message d1" },
1138
+    { NULL, 0, 0, 0, 0 }
1139
+  };
1140
+
1141
+  cmDspMidiOut_t* p = cmDspInstAlloc(cmDspMidiOut_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
1142
+
1143
+  p->devIdx  = cmInvalidIdx;
1144
+  p->portIdx = cmInvalidIdx;
1145
+
1146
+	cmDspSetDefaultUInt(ctx,&p->inst, kStatusMoId, 0, 0 );
1147
+  cmDspSetDefaultUInt(ctx,&p->inst, kD0MoId,     0, 0 );
1148
+  cmDspSetDefaultUInt(ctx,&p->inst, kD1MoId,     0, 0 );
1149
+  
1150
+  return &p->inst;
1151
+}
1152
+
1153
+cmDspRC_t _cmDspMidiOutReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
1154
+{
1155
+  cmDspRC_t      rc = kOkDspRC;
1156
+  cmDspMidiOut_t* p = (cmDspMidiOut_t*)inst;
1157
+
1158
+  cmDspApplyAllDefaults(ctx,inst);
1159
+
1160
+  _cmDspMidiOutSetDevice(ctx,p,cmDspStrcz(inst,kDeviceMoId));
1161
+  _cmDspMidiOutSetPort(  ctx,p,cmDspStrcz(inst,kPortMoId));
1162
+
1163
+  return rc;
1164
+} 
1165
+
1166
+cmDspRC_t _cmDspMidiOutRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
1167
+{
1168
+  cmDspMidiOut_t* p = (cmDspMidiOut_t*)inst;
1169
+
1170
+  switch( evt->dstVarId )
1171
+  {
1172
+    case kDeviceMoId:      
1173
+      _cmDspMidiOutSetDevice(ctx, p, cmDsvStrcz(evt->valuePtr) );
1174
+      break;
1175
+
1176
+    case kPortMoId:
1177
+      _cmDspMidiOutSetPort(ctx, p, cmDsvStrcz(evt->valuePtr) );
1178
+      break;
1179
+
1180
+    case kStatusMoId:
1181
+      if( p->devIdx != cmInvalidIdx && p->portIdx != cmInvalidIdx )
1182
+      {
1183
+        unsigned status = cmDsvGetUInt(evt->valuePtr);
1184
+        unsigned d0     = cmDspUInt(inst,kD0MoId);
1185
+        unsigned d1     = cmDspUInt(inst,kD1MoId);
1186
+        if( cmMpDeviceSend( p->devIdx, p->portIdx, status, d0, d1 ) != kOkMpRC )
1187
+          cmDspInstErr(ctx,inst,kInvalidArgDspRC,"MIDI send failed.");
1188
+      }
1189
+      break;
1190
+
1191
+    default:
1192
+      cmDspSetEvent(ctx,inst,evt);
1193
+      break;
1194
+  }
1195
+
1196
+
1197
+  return kOkDspRC;
1198
+}
1199
+
1200
+struct cmDspClass_str* cmMidiOutClassCons( cmDspCtx_t* ctx )
1201
+{
1202
+  cmDspClassSetup(&_cmMidiOutDC,ctx,"MidiOut",
1203
+    NULL,
1204
+    _cmDspMidiOutAlloc,
1205
+    NULL,
1206
+    _cmDspMidiOutReset,
1207
+    NULL,
1208
+    _cmDspMidiOutRecv,
1209
+    NULL,
1210
+    NULL,
1211
+    "Midi input port");
1212
+
1213
+  return &_cmMidiOutDC;
1214
+}
1215
+
1216
+//==========================================================================================================================================
1217
+enum
1218
+{
985
   kChAiId,
1219
   kChAiId,
986
   kGainAiId,
1220
   kGainAiId,
987
   kOutAiId
1221
   kOutAiId
2980
 
3214
 
2981
 cmDspRC_t _cmDspWaveTableInitAudioFile( cmDspCtx_t* ctx, cmDspWaveTable_t* p )
3215
 cmDspRC_t _cmDspWaveTableInitAudioFile( cmDspCtx_t* ctx, cmDspWaveTable_t* p )
2982
 {
3216
 {
2983
-  cmDspRC_t         rc;
3217
+  cmDspRC_t         rc = kOkDspRC;
2984
   cmAudioFileH_t    afH;
3218
   cmAudioFileH_t    afH;
2985
   cmRC_t            afRC;
3219
   cmRC_t            afRC;
2986
   cmAudioFileInfo_t afInfo;
3220
   cmAudioFileInfo_t afInfo;
2992
   // if the file name is valid
3226
   // if the file name is valid
2993
   if( fn == NULL || strlen(fn)==0 )
3227
   if( fn == NULL || strlen(fn)==0 )
2994
   {
3228
   {
2995
-     cmDspInstErr(ctx,&p->inst,kVarNotValidDspRC,"Audio file loading was requested for the wave table but no file name was given.");
3229
+     rc = cmDspInstErr(ctx,&p->inst,kVarNotValidDspRC,"Audio file loading was requested for the wave table but no file name was given.");
2996
      goto errLabel;
3230
      goto errLabel;
2997
   }
3231
   }
2998
 
3232
 
3468
         snprintf(fmtArray[j].label,kSprintfLabelCharCnt,"in-%i",j);
3702
         snprintf(fmtArray[j].label,kSprintfLabelCharCnt,"in-%i",j);
3469
 
3703
 
3470
         fmtArray[j].label[kSprintfLabelCharCnt]=0;
3704
         fmtArray[j].label[kSprintfLabelCharCnt]=0;
3471
-        fmtArray[j].label[kSprintfDocCharCnt] = 0;
3705
+        fmtArray[j].doc[kSprintfDocCharCnt] = 0;
3472
 
3706
 
3473
         switch( fmt[ i + fn - 1 ] )
3707
         switch( fmt[ i + fn - 1 ] )
3474
         {
3708
         {
4942
   cmCounterClassCons,
5176
   cmCounterClassCons,
4943
 
5177
 
4944
   cmPhasorClassCons,
5178
   cmPhasorClassCons,
5179
+  cmMidiOutClassCons,
5180
+  cmMidiInClassCons,
4945
   cmAudioInClassCons,
5181
   cmAudioInClassCons,
4946
   cmAudioOutClassCons,
5182
   cmAudioOutClassCons,
4947
   cmAudioFileOutClassCons,
5183
   cmAudioFileOutClassCons,
5018
   cmScFolClassCons,
5254
   cmScFolClassCons,
5019
   cmScModClassCons,
5255
   cmScModClassCons,
5020
   cmGSwitchClassCons,
5256
   cmGSwitchClassCons,
5257
+  cmScaleRangeClassCons,
5021
 
5258
 
5022
   NULL,
5259
   NULL,
5023
 };
5260
 };

+ 36
- 1
dsp/cmDspPgm.c View File

25
 #include "cmDspPgmPP.h"
25
 #include "cmDspPgmPP.h"
26
 #include "cmDspPgmKr.h"
26
 #include "cmDspPgmKr.h"
27
 
27
 
28
+cmDspRC_t _cmDspSysPgm_Test_Midi( cmDspSysH_t h, void** userPtrPtr )
29
+{
30
+  cmDspRC_t rc = kOkDspRC;
31
+
32
+  cmDspInst_t* sendBtn = cmDspSysAllocInst( h,"Button", "Send",    2, kButtonDuiId, 0.0 );
33
+  cmDspInst_t* status  = cmDspSysAllocInst( h,"Scalar", "Status",  5, kNumberDuiId, 0.0,  127.0, 1.0,  144.0);
34
+  cmDspInst_t* d0      = cmDspSysAllocInst( h,"Scalar", "D0",      5, kNumberDuiId, 0.0,  127.0, 1.0,  64.0);
35
+  cmDspInst_t* d1      = cmDspSysAllocInst( h,"Scalar", "D1",      5, kNumberDuiId, 0.0,  127.0, 1.0,  64.0);
36
+  cmDspInst_t* midiOut = cmDspSysAllocInst( h,"MidiOut", NULL,     2, "Fastlane", "Fastlane MIDI A");
37
+  cmDspInst_t* midiIn  = cmDspSysAllocInst( h,"MidiIn",  NULL,     0 );
38
+  cmDspInst_t* printer = cmDspSysAllocInst( h,"Printer", NULL,     1, ">" );
39
+
40
+  // check for allocation errors
41
+  if((rc = cmDspSysLastRC(h)) != kOkDspRC )
42
+    goto errLabel;
43
+
44
+  cmDspSysInstallCb(   h, sendBtn, "out", d1,      "send", NULL);
45
+  cmDspSysInstallCb(   h, sendBtn, "out", d0,      "send", NULL);
46
+  cmDspSysInstallCb(   h, sendBtn, "out", status,  "send", NULL);
47
+
48
+  cmDspSysInstallCb(   h, status,  "val", midiOut, "status",NULL);
49
+  cmDspSysInstallCb(   h, d0,      "val", midiOut, "d0",    NULL);
50
+  cmDspSysInstallCb(   h, d1,      "val", midiOut, "d1",    NULL);
51
+
52
+  cmDspSysInstallCb(   h, midiIn,  "status", printer, "in", NULL);
53
+  cmDspSysInstallCb(   h, midiIn,  "d0",     printer, "in", NULL);
54
+  cmDspSysInstallCb(   h, midiIn,  "d1",     printer, "in", NULL);
55
+  cmDspSysInstallCb(   h, midiIn,  "smpidx", printer, "in", NULL);
56
+
57
+ errLabel:
58
+  return rc;
59
+  
60
+}
61
+
28
 cmDspRC_t _cmDspSysPgm_Stereo_Through( cmDspSysH_t h, void** userPtrPtr )
62
 cmDspRC_t _cmDspSysPgm_Stereo_Through( cmDspSysH_t h, void** userPtrPtr )
29
 {
63
 {
30
   bool useBuiltInFl = true;
64
   bool useBuiltInFl = true;
2332
   cmDspInst_t* fwtp  =  cmDspSysAllocInst( h, "WaveTable", NULL,   5, ((int)cmDspSysSampleRate(h)), 1, fn, -1, 7000000 );
2366
   cmDspInst_t* fwtp  =  cmDspSysAllocInst( h, "WaveTable", NULL,   5, ((int)cmDspSysSampleRate(h)), 1, fn, -1, 7000000 );
2333
   cmDspInst_t* fad0  =  cmDspSysAllocInst( h, "Xfader",    NULL,   3, xfadeChCnt,  xfadeMs, xfadeInitFl ); 
2367
   cmDspInst_t* fad0  =  cmDspSysAllocInst( h, "Xfader",    NULL,   3, xfadeChCnt,  xfadeMs, xfadeInitFl ); 
2334
 
2368
 
2335
-  cmDspInst_t*  prp  = cmDspSysAllocInst(  h, "Printer",  NULL, 1, ">" );
2369
+  //cmDspInst_t*  prp  = cmDspSysAllocInst(  h, "Printer",  NULL, 1, ">" );
2336
 
2370
 
2337
   cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut",  NULL,   1, 0 );
2371
   cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut",  NULL,   1, 0 );
2338
   cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut",  NULL,   1, 1 );
2372
   cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut",  NULL,   1, 1 );
2389
   { "pickup tails", _cmDspSysPgm_NoiseTails,    NULL, NULL },
2423
   { "pickup tails", _cmDspSysPgm_NoiseTails,    NULL, NULL },
2390
   { "tails_2",      _cmDspSysPgm_NoiseTails2,   NULL, NULL },
2424
   { "tails_2",      _cmDspSysPgm_NoiseTails2,   NULL, NULL },
2391
   { "pickups",     _cmDspSysPgm_Pickups0,       NULL, NULL },
2425
   { "pickups",     _cmDspSysPgm_Pickups0,       NULL, NULL },
2426
+  { "midi_test",   _cmDspSysPgm_Test_Midi,      NULL, NULL },
2392
   { "2_thru",      _cmDspSysPgm_Stereo_Through, NULL, NULL },
2427
   { "2_thru",      _cmDspSysPgm_Stereo_Through, NULL, NULL },
2393
   { "guitar",      _cmDspSysPgmGuitar,          NULL, NULL },
2428
   { "guitar",      _cmDspSysPgmGuitar,          NULL, NULL },
2394
   { "2_fx",        _cmDspSysPgm_Stereo_Fx,      NULL, NULL },
2429
   { "2_fx",        _cmDspSysPgm_Stereo_Fx,      NULL, NULL },

+ 22
- 2
dsp/cmDspSys.c View File

10
 #include "cmText.h"
10
 #include "cmText.h"
11
 #include "cmFileSys.h"
11
 #include "cmFileSys.h"
12
 #include "cmSymTbl.h"
12
 #include "cmSymTbl.h"
13
+#include "cmMidi.h"
13
 #include "cmJson.h"
14
 #include "cmJson.h"
14
 #include "cmPrefs.h"
15
 #include "cmPrefs.h"
15
 #include "cmDspValue.h"
16
 #include "cmDspValue.h"
619
   }
620
   }
620
   else
621
   else
621
   {
622
   {
623
+    unsigned* hdr = (unsigned*)msgPtr;
624
+
622
     // the msg selector is the second field in the data packet (following the audio system sub-system id)
625
     // the msg selector is the second field in the data packet (following the audio system sub-system id)
623
-    const unsigned msgTypeSelId = ((const unsigned*)msgPtr)[1];
626
+    //const unsigned msgTypeSelId = ((const unsigned*)msgPtr)[1];
627
+    
624
 
628
 
625
-    switch( msgTypeSelId )
629
+    switch( hdr[1] )
626
     {
630
     {
627
       case kUiSelAsId:
631
       case kUiSelAsId:
628
         _cmDspSysHandleUiMsg(p,ip,msgPtr,msgByteCnt);
632
         _cmDspSysHandleUiMsg(p,ip,msgPtr,msgByteCnt);
633
         break;
637
         break;
634
 
638
 
635
       case kMidiMsgArraySelAsId:
639
       case kMidiMsgArraySelAsId:
640
+        {
641
+          cmMidiPacket_t pkt;
642
+          cmDspValue_t   v;
643
+
644
+          pkt.cbDataPtr = NULL;
645
+          pkt.devIdx    = hdr[2];
646
+          pkt.portIdx   = hdr[3];
647
+          pkt.msgCnt    = hdr[4];
648
+          pkt.msgArray  = (cmMidiMsg*)(hdr + 5);
649
+          unsigned     midiSymId = cmDspSysRegisterStaticSymbol(h,"_midi");
650
+
651
+          v.u.m.u.vp = &pkt;
652
+          cmDspSysBroadcastValue(h, midiSymId, &v);
653
+
654
+          
636
         /*
655
         /*
637
         // data format for MIDI messages
656
         // data format for MIDI messages
638
         { kMidiMsgArraytSelAsId, devIdx, portIdx, msgCnt, msgArray[msgCnt] }
657
         { kMidiMsgArraytSelAsId, devIdx, portIdx, msgCnt, msgArray[msgCnt] }
639
         where each msgArray[] record is a cmMidiMsg record.
658
         where each msgArray[] record is a cmMidiMsg record.
640
         */
659
         */
660
+        }
641
         break;
661
         break;
642
 
662
 
643
     }
663
     }

Loading…
Cancel
Save