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().
This commit is contained in:
kevin 2013-04-20 10:36:21 -07:00
parent ca06ba399a
commit f4448e99b6
3 changed files with 299 additions and 7 deletions

View File

@ -40,6 +40,7 @@
#include "cmMidi.h"
#include "cmProc2.h"
#include "cmVectOpsTemplateMain.h"
#include "cmMidiPort.h"
/*
About variables:
@ -979,6 +980,239 @@ struct cmDspClass_str* cmSigGenClassCons( cmDspCtx_t* ctx )
return &_cmSigGenDC;
}
//==========================================================================================================================================
enum
{
kDeviceMiId,
kPortMiId,
kSmpIdxMiId,
kStatusMiId,
kD0MiId,
kD1MiId
};
cmDspClass_t _cmMidiInDC;
typedef struct
{
cmDspInst_t inst;
unsigned midiSymId;
unsigned prevSmpIdx;
} cmDspMidiIn_t;
cmDspInst_t* _cmDspMidiInAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
{
cmDspVarArg_t args[] =
{
{ "device", kDeviceMiId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI device" },
{ "port", kPortMiId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI device port"},
{ "smpidx", kSmpIdxMiId, 0, 0, kOutDsvFl | kUIntDsvFl, "Message time tag as sample index."},
{ "status", kStatusMiId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI status" },
{ "d0", kD0MiId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI channel message d0" },
{ "d1", kD1MiId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI channel message d1" },
{ NULL, 0, 0, 0, 0 }
};
cmDspMidiIn_t* p = cmDspInstAlloc(cmDspMidiIn_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
p->midiSymId = cmDspSysAssignInstAttrSymbolStr( ctx->dspH, &p->inst, "_midi" );
return &p->inst;
}
cmDspRC_t _cmDspMidiInReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspMidiIn_t* p = (cmDspMidiIn_t*)inst;
cmDspApplyAllDefaults(ctx,inst);
p->prevSmpIdx = 0;
return rc;
}
cmDspRC_t _cmDspMidiInRecvFunc( cmDspCtx_t* ctx, struct cmDspInst_str* inst, unsigned attrSymId, const cmDspValue_t* value )
{
cmDspMidiIn_t* p = (cmDspMidiIn_t*)inst;
if( attrSymId == p->midiSymId )
{
cmMidiPacket_t* pkt = (cmMidiPacket_t*)(value->u.m.u.vp);
unsigned i;
cmDspSetUInt(ctx, inst, kDeviceMiId, pkt->devIdx);
cmDspSetUInt(ctx, inst, kPortMiId, pkt->portIdx);
for(i=0; i<pkt->msgCnt; ++i)
{
cmMidiMsg* m = pkt->msgArray + i;
unsigned deltaSmpCnt = floor((m->deltaUs * cmDspSampleRate(ctx)) / 1000000.0);
if( p->prevSmpIdx == 0 )
p->prevSmpIdx = ctx->cycleCnt * cmDspSamplesPerCycle(ctx);
else
p->prevSmpIdx += deltaSmpCnt;
cmDspSetUInt(ctx, inst, kSmpIdxMiId, p->prevSmpIdx );
cmDspSetUInt(ctx, inst, kD1MiId, m->d1 );
cmDspSetUInt(ctx, inst, kD0MiId, m->d0 );
cmDspSetUInt(ctx, inst, kStatusMiId, m->status );
}
}
return kOkDspRC;
}
struct cmDspClass_str* cmMidiInClassCons( cmDspCtx_t* ctx )
{
cmDspClassSetup(&_cmMidiInDC,ctx,"MidiIn",
NULL,
_cmDspMidiInAlloc,
NULL,
_cmDspMidiInReset,
NULL,
NULL,
NULL,
_cmDspMidiInRecvFunc,
"Midi input port");
return &_cmMidiInDC;
}
//==========================================================================================================================================
enum
{
kDeviceMoId,
kPortMoId,
kStatusMoId,
kD0MoId,
kD1MoId
};
cmDspClass_t _cmMidiOutDC;
typedef struct
{
cmDspInst_t inst;
unsigned devIdx;
unsigned portIdx;
} cmDspMidiOut_t;
cmDspRC_t _cmDspMidiOutSetDevice( cmDspCtx_t* ctx, cmDspMidiOut_t* p, const cmChar_t* deviceStr )
{
cmDspRC_t rc = kOkDspRC;
if( deviceStr != NULL )
if((p->devIdx = cmMpDeviceNameToIndex(deviceStr)) == cmInvalidIdx )
rc = cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"The MIDI device '%s' could not be found.",cmStringNullGuard(deviceStr));
return rc;
}
cmDspRC_t _cmDspMidiOutSetPort( cmDspCtx_t* ctx, cmDspMidiOut_t* p, const cmChar_t* portStr )
{
cmDspRC_t rc = kOkDspRC;
if( portStr == NULL )
return rc;
if( p->devIdx == cmInvalidIdx )
rc = cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"The MIDI port cannot be set until the MIDI device is set.");
else
{
if((p->portIdx = cmMpDevicePortNameToIndex(p->devIdx,kOutMpFl,portStr)) == cmInvalidIdx )
rc = cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"The MIDI port '%s' could not be found on device '%s'.",cmStringNullGuard(portStr),cmStringNullGuard(cmMpDeviceName(p->devIdx)));
}
return rc;
}
cmDspInst_t* _cmDspMidiOutAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
{
cmDspVarArg_t args[] =
{
{ "device", kDeviceMoId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "MIDI device name"},
{ "port", kPortMoId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "MIDI port name"},
{ "status", kStatusMoId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI status" },
{ "d0", kD0MoId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI channel message d0" },
{ "d1", kD1MoId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI channel message d1" },
{ NULL, 0, 0, 0, 0 }
};
cmDspMidiOut_t* p = cmDspInstAlloc(cmDspMidiOut_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
p->devIdx = cmInvalidIdx;
p->portIdx = cmInvalidIdx;
cmDspSetDefaultUInt(ctx,&p->inst, kStatusMoId, 0, 0 );
cmDspSetDefaultUInt(ctx,&p->inst, kD0MoId, 0, 0 );
cmDspSetDefaultUInt(ctx,&p->inst, kD1MoId, 0, 0 );
return &p->inst;
}
cmDspRC_t _cmDspMidiOutReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspMidiOut_t* p = (cmDspMidiOut_t*)inst;
cmDspApplyAllDefaults(ctx,inst);
_cmDspMidiOutSetDevice(ctx,p,cmDspStrcz(inst,kDeviceMoId));
_cmDspMidiOutSetPort( ctx,p,cmDspStrcz(inst,kPortMoId));
return rc;
}
cmDspRC_t _cmDspMidiOutRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspMidiOut_t* p = (cmDspMidiOut_t*)inst;
switch( evt->dstVarId )
{
case kDeviceMoId:
_cmDspMidiOutSetDevice(ctx, p, cmDsvStrcz(evt->valuePtr) );
break;
case kPortMoId:
_cmDspMidiOutSetPort(ctx, p, cmDsvStrcz(evt->valuePtr) );
break;
case kStatusMoId:
if( p->devIdx != cmInvalidIdx && p->portIdx != cmInvalidIdx )
{
unsigned status = cmDsvGetUInt(evt->valuePtr);
unsigned d0 = cmDspUInt(inst,kD0MoId);
unsigned d1 = cmDspUInt(inst,kD1MoId);
if( cmMpDeviceSend( p->devIdx, p->portIdx, status, d0, d1 ) != kOkMpRC )
cmDspInstErr(ctx,inst,kInvalidArgDspRC,"MIDI send failed.");
}
break;
default:
cmDspSetEvent(ctx,inst,evt);
break;
}
return kOkDspRC;
}
struct cmDspClass_str* cmMidiOutClassCons( cmDspCtx_t* ctx )
{
cmDspClassSetup(&_cmMidiOutDC,ctx,"MidiOut",
NULL,
_cmDspMidiOutAlloc,
NULL,
_cmDspMidiOutReset,
NULL,
_cmDspMidiOutRecv,
NULL,
NULL,
"Midi input port");
return &_cmMidiOutDC;
}
//==========================================================================================================================================
enum
{
@ -2980,7 +3214,7 @@ cmDspRC_t _cmDspWaveTableReadAudioFile( cmDspCtx_t* ctx, cmDspWaveTable_t* p, un
cmDspRC_t _cmDspWaveTableInitAudioFile( cmDspCtx_t* ctx, cmDspWaveTable_t* p )
{
cmDspRC_t rc;
cmDspRC_t rc = kOkDspRC;
cmAudioFileH_t afH;
cmRC_t afRC;
cmAudioFileInfo_t afInfo;
@ -2992,7 +3226,7 @@ cmDspRC_t _cmDspWaveTableInitAudioFile( cmDspCtx_t* ctx, cmDspWaveTable_t* p )
// if the file name is valid
if( fn == NULL || strlen(fn)==0 )
{
cmDspInstErr(ctx,&p->inst,kVarNotValidDspRC,"Audio file loading was requested for the wave table but no file name was given.");
rc = cmDspInstErr(ctx,&p->inst,kVarNotValidDspRC,"Audio file loading was requested for the wave table but no file name was given.");
goto errLabel;
}
@ -3468,7 +3702,7 @@ cmDspRC_t _cmSprintfGetInputTypes( cmDspCtx_t* ctx, cmDspClass_t* classPtr, cons
snprintf(fmtArray[j].label,kSprintfLabelCharCnt,"in-%i",j);
fmtArray[j].label[kSprintfLabelCharCnt]=0;
fmtArray[j].label[kSprintfDocCharCnt] = 0;
fmtArray[j].doc[kSprintfDocCharCnt] = 0;
switch( fmt[ i + fn - 1 ] )
{
@ -4942,6 +5176,8 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
cmCounterClassCons,
cmPhasorClassCons,
cmMidiOutClassCons,
cmMidiInClassCons,
cmAudioInClassCons,
cmAudioOutClassCons,
cmAudioFileOutClassCons,
@ -5018,6 +5254,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
cmScFolClassCons,
cmScModClassCons,
cmGSwitchClassCons,
cmScaleRangeClassCons,
NULL,
};

View File

@ -25,6 +25,40 @@
#include "cmDspPgmPP.h"
#include "cmDspPgmKr.h"
cmDspRC_t _cmDspSysPgm_Test_Midi( cmDspSysH_t h, void** userPtrPtr )
{
cmDspRC_t rc = kOkDspRC;
cmDspInst_t* sendBtn = cmDspSysAllocInst( h,"Button", "Send", 2, kButtonDuiId, 0.0 );
cmDspInst_t* status = cmDspSysAllocInst( h,"Scalar", "Status", 5, kNumberDuiId, 0.0, 127.0, 1.0, 144.0);
cmDspInst_t* d0 = cmDspSysAllocInst( h,"Scalar", "D0", 5, kNumberDuiId, 0.0, 127.0, 1.0, 64.0);
cmDspInst_t* d1 = cmDspSysAllocInst( h,"Scalar", "D1", 5, kNumberDuiId, 0.0, 127.0, 1.0, 64.0);
cmDspInst_t* midiOut = cmDspSysAllocInst( h,"MidiOut", NULL, 2, "Fastlane", "Fastlane MIDI A");
cmDspInst_t* midiIn = cmDspSysAllocInst( h,"MidiIn", NULL, 0 );
cmDspInst_t* printer = cmDspSysAllocInst( h,"Printer", NULL, 1, ">" );
// check for allocation errors
if((rc = cmDspSysLastRC(h)) != kOkDspRC )
goto errLabel;
cmDspSysInstallCb( h, sendBtn, "out", d1, "send", NULL);
cmDspSysInstallCb( h, sendBtn, "out", d0, "send", NULL);
cmDspSysInstallCb( h, sendBtn, "out", status, "send", NULL);
cmDspSysInstallCb( h, status, "val", midiOut, "status",NULL);
cmDspSysInstallCb( h, d0, "val", midiOut, "d0", NULL);
cmDspSysInstallCb( h, d1, "val", midiOut, "d1", NULL);
cmDspSysInstallCb( h, midiIn, "status", printer, "in", NULL);
cmDspSysInstallCb( h, midiIn, "d0", printer, "in", NULL);
cmDspSysInstallCb( h, midiIn, "d1", printer, "in", NULL);
cmDspSysInstallCb( h, midiIn, "smpidx", printer, "in", NULL);
errLabel:
return rc;
}
cmDspRC_t _cmDspSysPgm_Stereo_Through( cmDspSysH_t h, void** userPtrPtr )
{
bool useBuiltInFl = true;
@ -2332,7 +2366,7 @@ cmDspRC_t _cmDspSysPgm_AvailCh( cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* fwtp = cmDspSysAllocInst( h, "WaveTable", NULL, 5, ((int)cmDspSysSampleRate(h)), 1, fn, -1, 7000000 );
cmDspInst_t* fad0 = cmDspSysAllocInst( h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl );
cmDspInst_t* prp = cmDspSysAllocInst( h, "Printer", NULL, 1, ">" );
//cmDspInst_t* prp = cmDspSysAllocInst( h, "Printer", NULL, 1, ">" );
cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 );
cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 );
@ -2389,6 +2423,7 @@ _cmDspSysPgm_t _cmDspSysPgmArray[] =
{ "pickup tails", _cmDspSysPgm_NoiseTails, NULL, NULL },
{ "tails_2", _cmDspSysPgm_NoiseTails2, NULL, NULL },
{ "pickups", _cmDspSysPgm_Pickups0, NULL, NULL },
{ "midi_test", _cmDspSysPgm_Test_Midi, NULL, NULL },
{ "2_thru", _cmDspSysPgm_Stereo_Through, NULL, NULL },
{ "guitar", _cmDspSysPgmGuitar, NULL, NULL },
{ "2_fx", _cmDspSysPgm_Stereo_Fx, NULL, NULL },

View File

@ -10,6 +10,7 @@
#include "cmText.h"
#include "cmFileSys.h"
#include "cmSymTbl.h"
#include "cmMidi.h"
#include "cmJson.h"
#include "cmPrefs.h"
#include "cmDspValue.h"
@ -619,10 +620,13 @@ cmDspRC_t cmDspSysRcvMsg( cmDspSysH_t h, cmAudioSysCtx_t* asCtx, const void*
}
else
{
// the msg selector is the second field in the data packet (following the audio system sub-system id)
const unsigned msgTypeSelId = ((const unsigned*)msgPtr)[1];
unsigned* hdr = (unsigned*)msgPtr;
switch( msgTypeSelId )
// the msg selector is the second field in the data packet (following the audio system sub-system id)
//const unsigned msgTypeSelId = ((const unsigned*)msgPtr)[1];
switch( hdr[1] )
{
case kUiSelAsId:
_cmDspSysHandleUiMsg(p,ip,msgPtr,msgByteCnt);
@ -633,11 +637,27 @@ cmDspRC_t cmDspSysRcvMsg( cmDspSysH_t h, cmAudioSysCtx_t* asCtx, const void*
break;
case kMidiMsgArraySelAsId:
{
cmMidiPacket_t pkt;
cmDspValue_t v;
pkt.cbDataPtr = NULL;
pkt.devIdx = hdr[2];
pkt.portIdx = hdr[3];
pkt.msgCnt = hdr[4];
pkt.msgArray = (cmMidiMsg*)(hdr + 5);
unsigned midiSymId = cmDspSysRegisterStaticSymbol(h,"_midi");
v.u.m.u.vp = &pkt;
cmDspSysBroadcastValue(h, midiSymId, &v);
/*
// data format for MIDI messages
{ kMidiMsgArraytSelAsId, devIdx, portIdx, msgCnt, msgArray[msgCnt] }
where each msgArray[] record is a cmMidiMsg record.
*/
}
break;
}