cwFlow* : Added MIDI input and output devices to 'flow' framework.
This commit is contained in:
parent
c4d518db47
commit
e49df496e6
24
cwFlow.cpp
24
cwFlow.cpp
@ -8,6 +8,8 @@
|
|||||||
#include "cwVectOps.h"
|
#include "cwVectOps.h"
|
||||||
#include "cwMtx.h"
|
#include "cwMtx.h"
|
||||||
#include "cwDspTypes.h" // real_t, sample_t
|
#include "cwDspTypes.h" // real_t, sample_t
|
||||||
|
#include "cwTime.h"
|
||||||
|
#include "cwMidiDecls.h"
|
||||||
#include "cwFlowDecl.h"
|
#include "cwFlowDecl.h"
|
||||||
#include "cwFlow.h"
|
#include "cwFlow.h"
|
||||||
#include "cwFlowTypes.h"
|
#include "cwFlowTypes.h"
|
||||||
@ -24,6 +26,8 @@ namespace cw
|
|||||||
} library_t;
|
} library_t;
|
||||||
|
|
||||||
library_t g_library[] = {
|
library_t g_library[] = {
|
||||||
|
{ "midi_in", &midi_in::members },
|
||||||
|
{ "midi_out", &midi_out::members },
|
||||||
{ "audio_in", &audio_in::members },
|
{ "audio_in", &audio_in::members },
|
||||||
{ "audio_out", &audio_out::members },
|
{ "audio_out", &audio_out::members },
|
||||||
{ "audioFileIn", &audioFileIn::members },
|
{ "audioFileIn", &audioFileIn::members },
|
||||||
@ -292,7 +296,7 @@ namespace cw
|
|||||||
|
|
||||||
if( src_var->value == nullptr )
|
if( src_var->value == nullptr )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kSyntaxErrorRC,"The source value is null on the connection input:%s %s source:%s %s .", in_inst->label, in_var_label, src_inst->label, suffix);
|
rc = cwLogError(kSyntaxErrorRC,"The source value is null on the connection input:'%s' %s source:'%s' '%s' .", in_inst->label, in_var_label, src_inst->label, suffix);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1549,7 +1553,7 @@ void cw::flow::print_abuf( const abuf_t* abuf )
|
|||||||
|
|
||||||
void cw::flow::print_external_device( const external_device_t* dev )
|
void cw::flow::print_external_device( const external_device_t* dev )
|
||||||
{
|
{
|
||||||
printf("Dev: %10s id:%3i type:%3i fl:0x%x : ", cwStringNullGuard(dev->label),dev->ioDevId,dev->typeId,dev->flags);
|
printf("Dev: %10s type:%3i fl:0x%x : ", cwStringNullGuard(dev->devLabel),dev->typeId,dev->flags);
|
||||||
if( dev->typeId == kAudioDevTypeId )
|
if( dev->typeId == kAudioDevTypeId )
|
||||||
print_abuf(dev->u.a.abuf);
|
print_abuf(dev->u.a.abuf);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -1603,6 +1607,19 @@ cw::rc_t cw::flow::create( handle_t& hRef,
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(unsigned i=0; i<deviceN; ++i)
|
||||||
|
if( deviceA[i].typeId == kAudioDevTypeId )
|
||||||
|
{
|
||||||
|
if( deviceA[i].u.a.abuf == NULL )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The audio '%s' device does not have a valid audio buffer.",cwStringNullGuard(deviceA[i].devLabel));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( deviceA[i].u.a.abuf->frameN != p->framesPerCycle )
|
||||||
|
cwLogWarning("The audio frame count (%i) for audio device '%s' does not match the Flow framesPerCycle (%i).",deviceA[i].u.a.abuf->frameN,p->framesPerCycle);
|
||||||
|
}
|
||||||
|
|
||||||
// print the class dict
|
// print the class dict
|
||||||
if( printClassDictFl )
|
if( printClassDictFl )
|
||||||
class_dict_print( p );
|
class_dict_print( p );
|
||||||
@ -1692,7 +1709,10 @@ cw::rc_t cw::flow::exec( handle_t h )
|
|||||||
|
|
||||||
p->cycleIndex += 1;
|
p->cycleIndex += 1;
|
||||||
if( p->maxCycleCount > 0 && p->cycleIndex >= p->maxCycleCount )
|
if( p->maxCycleCount > 0 && p->cycleIndex >= p->maxCycleCount )
|
||||||
|
{
|
||||||
|
cwLogInfo("'maxCycleCnt' reached: %i. Shutting down flow.",p->maxCycleCount);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
31
cwFlow.h
31
cwFlow.h
@ -31,17 +31,38 @@ namespace cw
|
|||||||
// The audio_in/audio_out proc's locate and use these buffers.
|
// The audio_in/audio_out proc's locate and use these buffers.
|
||||||
} audio_dev_cfg_t;
|
} audio_dev_cfg_t;
|
||||||
|
|
||||||
|
struct external_device_str;
|
||||||
|
|
||||||
|
typedef rc_t (*send_midi_triple_func_t)( struct external_device_str* dev, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1 );
|
||||||
|
|
||||||
|
typedef struct midi_dev_cfg_str
|
||||||
|
{
|
||||||
|
// msgArray[] contains the current msgs for all devices NOT just the device that this record is embedded in.
|
||||||
|
// We do this so that the order of messages as they arrived is maintained. Otherwise, to achieve this ordering,
|
||||||
|
// the messages for all devices would need to be collected and sorted by time.
|
||||||
|
const midi::ch_msg_t* msgArray;
|
||||||
|
unsigned msgCnt;
|
||||||
|
|
||||||
|
unsigned maxMsgCnt; // max possible value of msgCnt
|
||||||
|
send_midi_triple_func_t sendTripleFunc;
|
||||||
|
} midi_dev_cfg_t;
|
||||||
|
|
||||||
// Generate external device record
|
// Generate external device record
|
||||||
typedef struct external_device_str
|
typedef struct external_device_str
|
||||||
{
|
{
|
||||||
const char* label; // IO framework device label
|
void* reserved;
|
||||||
unsigned ioDevId; // IO framework device id
|
const char* devLabel; // IO framework device label
|
||||||
unsigned typeId; // see ???DevTypeId above
|
const char* portLabel; // IO framework MIDI port label (only used by MIDI devices)
|
||||||
unsigned flags; // see ???Fl above
|
unsigned typeId; // see ???DevTypeId above
|
||||||
|
unsigned flags; // see ???Fl above
|
||||||
|
|
||||||
|
unsigned ioDevIdx; // IO framework device index
|
||||||
|
unsigned ioPortIdx; // IO framework MIDI port index (only used by MIDI devices)
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
audio_dev_cfg_t a; // audio devices include this additional record
|
audio_dev_cfg_t a; // audio devices use this record
|
||||||
|
midi_dev_cfg_t m; // MIDI " " " "
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
} external_device_t;
|
} external_device_t;
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include "cwMtx.h"
|
#include "cwMtx.h"
|
||||||
#include "cwDspTypes.h" // real_t, sample_t
|
#include "cwDspTypes.h" // real_t, sample_t
|
||||||
#include "cwDspTransforms.h"
|
#include "cwDspTransforms.h"
|
||||||
|
#include "cwTime.h"
|
||||||
|
#include "cwMidiDecls.h"
|
||||||
#include "cwFlowDecl.h"
|
#include "cwFlowDecl.h"
|
||||||
#include "cwFlow.h"
|
#include "cwFlow.h"
|
||||||
#include "cwFlowTypes.h"
|
#include "cwFlowTypes.h"
|
||||||
@ -28,14 +30,15 @@ namespace cw
|
|||||||
kFadeOutStateId,
|
kFadeOutStateId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Each duplicated network is represented by a flow_netword_t record in flow_cross_t.netA[].
|
||||||
typedef struct flow_network_str
|
typedef struct flow_network_str
|
||||||
{
|
{
|
||||||
dsp::recorder::obj_t* recorder;
|
dsp::recorder::obj_t* recorder;
|
||||||
|
|
||||||
flow::external_device_t* deviceA;
|
flow::external_device_t* deviceA; // deviceA[ deviceN ] - cloned exteranl device array
|
||||||
unsigned deviceN;
|
unsigned deviceN;
|
||||||
flow::handle_t flowH;
|
flow::handle_t flowH;
|
||||||
|
|
||||||
unsigned stateId; // inactive, fade-in, fade-out
|
unsigned stateId; // inactive, fade-in, fade-out
|
||||||
double fadeGain; // 0 0->1 1->0
|
double fadeGain; // 0 0->1 1->0
|
||||||
unsigned fadeSmpN; //
|
unsigned fadeSmpN; //
|
||||||
@ -47,7 +50,7 @@ namespace cw
|
|||||||
|
|
||||||
typedef struct flow_cross_str
|
typedef struct flow_cross_str
|
||||||
{
|
{
|
||||||
unsigned cur_idx;
|
unsigned cur_idx; // index of the network currently receiving parameter updates
|
||||||
double srate;
|
double srate;
|
||||||
|
|
||||||
unsigned netN;
|
unsigned netN;
|
||||||
@ -106,8 +109,21 @@ namespace cw
|
|||||||
memcpy(devA,srcDevA,devN * sizeof(flow::external_device_t));
|
memcpy(devA,srcDevA,devN * sizeof(flow::external_device_t));
|
||||||
|
|
||||||
for(unsigned i=0; i<devN; ++i)
|
for(unsigned i=0; i<devN; ++i)
|
||||||
if( devA[i].typeId == flow::kAudioDevTypeId )
|
{
|
||||||
devA[i].u.a.abuf = _clone_abuf( srcDevA[i].u.a.abuf );
|
switch( devA[i].typeId )
|
||||||
|
{
|
||||||
|
case flow::kAudioDevTypeId:
|
||||||
|
devA[i].u.a.abuf = _clone_abuf( srcDevA[i].u.a.abuf );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case flow::kMidiDevTypeId:
|
||||||
|
devA[i].u.m = srcDevA[i].u.m;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return devA;
|
return devA;
|
||||||
}
|
}
|
||||||
@ -203,9 +219,20 @@ namespace cw
|
|||||||
|
|
||||||
if( net->stateId == kFadeOutStateId && ef == 0.0 )
|
if( net->stateId == kFadeOutStateId && ef == 0.0 )
|
||||||
net->stateId = kInactiveStateId;
|
net->stateId = kInactiveStateId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy audio from the actual external audio device to a cloned audio device
|
||||||
|
void _update_midi_input( flow_cross_t* p, flow_network_t* net, unsigned devIdx )
|
||||||
|
{
|
||||||
|
flow::midi_dev_cfg_t& src = p->deviceA[devIdx].u.m; // src MIDI device
|
||||||
|
flow::midi_dev_cfg_t& dst = net->deviceA[devIdx].u.m; // dst MIDI device clone
|
||||||
|
|
||||||
|
// redirect the MIDI msg list array to the clones
|
||||||
|
dst.msgArray = src.msgArray;
|
||||||
|
dst.msgCnt = src.msgCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy audio from the actual external audio device to a cloned audio device
|
||||||
void _update_audio_input( flow_cross_t* p, flow_network_t* net, unsigned devIdx )
|
void _update_audio_input( flow_cross_t* p, flow_network_t* net, unsigned devIdx )
|
||||||
{
|
{
|
||||||
flow::abuf_t* src = p->deviceA[devIdx].u.a.abuf;
|
flow::abuf_t* src = p->deviceA[devIdx].u.a.abuf;
|
||||||
@ -216,6 +243,7 @@ namespace cw
|
|||||||
//_fade_audio( src, dst, net );
|
//_fade_audio( src, dst, net );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _zero_audio_output( flow_cross_t* p, flow_network_t* net, unsigned devIdx )
|
void _zero_audio_output( flow_cross_t* p, flow_network_t* net, unsigned devIdx )
|
||||||
{
|
{
|
||||||
flow::abuf_t* dst = net->deviceA[devIdx].u.a.abuf;
|
flow::abuf_t* dst = net->deviceA[devIdx].u.a.abuf;
|
||||||
@ -378,13 +406,27 @@ cw::rc_t cw::flow_cross::exec_cycle( handle_t h )
|
|||||||
{
|
{
|
||||||
flow_network_t* net = p->netA + i;
|
flow_network_t* net = p->netA + i;
|
||||||
|
|
||||||
// We generally don't want to fade the input because the state
|
|
||||||
// of the network delay lines would then be invalid when the
|
|
||||||
// network is eventually made active again
|
|
||||||
for(unsigned j=0; j<p->deviceN; ++j)
|
for(unsigned j=0; j<p->deviceN; ++j)
|
||||||
if( p->deviceA[j].typeId == flow::kAudioDevTypeId && cwIsFlag(p->deviceA[j].flags, flow::kInFl ) )
|
if( cwIsFlag(p->deviceA[j].flags, flow::kInFl ) )
|
||||||
_update_audio_input( p, p->netA + i, j );
|
{
|
||||||
|
switch( p->deviceA[j].typeId)
|
||||||
|
{
|
||||||
|
case flow::kAudioDevTypeId:
|
||||||
|
// We generally don't want to fade the input because the state
|
||||||
|
// of the network delay lines would then be invalid when the
|
||||||
|
// network is eventually made active again
|
||||||
|
|
||||||
|
// copy audio from the actual audio device to the cloned audio devices
|
||||||
|
_update_audio_input( p, p->netA + i, j );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case flow::kMidiDevTypeId:
|
||||||
|
// update the cloned MIDI devices from the master device
|
||||||
|
_update_midi_input( p, p->netA + i, j );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// zero the audio device output buffers because we are about to sum into them
|
// zero the audio device output buffers because we are about to sum into them
|
||||||
for(unsigned j=0; j<p->deviceN; ++j)
|
for(unsigned j=0; j<p->deviceN; ++j)
|
||||||
if( p->deviceA[j].typeId == flow::kAudioDevTypeId && cwIsFlag(p->deviceA[j].flags, flow::kOutFl ) )
|
if( p->deviceA[j].typeId == flow::kAudioDevTypeId && cwIsFlag(p->deviceA[j].flags, flow::kOutFl ) )
|
||||||
|
251
cwFlowProc.cpp
251
cwFlowProc.cpp
@ -2,12 +2,18 @@
|
|||||||
#include "cwLog.h"
|
#include "cwLog.h"
|
||||||
#include "cwCommonImpl.h"
|
#include "cwCommonImpl.h"
|
||||||
#include "cwMem.h"
|
#include "cwMem.h"
|
||||||
|
#include "cwText.h"
|
||||||
#include "cwObject.h"
|
#include "cwObject.h"
|
||||||
#include "cwAudioFile.h"
|
#include "cwAudioFile.h"
|
||||||
#include "cwVectOps.h"
|
#include "cwVectOps.h"
|
||||||
#include "cwMtx.h"
|
#include "cwMtx.h"
|
||||||
|
|
||||||
#include "cwDspTypes.h" // real_t, sample_t
|
#include "cwDspTypes.h" // real_t, sample_t
|
||||||
|
|
||||||
|
#include "cwTime.h"
|
||||||
|
#include "cwMidiDecls.h"
|
||||||
|
|
||||||
|
|
||||||
#include "cwFlowDecl.h"
|
#include "cwFlowDecl.h"
|
||||||
#include "cwFlow.h"
|
#include "cwFlow.h"
|
||||||
#include "cwFlowTypes.h"
|
#include "cwFlowTypes.h"
|
||||||
@ -164,6 +170,251 @@ namespace cw
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// midi_in
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace midi_in
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kDevLabelPId,
|
||||||
|
kPortLabelPId,
|
||||||
|
kOutPId
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
midi::ch_msg_t* buf;
|
||||||
|
unsigned bufN;
|
||||||
|
bool dev_filt_fl;
|
||||||
|
bool port_filt_fl;
|
||||||
|
external_device_t* ext_dev;
|
||||||
|
} inst_t;
|
||||||
|
|
||||||
|
rc_t create( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const char* dev_label = nullptr;
|
||||||
|
const char* port_label = nullptr;
|
||||||
|
inst_t* inst = mem::allocZ<inst_t>();
|
||||||
|
|
||||||
|
ctx->userPtr = inst;
|
||||||
|
|
||||||
|
// Register variable and get their current value
|
||||||
|
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
||||||
|
kDevLabelPId, "dev_label", dev_label,
|
||||||
|
kPortLabelPId, "port_label", port_label )) != kOkRC )
|
||||||
|
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = var_register( ctx, kAnyChIdx,kOutPId, "out")) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inst->dev_filt_fl = true;
|
||||||
|
inst->port_filt_fl = true;
|
||||||
|
|
||||||
|
if( textIsEqual(dev_label,"<all>") )
|
||||||
|
{
|
||||||
|
inst->dev_filt_fl = false;
|
||||||
|
dev_label = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( textIsEqual(dev_label,"<all>") )
|
||||||
|
{
|
||||||
|
inst->port_filt_fl = false;
|
||||||
|
port_label = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if((inst->ext_dev = external_device_find( ctx->ctx, dev_label, kMidiDevTypeId, kInFl, port_label )) == nullptr )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The MIDI input device '%s' port '%s' could not be found.", cwStringNullGuard(dev_label), cwStringNullGuard(port_label));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a buffer large enough to hold the max. number of messages arriving on a single call to exec().
|
||||||
|
inst->bufN = inst->ext_dev->u.m.maxMsgCnt;
|
||||||
|
inst->buf = mem::allocZ<midi::ch_msg_t>( inst->bufN );
|
||||||
|
|
||||||
|
// create one output audio buffer
|
||||||
|
rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, nullptr, 0 );
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t destroy( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
mem::release(inst->buf);
|
||||||
|
|
||||||
|
mem::release(inst);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t value( instance_t* ctx, variable_t* var )
|
||||||
|
{ return kOkRC; }
|
||||||
|
|
||||||
|
rc_t exec( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
mbuf_t* mbuf = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
// get the output variable
|
||||||
|
if((rc = var_get(ctx,kOutPId,kAnyChIdx,mbuf)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The MIDI file instance '%s' does not have a valid MIDI output buffer.",ctx->label);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the device filter is not set
|
||||||
|
if( !inst->dev_filt_fl)
|
||||||
|
{
|
||||||
|
mbuf->msgA = inst->ext_dev->u.m.msgArray;
|
||||||
|
mbuf->msgN = inst->ext_dev->u.m.msgCnt;
|
||||||
|
}
|
||||||
|
else // the device filter is set
|
||||||
|
{
|
||||||
|
const midi::ch_msg_t* m = inst->ext_dev->u.m.msgArray;
|
||||||
|
unsigned j = 0;
|
||||||
|
for(unsigned i=0; i<inst->ext_dev->u.m.msgCnt && j<inst->bufN; ++i)
|
||||||
|
if( m->devIdx == inst->ext_dev->ioDevIdx && (!inst->port_filt_fl || m->portIdx == inst->ext_dev->ioPortIdx) )
|
||||||
|
inst->buf[j++] = m[i];
|
||||||
|
|
||||||
|
mbuf->msgN = j;
|
||||||
|
mbuf->msgA = inst->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_members_t members = {
|
||||||
|
.create = create,
|
||||||
|
.destroy = destroy,
|
||||||
|
.value = value,
|
||||||
|
.exec = exec,
|
||||||
|
.report = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// midi_out
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace midi_out
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kInPId,
|
||||||
|
kDevLabelPId,
|
||||||
|
kPortLabelPId
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
external_device_t* ext_dev;
|
||||||
|
} inst_t;
|
||||||
|
|
||||||
|
rc_t create( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC; //
|
||||||
|
inst_t* inst = mem::allocZ<inst_t>(); //
|
||||||
|
const char* dev_label = nullptr;
|
||||||
|
const char* port_label = nullptr;
|
||||||
|
mbuf_t* mbuf = nullptr;
|
||||||
|
|
||||||
|
ctx->userPtr = inst;
|
||||||
|
|
||||||
|
// Register variables and get their current value
|
||||||
|
if((rc = var_register_and_get( ctx, kAnyChIdx,
|
||||||
|
kDevLabelPId, "dev_label", dev_label,
|
||||||
|
kPortLabelPId,"port_label", port_label,
|
||||||
|
kInPId, "in", mbuf)) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((inst->ext_dev = external_device_find( ctx->ctx, dev_label, kMidiDevTypeId, kOutFl, port_label )) == nullptr )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The audio output device description '%s' could not be found.", cwStringNullGuard(dev_label));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t destroy( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
|
||||||
|
mem::release(inst);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t value( instance_t* ctx, variable_t* var )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t exec( instance_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
inst_t* inst = (inst_t*)ctx->userPtr;
|
||||||
|
const mbuf_t* src_mbuf = nullptr;
|
||||||
|
|
||||||
|
if((rc = var_get(ctx,kInPId,kAnyChIdx,src_mbuf)) != kOkRC )
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The MIDI output instance '%s' does not have a valid input connection.",ctx->label);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<src_mbuf->msgN; ++i)
|
||||||
|
{
|
||||||
|
const midi::ch_msg_t* m = src_mbuf->msgA + i;
|
||||||
|
inst->ext_dev->u.m.sendTripleFunc( inst->ext_dev, m->ch, m->status, m->d0, m->d1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_members_t members = {
|
||||||
|
.create = create,
|
||||||
|
.destroy = destroy,
|
||||||
|
.value = value,
|
||||||
|
.exec = exec,
|
||||||
|
.report = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -2,6 +2,8 @@ namespace cw
|
|||||||
{
|
{
|
||||||
namespace flow
|
namespace flow
|
||||||
{
|
{
|
||||||
|
namespace midi_in { extern class_members_t members; }
|
||||||
|
namespace midi_out { extern class_members_t members; }
|
||||||
namespace audio_in { extern class_members_t members; }
|
namespace audio_in { extern class_members_t members; }
|
||||||
namespace audio_out { extern class_members_t members; }
|
namespace audio_out { extern class_members_t members; }
|
||||||
namespace audioFileIn { extern class_members_t members; }
|
namespace audioFileIn { extern class_members_t members; }
|
||||||
|
135
cwFlowTypes.cpp
135
cwFlowTypes.cpp
@ -7,6 +7,8 @@
|
|||||||
#include "cwVectOps.h"
|
#include "cwVectOps.h"
|
||||||
#include "cwMtx.h"
|
#include "cwMtx.h"
|
||||||
#include "cwDspTypes.h" // real_t, sample_t
|
#include "cwDspTypes.h" // real_t, sample_t
|
||||||
|
#include "cwTime.h"
|
||||||
|
#include "cwMidiDecls.h"
|
||||||
#include "cwFlowDecl.h"
|
#include "cwFlowDecl.h"
|
||||||
#include "cwFlow.h"
|
#include "cwFlow.h"
|
||||||
#include "cwFlowTypes.h"
|
#include "cwFlowTypes.h"
|
||||||
@ -18,21 +20,22 @@ namespace cw
|
|||||||
{
|
{
|
||||||
idLabelPair_t typeLabelFlagsA[] = {
|
idLabelPair_t typeLabelFlagsA[] = {
|
||||||
|
|
||||||
{ kBoolTFl, "bool" },
|
{ kBoolTFl, "bool" },
|
||||||
{ kUIntTFl, "uint" },
|
{ kUIntTFl, "uint" },
|
||||||
{ kIntTFl, "int", },
|
{ kIntTFl, "int", },
|
||||||
{ kFloatTFl, "float"},
|
{ kFloatTFl, "float"},
|
||||||
{ kRealTFl, "real"},
|
{ kRealTFl, "real"},
|
||||||
{ kDoubleTFl, "double"},
|
{ kDoubleTFl,"double"},
|
||||||
|
|
||||||
{ kBoolMtxTFl, "bool_mtx" },
|
{ kBoolMtxTFl, "bool_mtx" },
|
||||||
{ kUIntMtxTFl, "uint_mtx" },
|
{ kUIntMtxTFl, "uint_mtx" },
|
||||||
{ kIntMtxTFl, "int_mtx" },
|
{ kIntMtxTFl, "int_mtx" },
|
||||||
{ kFloatMtxTFl, "float_mtx" },
|
{ kFloatMtxTFl, "float_mtx" },
|
||||||
{ kDoubleMtxTFl, "double_mtx" },
|
{ kDoubleMtxTFl,"double_mtx" },
|
||||||
|
|
||||||
{ kABufTFl, "audio" },
|
{ kABufTFl, "audio" },
|
||||||
{ kFBufTFl, "spectrum" },
|
{ kFBufTFl, "spectrum" },
|
||||||
|
{ kMBufTFl, "midi" },
|
||||||
{ kStringTFl, "string" },
|
{ kStringTFl, "string" },
|
||||||
{ kTimeTFl, "time" },
|
{ kTimeTFl, "time" },
|
||||||
{ kInvalidTFl, nullptr }
|
{ kInvalidTFl, nullptr }
|
||||||
@ -73,6 +76,9 @@ namespace cw
|
|||||||
fbuf_destroy( v->u.fbuf );
|
fbuf_destroy( v->u.fbuf );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kMBufTFl:
|
||||||
|
mbuf_destroy( v->u.mbuf );
|
||||||
|
break;
|
||||||
|
|
||||||
case kBoolMtxTFl:
|
case kBoolMtxTFl:
|
||||||
case kUIntMtxTFl:
|
case kUIntMtxTFl:
|
||||||
@ -99,8 +105,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _value_duplicate( value_t& dst, const value_t& src )
|
void _value_duplicate( value_t& dst, const value_t& src )
|
||||||
{
|
{
|
||||||
|
|
||||||
switch( src.flags & kTypeMask )
|
switch( src.flags & kTypeMask )
|
||||||
{
|
{
|
||||||
case kInvalidTFl:
|
case kInvalidTFl:
|
||||||
@ -125,6 +130,10 @@ namespace cw
|
|||||||
dst.flags = src.flags;
|
dst.flags = src.flags;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kMBufTFl:
|
||||||
|
dst.u.mbuf = src.u.mbuf == nullptr ? nullptr : mbuf_duplicate(src.u.mbuf);
|
||||||
|
dst.flags = src.flags;
|
||||||
|
break;
|
||||||
|
|
||||||
case kBoolMtxTFl:
|
case kBoolMtxTFl:
|
||||||
case kUIntMtxTFl:
|
case kUIntMtxTFl:
|
||||||
@ -182,6 +191,15 @@ namespace cw
|
|||||||
printf("(binN:%i hopSmpN:%i) ", v->u.fbuf->binN_V[i], v->u.fbuf->hopSmpN_V[i] );
|
printf("(binN:%i hopSmpN:%i) ", v->u.fbuf->binN_V[i], v->u.fbuf->hopSmpN_V[i] );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kMBufTFl:
|
||||||
|
if( v->u.mbuf == nullptr )
|
||||||
|
printf("mbuf: <null>");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("mbuf: cnt: %i", v->u.mbuf->msgN );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case kBoolMtxTFl:
|
case kBoolMtxTFl:
|
||||||
case kUIntMtxTFl:
|
case kUIntMtxTFl:
|
||||||
@ -345,6 +363,28 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _val_get( value_t* val, mbuf_t*& valRef )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
if( cwIsFlag(val->flags & kTypeMask, kMBufTFl) )
|
||||||
|
valRef = val->u.mbuf;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valRef = nullptr;
|
||||||
|
rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an mbuf_t.",val->flags);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _val_get( value_t* val, const mbuf_t*& valRef )
|
||||||
|
{
|
||||||
|
mbuf_t* non_const_val;
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
if((rc = _val_get(val,non_const_val)) == kOkRC )
|
||||||
|
valRef = non_const_val;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
rc_t _val_get_driver( const variable_t* var, T& valRef )
|
rc_t _val_get_driver( const variable_t* var, T& valRef )
|
||||||
@ -492,6 +532,14 @@ namespace cw
|
|||||||
var->local_value[ local_value_idx ].flags = kABufTFl;
|
var->local_value[ local_value_idx ].flags = kABufTFl;
|
||||||
cwLogMod("%s.%s ch:%i %s (abuf).",var->inst->label,var->label,var->chIdx,abuf==nullptr ? "null" : "valid");
|
cwLogMod("%s.%s ch:%i %s (abuf).",var->inst->label,var->label,var->chIdx,abuf==nullptr ? "null" : "valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void _var_setter<mbuf_t*>( variable_t* var, unsigned local_value_idx, mbuf_t* val )
|
||||||
|
{
|
||||||
|
var->local_value[ local_value_idx ].u.mbuf = val;
|
||||||
|
var->local_value[ local_value_idx ].flags = kMBufTFl;
|
||||||
|
cwLogMod("%s.%s ch:%i %s (abuf).",var->inst->label,var->label,var->chIdx,mbuf==nullptr ? "null" : "valid");
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void _var_setter<fbuf_t*>( variable_t* var, unsigned local_value_idx, fbuf_t* val )
|
void _var_setter<fbuf_t*>( variable_t* var, unsigned local_value_idx, fbuf_t* val )
|
||||||
@ -609,6 +657,19 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, mbuf_t* mbuf )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
variable_t* var = nullptr;
|
||||||
|
if((rc = var_register_and_set( inst, var_label, vid, chIdx, var)) != kOkRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if( var != nullptr )
|
||||||
|
_var_set_driver( var, kMBufTFl, mbuf );
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, fbuf_t* fbuf )
|
rc_t _var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, fbuf_t* fbuf )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
@ -1010,6 +1071,25 @@ cw::flow::fbuf_t* cw::flow::fbuf_duplicate( const fbuf_t* src )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cw::flow::mbuf_t* cw::flow::mbuf_create( const midi::ch_msg_t* msgA, unsigned msgN )
|
||||||
|
{
|
||||||
|
mbuf_t* m = mem::allocZ<mbuf_t>();
|
||||||
|
m->msgA = msgA;
|
||||||
|
m->msgN = msgN;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::flow::mbuf_destroy( mbuf_t*& buf )
|
||||||
|
{
|
||||||
|
mem::release(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::flow::mbuf_t* cw::flow::mbuf_duplicate( const mbuf_t* src )
|
||||||
|
{
|
||||||
|
return mbuf_create(src->msgA,src->msgN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::flow::value_type_label_to_flag( const char* s )
|
unsigned cw::flow::value_type_label_to_flag( const char* s )
|
||||||
{
|
{
|
||||||
unsigned flags = labelToId(typeLabelFlagsA,s,kInvalidTFl);
|
unsigned flags = labelToId(typeLabelFlagsA,s,kInvalidTFl);
|
||||||
@ -1089,10 +1169,13 @@ cw::rc_t cw::flow::instance_find( flow_t* p, const char* inst_label, instance_t*
|
|||||||
return cwLogError(kInvalidArgRC,"The instance '%s' was not found.", inst_label );
|
return cwLogError(kInvalidArgRC,"The instance '%s' was not found.", inst_label );
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::flow::external_device_t* cw::flow::external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl )
|
cw::flow::external_device_t* cw::flow::external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl, const char* midiPortLabel )
|
||||||
{
|
{
|
||||||
for(unsigned i=0; i<p->deviceN; ++i)
|
for(unsigned i=0; i<p->deviceN; ++i)
|
||||||
if( cw::textIsEqual(p->deviceA[i].label,device_label) && p->deviceA[i].typeId==typeId && cwIsFlag(p->deviceA[i].flags,inOrOutFl ))
|
if( (device_label==nullptr || cw::textIsEqual(p->deviceA[i].devLabel,device_label))
|
||||||
|
&& p->deviceA[i].typeId==typeId
|
||||||
|
&& cwIsFlag(p->deviceA[i].flags,inOrOutFl)
|
||||||
|
&& (midiPortLabel==nullptr || cw::textIsEqual(p->deviceA[i].portLabel,midiPortLabel)) )
|
||||||
return p->deviceA + i;
|
return p->deviceA + i;
|
||||||
|
|
||||||
cwLogError(kInvalidArgRC,"The %s device named '%s' could not be found.", cwIsFlag(inOrOutFl,kInFl) ? "in" : "out", device_label );
|
cwLogError(kInvalidArgRC,"The %s device named '%s' could not be found.", cwIsFlag(inOrOutFl,kInFl) ? "in" : "out", device_label );
|
||||||
@ -1381,6 +1464,21 @@ cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, midi::ch_msg_t* msgA, unsigned msgN )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
mbuf_t* mbuf;
|
||||||
|
|
||||||
|
if((mbuf = mbuf_create(msgA,msgN)) == nullptr )
|
||||||
|
return cwLogError(kOpFailRC,"mbuf create failed on instance:'%s' variable:'%s'.", inst->label, var_label);
|
||||||
|
|
||||||
|
if((rc = _var_register_and_set( inst, var_label, vid, chIdx, mbuf )) != kOkRC )
|
||||||
|
mbuf_destroy(mbuf);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_real_t** magV, const fd_real_t** phsV, const fd_real_t** hzV )
|
cw::rc_t cw::flow::var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_real_t** magV, const fd_real_t** phsV, const fd_real_t** hzV )
|
||||||
{
|
{
|
||||||
unsigned maxBinN_V[ chN ];
|
unsigned maxBinN_V[ chN ];
|
||||||
@ -1423,6 +1521,13 @@ cw::rc_t cw::flow::var_get( const variable_t* var, const fbuf_t*& valRef )
|
|||||||
cw::rc_t cw::flow::var_get( variable_t* var, fbuf_t*& valRef )
|
cw::rc_t cw::flow::var_get( variable_t* var, fbuf_t*& valRef )
|
||||||
{ return _val_get_driver(var,valRef); }
|
{ return _val_get_driver(var,valRef); }
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::var_get( const variable_t* var, const mbuf_t*& valRef )
|
||||||
|
{ return _val_get_driver(var,valRef); }
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::var_get( variable_t* var, mbuf_t*& valRef )
|
||||||
|
{ return _val_get_driver(var,valRef); }
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val )
|
cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
@ -4,16 +4,22 @@ namespace cw
|
|||||||
{
|
{
|
||||||
|
|
||||||
#define kRealTFl kFloatTFl
|
#define kRealTFl kFloatTFl
|
||||||
typedef dsp::real_t real_t;
|
typedef dsp::real_t real_t;
|
||||||
typedef dsp::sample_t sample_t;
|
typedef dsp::sample_t sample_t;
|
||||||
typedef dsp::fd_real_t fd_real_t;
|
typedef dsp::fd_real_t fd_real_t;
|
||||||
typedef dsp::srate_t srate_t;
|
typedef dsp::srate_t srate_t;
|
||||||
typedef unsigned uint_t;
|
typedef unsigned uint_t;
|
||||||
typedef int int_t;
|
typedef int int_t;
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned vid_t;
|
typedef unsigned vid_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kFbufVectN = 3, // count of signal vectors in fbuf (mag,phs,hz)
|
||||||
|
kAnyChIdx = kInvalidIdx,
|
||||||
|
kLocalValueN = 2
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct abuf_str
|
typedef struct abuf_str
|
||||||
{
|
{
|
||||||
struct value_str* base;
|
struct value_str* base;
|
||||||
@ -24,12 +30,6 @@ namespace cw
|
|||||||
} abuf_t;
|
} abuf_t;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
kFbufVectN = 3, // count of signal vectors in fbuf (mag,phs,hz)
|
|
||||||
kAnyChIdx = kInvalidIdx,
|
|
||||||
kLocalValueN = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct fbuf_str
|
typedef struct fbuf_str
|
||||||
{
|
{
|
||||||
struct value_str* base;
|
struct value_str* base;
|
||||||
@ -39,13 +39,20 @@ namespace cw
|
|||||||
unsigned* maxBinN_V; // max value that binN_V[i] is allowed to take
|
unsigned* maxBinN_V; // max value that binN_V[i] is allowed to take
|
||||||
unsigned* binN_V; // binN_V[ chN ] count of sample frames per channel
|
unsigned* binN_V; // binN_V[ chN ] count of sample frames per channel
|
||||||
unsigned* hopSmpN_V; // hopSmpN_V[ chN ] hop sample count
|
unsigned* hopSmpN_V; // hopSmpN_V[ chN ] hop sample count
|
||||||
fd_real_t** magV; // magV[ chN ][ binN ]
|
fd_real_t** magV; // magV[ chN ][ binN ]
|
||||||
fd_real_t** phsV; // phsV[ chN ][ binN ]
|
fd_real_t** phsV; // phsV[ chN ][ binN ]
|
||||||
fd_real_t** hzV; // hzV[ chN ][ binN ]
|
fd_real_t** hzV; // hzV[ chN ][ binN ]
|
||||||
bool* readyFlV; // readyFlV[chN] true if this channel is ready to be processed (used to sync. fbuf rate to abuf rate)
|
bool* readyFlV; // readyFlV[chN] true if this channel is ready to be processed (used to sync. fbuf rate to abuf rate)
|
||||||
fd_real_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer)
|
fd_real_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer)
|
||||||
} fbuf_t;
|
} fbuf_t;
|
||||||
|
|
||||||
|
typedef struct mbuf_str
|
||||||
|
{
|
||||||
|
struct value_str* base;
|
||||||
|
const midi::ch_msg_t* msgA;
|
||||||
|
unsigned msgN;
|
||||||
|
} mbuf_t;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kInvalidTFl = 0x00000000,
|
kInvalidTFl = 0x00000000,
|
||||||
@ -64,10 +71,11 @@ namespace cw
|
|||||||
|
|
||||||
kABufTFl = 0x00000800,
|
kABufTFl = 0x00000800,
|
||||||
kFBufTFl = 0x00001000,
|
kFBufTFl = 0x00001000,
|
||||||
kStringTFl = 0x00002000,
|
kMBufTFl = 0x00002000,
|
||||||
kTimeTFl = 0x00004000,
|
kStringTFl = 0x00004000,
|
||||||
|
kTimeTFl = 0x00008000,
|
||||||
|
|
||||||
kTypeMask = 0x00007fff,
|
kTypeMask = 0x0000ffff,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -96,6 +104,7 @@ namespace cw
|
|||||||
|
|
||||||
abuf_t* abuf;
|
abuf_t* abuf;
|
||||||
fbuf_t* fbuf;
|
fbuf_t* fbuf;
|
||||||
|
mbuf_t* mbuf;
|
||||||
|
|
||||||
char* s;
|
char* s;
|
||||||
char* fname;
|
char* fname;
|
||||||
@ -115,11 +124,11 @@ namespace cw
|
|||||||
|
|
||||||
typedef rc_t (*member_func_t)( struct instance_str* ctx );
|
typedef rc_t (*member_func_t)( struct instance_str* ctx );
|
||||||
typedef rc_t (*member_value_func_t)( struct instance_str* ctx, struct variable_str* var );
|
typedef rc_t (*member_value_func_t)( struct instance_str* ctx, struct variable_str* var );
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kSrcVarFl = 0x01,
|
kSrcVarFl = 0x01,
|
||||||
kSrcOptVarFl = 0x02
|
kSrcOptVarFl = 0x02
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct class_members_str
|
typedef struct class_members_str
|
||||||
@ -242,6 +251,10 @@ namespace cw
|
|||||||
fbuf_t* fbuf_create( srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_real_t** magV=nullptr, const fd_real_t** phsV=nullptr, const fd_real_t** hzV=nullptr );
|
fbuf_t* fbuf_create( srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_real_t** magV=nullptr, const fd_real_t** phsV=nullptr, const fd_real_t** hzV=nullptr );
|
||||||
void fbuf_destroy( fbuf_t*& buf );
|
void fbuf_destroy( fbuf_t*& buf );
|
||||||
fbuf_t* fbuf_duplicate( const fbuf_t* src );
|
fbuf_t* fbuf_duplicate( const fbuf_t* src );
|
||||||
|
|
||||||
|
mbuf_t* mbuf_create( const midi::ch_msg_t* msgA=nullptr, unsigned msgN=0 );
|
||||||
|
void mbuf_destroy( mbuf_t*& buf );
|
||||||
|
mbuf_t* mbuf_duplicate( const mbuf_t* src );
|
||||||
|
|
||||||
inline bool value_is_abuf( const value_t* v ) { return v->flags & kABufTFl; }
|
inline bool value_is_abuf( const value_t* v ) { return v->flags & kABufTFl; }
|
||||||
inline bool value_is_fbuf( const value_t* v ) { return v->flags & kFBufTFl; }
|
inline bool value_is_fbuf( const value_t* v ) { return v->flags & kFBufTFl; }
|
||||||
@ -274,7 +287,7 @@ namespace cw
|
|||||||
|
|
||||||
instance_t* instance_find( flow_t* p, const char* inst_label );
|
instance_t* instance_find( flow_t* p, const char* inst_label );
|
||||||
rc_t instance_find( flow_t* p, const char* inst_label, instance_t*& instPtrRef );
|
rc_t instance_find( flow_t* p, const char* inst_label, instance_t*& instPtrRef );
|
||||||
external_device_t* external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl );
|
external_device_t* external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl, const char* midiPortLabel=nullptr );
|
||||||
|
|
||||||
void instance_print( instance_t* inst );
|
void instance_print( instance_t* inst );
|
||||||
|
|
||||||
@ -374,6 +387,7 @@ namespace cw
|
|||||||
rc_t var_register_and_set( instance_t* inst, const char* label, unsigned vid, unsigned chIdx, variable_t*& varRef );
|
rc_t var_register_and_set( instance_t* inst, const char* label, unsigned vid, unsigned chIdx, variable_t*& varRef );
|
||||||
|
|
||||||
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned frameN );
|
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned frameN );
|
||||||
|
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, midi::ch_msg_t* midiA, unsigned midiN );
|
||||||
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const fd_real_t** magV=nullptr, const fd_real_t** phsV=nullptr, const fd_real_t** hzV=nullptr );
|
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const fd_real_t** magV=nullptr, const fd_real_t** phsV=nullptr, const fd_real_t** hzV=nullptr );
|
||||||
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_real_t** magV=nullptr, const fd_real_t** phsV=nullptr, const fd_real_t** hzV=nullptr );
|
rc_t var_register_and_set( instance_t* inst, const char* var_label, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_real_t** magV=nullptr, const fd_real_t** phsV=nullptr, const fd_real_t** hzV=nullptr );
|
||||||
|
|
||||||
@ -427,6 +441,8 @@ namespace cw
|
|||||||
rc_t var_get( variable_t* var, abuf_t*& valRef );
|
rc_t var_get( variable_t* var, abuf_t*& valRef );
|
||||||
rc_t var_get( const variable_t* var, const fbuf_t*& valRef );
|
rc_t var_get( const variable_t* var, const fbuf_t*& valRef );
|
||||||
rc_t var_get( variable_t* var, fbuf_t*& valRef );
|
rc_t var_get( variable_t* var, fbuf_t*& valRef );
|
||||||
|
rc_t var_get( const variable_t* var, const mbuf_t*& valRef );
|
||||||
|
rc_t var_get( variable_t* var, mbuf_t*& valRef );
|
||||||
|
|
||||||
template< typename T>
|
template< typename T>
|
||||||
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, T& valRef)
|
rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, T& valRef)
|
||||||
|
80
cwIoFlow.cpp
80
cwIoFlow.cpp
@ -8,6 +8,8 @@
|
|||||||
#include "cwTime.h"
|
#include "cwTime.h"
|
||||||
#include "cwVectOps.h"
|
#include "cwVectOps.h"
|
||||||
#include "cwMtx.h"
|
#include "cwMtx.h"
|
||||||
|
#include "cwTime.h"
|
||||||
|
#include "cwMidiDecls.h"
|
||||||
|
|
||||||
#include "cwDspTypes.h"
|
#include "cwDspTypes.h"
|
||||||
#include "cwFlowDecl.h"
|
#include "cwFlowDecl.h"
|
||||||
@ -87,7 +89,7 @@ namespace cw
|
|||||||
|
|
||||||
mem::release(p->audioGroupA);
|
mem::release(p->audioGroupA);
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,10 +97,13 @@ namespace cw
|
|||||||
{
|
{
|
||||||
unsigned devN = 0;
|
unsigned devN = 0;
|
||||||
|
|
||||||
//devN += midiDeviceCount(p->ioH);
|
|
||||||
devN += socketCount(p->ioH);
|
devN += socketCount(p->ioH);
|
||||||
devN += serialDeviceCount(p->ioH);
|
devN += serialDeviceCount(p->ioH);
|
||||||
|
|
||||||
|
unsigned midiDevN = midiDeviceCount(p->ioH);
|
||||||
|
for(unsigned i=0; i<midiDevN; ++i)
|
||||||
|
devN += midiDevicePortCount(p->ioH,i,true) + midiDevicePortCount(p->ioH,i,false);
|
||||||
|
|
||||||
for(unsigned i=0; i<p->audioGroupN; ++i)
|
for(unsigned i=0; i<p->audioGroupN; ++i)
|
||||||
devN += p->audioGroupA[i].iDeviceN + p->audioGroupA[i].oDeviceN;
|
devN += p->audioGroupA[i].iDeviceN + p->audioGroupA[i].oDeviceN;
|
||||||
|
|
||||||
@ -146,23 +151,38 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _send_midi_triple( flow::external_device_t* dev, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1 )
|
||||||
void _setup_device_cfg( flow::external_device_t* d, const char* devLabel, unsigned ioDevId, unsigned typeId, unsigned flags )
|
|
||||||
{
|
{
|
||||||
d->label = devLabel;
|
return midiDeviceSend(((io_flow_t*)dev->reserved)->ioH, dev->ioDevIdx, dev->ioPortIdx, status |= ch, d0, d1);
|
||||||
d->ioDevId = ioDevId;
|
|
||||||
d->typeId = typeId;
|
|
||||||
d->flags = flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _setup_device_cfg( io_flow_t* p, flow::external_device_t* d, const char* devLabel, unsigned ioDevIdx, unsigned typeId, unsigned flags, const char* midiPortLabel=nullptr, unsigned midiPortIdx=kInvalidIdx )
|
||||||
|
{
|
||||||
|
d->reserved = p;
|
||||||
|
d->devLabel = devLabel;
|
||||||
|
d->portLabel = midiPortLabel;
|
||||||
|
d->typeId = typeId;
|
||||||
|
d->flags = flags;
|
||||||
|
d->ioDevIdx = ioDevIdx;
|
||||||
|
d->ioPortIdx = midiPortIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setup_midi_device_cfg( io_flow_t* p, flow::external_device_t* d, const char* devLabel, unsigned ioDevIdx, unsigned flags, unsigned ioMidiPortIdx )
|
||||||
|
{
|
||||||
|
const char* midiPortLabel = io::midiDevicePortName(p->ioH,ioDevIdx, flags & flow::kInFl ? true : false,ioMidiPortIdx);
|
||||||
|
_setup_device_cfg( p, d, devLabel, ioDevIdx, flow::kMidiDevTypeId, flags, midiPortLabel, ioMidiPortIdx );
|
||||||
|
d->u.m.maxMsgCnt = io::midiDeviceMaxBufferMsgCount(p->ioH);
|
||||||
|
d->u.m.sendTripleFunc = _send_midi_triple;
|
||||||
|
}
|
||||||
|
|
||||||
void _setup_audio_device_cfg( io_flow_t* p, flow::external_device_t* d, audio_group_t* ag, audio_dev_t* ad, unsigned flags )
|
void _setup_audio_device_cfg( io_flow_t* p, flow::external_device_t* d, audio_group_t* ag, audio_dev_t* ad, unsigned flags )
|
||||||
{
|
{
|
||||||
_setup_device_cfg( d, io::audioDeviceLabel(p->ioH,ad->ioDevIdx), ad->ioDevId, flow::kAudioDevTypeId, flags );
|
_setup_device_cfg( p, d, io::audioDeviceLabel(p->ioH,ad->ioDevIdx), ad->ioDevIdx, flow::kAudioDevTypeId, flags );
|
||||||
|
|
||||||
// Each audio device is given a flow::abuf to hold incoming or outgoing audio.
|
// Each audio device is given a flow::abuf to hold incoming or outgoing audio.
|
||||||
// This buffer also allows the 'audio_in' and 'audio_out' flow procs to configure themselves.
|
// This buffer also allows the 'audio_in' and 'audio_out' flow procs to configure themselves.
|
||||||
d->u.a.abuf = &ad->abuf;
|
d->u.a.abuf = &ad->abuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setup_generic_device_array( io_flow_t* p )
|
void _setup_generic_device_array( io_flow_t* p )
|
||||||
{
|
{
|
||||||
@ -175,17 +195,27 @@ namespace cw
|
|||||||
|
|
||||||
// get serial devices
|
// get serial devices
|
||||||
for(unsigned di=0; i<p->deviceN && di<serialDeviceCount(p->ioH); ++di,++i)
|
for(unsigned di=0; i<p->deviceN && di<serialDeviceCount(p->ioH); ++di,++i)
|
||||||
_setup_device_cfg( p->deviceA + i, io::serialDeviceLabel(p->ioH,di), io::serialDeviceId(p->ioH,di), flow::kSerialDevTypeId, flow::kInFl | flow::kOutFl );
|
_setup_device_cfg( p, p->deviceA + i, io::serialDeviceLabel(p->ioH,di), di, flow::kSerialDevTypeId, flow::kInFl | flow::kOutFl );
|
||||||
|
|
||||||
// get midi devices
|
|
||||||
//for(unsigned di=0; i<p->deviceN && di<midiDeviceCount(p->ioH); ++di,++i)
|
|
||||||
// _setup_device_cfg( p->deviceA + i, io::midiDeviceLabel(p->ioH,di), di, flow::kMidiDevTypeId, flow::kInFl | flow::kOutFl );
|
|
||||||
|
|
||||||
// get sockets
|
// get sockets
|
||||||
for(unsigned di=0; i<p->deviceN && di<socketCount(p->ioH); ++di,++i)
|
for(unsigned di=0; i<p->deviceN && di<socketCount(p->ioH); ++di,++i)
|
||||||
_setup_device_cfg( p->deviceA + i, io::socketLabel(p->ioH,di), io::socketUserId(p->ioH,di), flow::kSocketDevTypeId, flow::kInFl | flow::kOutFl );
|
_setup_device_cfg( p, p->deviceA + i, io::socketLabel(p->ioH,di), di, flow::kSocketDevTypeId, flow::kInFl | flow::kOutFl );
|
||||||
|
|
||||||
|
|
||||||
|
// get midi devices
|
||||||
|
for(unsigned di=0; i<p->deviceN && di<midiDeviceCount(p->ioH); ++di)
|
||||||
|
{
|
||||||
|
// input port setup
|
||||||
|
for(unsigned pi=0; pi<midiDevicePortCount(p->ioH,di,true); ++pi,++i)
|
||||||
|
_setup_midi_device_cfg( p, p->deviceA + i, io::midiDeviceName(p->ioH,di), di, flow::kInFl, pi);
|
||||||
|
|
||||||
|
// output port setup
|
||||||
|
for(unsigned pi=0; pi<midiDevicePortCount(p->ioH,di,false); ++pi,++i)
|
||||||
|
_setup_midi_device_cfg( p, p->deviceA + i, io::midiDeviceName(p->ioH,di), di, flow::kOutFl, pi);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// get the audio devices
|
// get the audio devices
|
||||||
for(unsigned gi=0; gi<p->audioGroupN; ++gi)
|
for(unsigned gi=0; gi<p->audioGroupN; ++gi)
|
||||||
{
|
{
|
||||||
@ -198,6 +228,9 @@ namespace cw
|
|||||||
_setup_audio_device_cfg( p, p->deviceA + i, ag, ag->oDeviceA + di, flow::kOutFl );
|
_setup_audio_device_cfg( p, p->deviceA + i, ag, ag->oDeviceA + di, flow::kOutFl );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert( i == p->deviceN );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _device_index_to_abuf( io_flow_t* p, unsigned ioGroupIdx, unsigned ioDevIdx, unsigned inOrOutFl, flow::abuf_t*& abuf_ref )
|
rc_t _device_index_to_abuf( io_flow_t* p, unsigned ioGroupIdx, unsigned ioDevIdx, unsigned inOrOutFl, flow::abuf_t*& abuf_ref )
|
||||||
@ -254,6 +287,18 @@ namespace cw
|
|||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
flow::abuf_t* abuf = nullptr;
|
flow::abuf_t* abuf = nullptr;
|
||||||
|
|
||||||
|
// Get an array of incoming MIDI events which have occurred since the last call to 'io::midiDeviceBuffer()'
|
||||||
|
unsigned midiBufMsgCnt = 0;
|
||||||
|
const midi::ch_msg_t* midiBuf = midiDeviceBuffer(p->ioH,midiBufMsgCnt);
|
||||||
|
|
||||||
|
// Give each MIDI input device a pointer to the incoming MIDI msgs
|
||||||
|
for(unsigned i=0; i<p->deviceN; ++i)
|
||||||
|
if( p->deviceA[i].typeId == flow::kMidiDevTypeId && cwIsFlag(p->deviceA[i].flags,flow::kInFl) )
|
||||||
|
{
|
||||||
|
p->deviceA[i].u.m.msgArray = midiBuf;
|
||||||
|
p->deviceA[i].u.m.msgCnt = midiBufMsgCnt;
|
||||||
|
}
|
||||||
|
|
||||||
// if there is incoming (recorded) audio
|
// if there is incoming (recorded) audio
|
||||||
if( m.iBufChCnt > 0 )
|
if( m.iBufChCnt > 0 )
|
||||||
{
|
{
|
||||||
@ -318,6 +363,9 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
|
// Drop the MIDI messages that were processed on this call.
|
||||||
|
midiDeviceClearBuffer(p->ioH,midiBufMsgCnt);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user