cwFlowProc.cpp : 'midi_out' now has both a 'midi' and a 'record' input variable.

Added 'print_fl' to 'midi_voice' and 'midi_out'
Added 'preset_sfx_id' and 'preset_label' variables to implement _apply_preset() in 'poly'.
This commit is contained in:
kevin 2024-12-23 16:26:08 -05:00
parent db3e96cdf6
commit 1bde870d3a

View File

@ -129,7 +129,7 @@ namespace cw
goto errLabel; goto errLabel;
} }
if((rc = network_create(proc->ctx,&networkCfg,1,proc->varL,1,nullptr,p->net)) != kOkRC ) if((rc = network_create(proc->ctx,&networkCfg,1,proc->varL,proc,1,p->net)) != kOkRC )
{ {
rc = cwLogError(rc,"Creation failed on the subnet internal network."); rc = cwLogError(rc,"Creation failed on the subnet internal network.");
goto errLabel; goto errLabel;
@ -192,6 +192,8 @@ namespace cw
{ {
kParallelFlPId, kParallelFlPId,
kCountPId, kCountPId,
kPresetSfxIdPId,
kPresetLabelPId
}; };
typedef struct voice_str typedef struct voice_str
@ -201,14 +203,13 @@ namespace cw
} voice_t; } voice_t;
typedef struct typedef struct
{ {
unsigned count; // count of subnets in 'net' unsigned count; // count of subnets in 'net'
//network_t* net; // internal network containing 'count' duplicate sub-nets
bool parallel_fl; // true if the subnets should be executed in parallel bool parallel_fl; // true if the subnets should be executed in parallel
thread_tasks::handle_t threadTasksH; // thread_tasks::handle_t threadTasksH; //
thread_tasks::task_t* taskA; // taskA[ count ] thread_tasks::task_t* taskA; // taskA[ count ]
voice_t* voiceA; // voiceA[ count ] voice_t* voiceA; // voiceA[ count ]
unsigned preset_sfx_id;
} inst_t; } inst_t;
rc_t _poly_thread_func( void* arg ) rc_t _poly_thread_func( void* arg )
@ -226,6 +227,31 @@ namespace cw
return rc; return rc;
} }
rc_t _apply_preset(proc_t* proc,unsigned preset_sfx_id,const char* preset_label)
{
rc_t rc = kOkRC;
network_t* net = proc->internal_net;
for(; net!=nullptr; net=net->poly_link)
if( net->poly_idx == preset_sfx_id )
break;
if( net == nullptr )
{
rc = cwLogError(kEleNotFoundRC,"The preset application poly voice '%i' was not found.",preset_sfx_id);
goto errLabel;
}
if((rc = network_apply_preset(*net,preset_label,preset_sfx_id)) != kOkRC )
{
goto errLabel;
}
errLabel:
return rc;
}
rc_t create( proc_t* proc ) rc_t create( proc_t* proc )
{ {
@ -236,6 +262,8 @@ namespace cw
const object_t** networkCfgA = nullptr; const object_t** networkCfgA = nullptr;
unsigned networkCfgN = 1; unsigned networkCfgN = 1;
network_t* internal_net = nullptr; network_t* internal_net = nullptr;
unsigned preset_sfx_id = kInvalidId;
const char* preset_label = nullptr;
proc->userPtr = inst; proc->userPtr = inst;
@ -247,7 +275,10 @@ namespace cw
} }
// get the 'parallel flag' // get the 'parallel flag'
if((rc = var_register_and_get( proc, kAnyChIdx,kParallelFlPId, "parallel_fl", kBaseSfxId, inst->parallel_fl )) != kOkRC ) if((rc = var_register_and_get( proc, kAnyChIdx,
kPresetSfxIdPId,"preset_sfx_id", kBaseSfxId, preset_sfx_id,
kPresetLabelPId,"preset_label", kBaseSfxId, preset_label,
kParallelFlPId, "parallel_fl", kBaseSfxId, inst->parallel_fl )) != kOkRC )
{ {
goto errLabel; goto errLabel;
} }
@ -299,12 +330,18 @@ namespace cw
// create the network object - which will hold 'count' subnets - each a duplicate of the // create the network object - which will hold 'count' subnets - each a duplicate of the
// network described by 'networkCfg'. // network described by 'networkCfg'.
if((rc = network_create(proc->ctx,networkCfgA,networkCfgN,proxyVarL,inst->count,nullptr,internal_net)) != kOkRC ) if((rc = network_create(proc->ctx,networkCfgA,networkCfgN,proxyVarL,proc,inst->count,internal_net)) != kOkRC )
{ {
rc = cwLogError(rc,"Creation failed on the internal network."); rc = cwLogError(rc,"Creation failed on the internal network.");
goto errLabel; goto errLabel;
} }
if( preset_sfx_id != kInvalidId && textLength(preset_label) > 0 )
{
if((rc = _apply_preset(proc,preset_sfx_id,preset_label)) != kOkRC )
goto errLabel;
}
if( inst->parallel_fl ) if( inst->parallel_fl )
{ {
network_t* net = internal_net; network_t* net = internal_net;
@ -369,6 +406,28 @@ namespace cw
{ {
inst_t* p = (inst_t*)proc->userPtr; inst_t* p = (inst_t*)proc->userPtr;
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned preset_sfx_id = kInvalidId;
if((rc = var_get(proc,kPresetSfxIdPId,kAnyChIdx,preset_sfx_id)) != kOkRC )
goto errLabel;
// if a new preset value has arrived
if( preset_sfx_id != kInvalidId && preset_sfx_id != p->preset_sfx_id )
{
const char* preset_label;
p->preset_sfx_id = preset_sfx_id;
// get the preset label
if((rc = var_get(proc,kPresetLabelPId,kAnyChIdx,preset_label)) != kOkRC )
goto errLabel;
// and apply the preset
if( textLength(preset_label) > 0 )
if((rc = _apply_preset(proc,preset_sfx_id,preset_label)) != kOkRC )
goto errLabel;
}
if( p->parallel_fl ) if( p->parallel_fl )
{ {
@ -389,6 +448,7 @@ namespace cw
} }
} }
errLabel:
return rc; return rc;
} }
@ -643,52 +703,88 @@ namespace cw
kPortLabelPId, kPortLabelPId,
kBufMsgCntPId, kBufMsgCntPId,
kInPId, kInPId,
kRInPId,
kPrintFlPId
}; };
typedef struct typedef struct
{ {
external_device_t* ext_dev; external_device_t* ext_dev;
bool rin_exists_fl;
unsigned inVarN; bool in_exists_fl;
unsigned msgN; unsigned msgN;
midi::ch_msg_t* msgA; midi::ch_msg_t* msgA;
unsigned msg_idx; unsigned msg_idx;
unsigned midi_fld_idx;
recd_type_t null_recd_type{ .fieldL=nullptr, .fieldN=0, .base=nullptr };
} inst_t; } inst_t;
rc_t _create( proc_t* proc, inst_t* p ) rc_t _create( proc_t* proc, inst_t* p )
{ {
rc_t rc = kOkRC; // rc_t rc = kOkRC; //h
const char* dev_label = nullptr; const char* dev_label = nullptr;
const char* port_label = nullptr; const char* port_label = nullptr;
unsigned inVarN = var_mult_count(proc,"in"); rbuf_t* rbuf = nullptr;
mbuf_t* mbuf = nullptr; bool printFl = false;
unsigned sfxIdA[ inVarN ];
// get the the sfx_id's of the input audio variables
if((rc = var_mult_sfx_id_array(proc, "in", sfxIdA, inVarN, p->inVarN )) != kOkRC )
goto errLabel;
std::sort(sfxIdA, sfxIdA + p->inVarN, [](unsigned& a,unsigned& b){ return a<b; } );
// Register variables and get their current value // Register variables and get their current value
if((rc = var_register_and_get( proc, kAnyChIdx, if((rc = var_register_and_get( proc, kAnyChIdx,
kDevLabelPId, "dev_label", kBaseSfxId, dev_label, kDevLabelPId, "dev_label", kBaseSfxId, dev_label,
kPortLabelPId,"port_label", kBaseSfxId, port_label, kPortLabelPId,"port_label", kBaseSfxId, port_label,
kInPId, "in", kBaseSfxId, mbuf, kPrintFlPId, "print_fl", kBaseSfxId, printFl,
kBufMsgCntPId,"buf_cnt", kBaseSfxId, p->msgN )) != kOkRC ) kBufMsgCntPId,"buf_cnt", kBaseSfxId, p->msgN )) != kOkRC )
{ {
goto errLabel; goto errLabel;
} }
// if the MIDI 'in' variable has a value then it exists and is connected ...
if((p->in_exists_fl = var_has_value(proc, "in", kBaseSfxId, kAnyChIdx )) == true )
{
// ... register it
if((rc = var_register( proc, kAnyChIdx,kInPId, "in", kBaseSfxId )) != kOkRC )
goto errLabel;
}
else
{
// ... otherwise setup it up with an empty mbuf to get it by the post proc create variable value checker
if((rc = var_register_and_set( proc, "in", kBaseSfxId, kInPId, kAnyChIdx, nullptr, 0 )) != kOkRC )
goto errLabel;
}
// if the 'record' input variable has a value then it exists and is connected ...
if((p->rin_exists_fl = var_has_value(proc, "rin", kBaseSfxId, kAnyChIdx )) == true )
{
// ... register it and get a pointer to the incoming record buffer to use below
if((rc = var_register_and_get( proc, kAnyChIdx,kRInPId, "rin", kBaseSfxId, rbuf )) != kOkRC )
goto errLabel;
}
else
{
// ... otherwise give it an empty record buf to get by the post proc create variable value checker
if((rc = var_register_and_set( proc, "rin", kBaseSfxId, kRInPId, kAnyChIdx, &p->null_recd_type, nullptr, 0 )) != kOkRC )
goto errLabel;
}
if((p->ext_dev = external_device_find( proc->ctx, dev_label, kMidiDevTypeId, kOutFl, port_label )) == nullptr ) if((p->ext_dev = external_device_find( proc->ctx, dev_label, kMidiDevTypeId, kOutFl, port_label )) == nullptr )
{ {
rc = cwLogError(kOpFailRC,"The audio output device description '%s' could not be found.", cwStringNullGuard(dev_label)); rc = cwLogError(kOpFailRC,"The audio output device description '%s' could not be found.", cwStringNullGuard(dev_label));
goto errLabel; goto errLabel;
} }
if( rbuf == nullptr )
p->midi_fld_idx = kInvalidIdx;
else
{
if((p->midi_fld_idx = recd_type_field_index( rbuf->type, "midi")) == kInvalidIdx )
{
rc = cwLogError(kInvalidArgRC,"The 'rin' record does not have a 'midi' field.");
goto errLabel;
}
}
p->msgA = mem::allocZ<midi::ch_msg_t>(p->msgN); p->msgA = mem::allocZ<midi::ch_msg_t>(p->msgN);
errLabel: errLabel:
@ -705,23 +801,63 @@ namespace cw
{ {
return kOkRC; return kOkRC;
} }
void _send_msg( inst_t* p, bool print_fl, const midi::ch_msg_t* m )
{
p->ext_dev->u.m.sendTripleFunc( p->ext_dev, m->ch, m->status, m->d0, m->d1 );
if( print_fl )
{
cwLogPrint("%2i 0x%2x %3i %3i : %s %s\n",m->ch, m->status, m->d0, m->d1, cwStringNullGuard(p->ext_dev->devLabel),cwStringNullGuard(p->ext_dev->portLabel));
}
}
rc_t _exec( proc_t* proc, inst_t* p ) rc_t _exec( proc_t* proc, inst_t* p )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
const rbuf_t* rbuf = nullptr;
bool print_fl = false;
const mbuf_t* src_mbuf = nullptr; const mbuf_t* src_mbuf = nullptr;
if((rc = var_get(proc,kInPId,kAnyChIdx,src_mbuf)) != kOkRC ) var_get(proc,kPrintFlPId,kAnyChIdx,print_fl);
rc = cwLogError(kInvalidStateRC,"The MIDI output instance '%s' does not have a valid input connection.",proc->label);
else if( p->rin_exists_fl )
{ {
for(unsigned i=0; i<src_mbuf->msgN; ++i) if((rc = var_get(proc,kRInPId,kAnyChIdx,rbuf)) != kOkRC )
{ rc = cwLogError(kInvalidStateRC,"The the record input connection is not valid.");
const midi::ch_msg_t* m = src_mbuf->msgA + i; else
p->ext_dev->u.m.sendTripleFunc( p->ext_dev, m->ch, m->status, m->d0, m->d1 ); {
for(unsigned i=0; i<rbuf->recdN; ++i)
{
const recd_t* r = rbuf->recdA + i;
const midi::ch_msg_t* m = nullptr;
if((rc = recd_get(rbuf->type,r,p->midi_fld_idx,m)) == kOkRC )
_send_msg(p,print_fl,m);
else
{
rc = cwLogError(rc,"Record 'midi' field read failed.");
goto errLabel;
}
}
}
}
if( p->in_exists_fl )
{
if((rc = var_get(proc,kInPId,kAnyChIdx,src_mbuf)) != kOkRC )
rc = cwLogError(kInvalidStateRC,"The MIDI output instance '%s' does not have a valid input connection.",proc->label);
else
{
for(unsigned i=0; i<src_mbuf->msgN; ++i)
{
_send_msg(p,print_fl,src_mbuf->msgA + i);
}
} }
} }
errLabel:
return rc; return rc;
} }
@ -4190,7 +4326,8 @@ namespace cw
if( p->voiceA[i].age > p->voiceA[ max_age_idx].age ) if( p->voiceA[i].age > p->voiceA[ max_age_idx].age )
max_age_idx = i; max_age_idx = i;
} }
cwLogWarning("Stealing:%i",p->voiceA[max_age_idx].pitch );
return max_age_idx; return max_age_idx;
} }
@ -4414,6 +4551,7 @@ namespace cw
kGainPId, kGainPId,
kChCntPId, kChCntPId,
kOutPId, kOutPId,
kPrintFlPId,
kDoneFlPId kDoneFlPId
}; };
@ -4455,12 +4593,14 @@ namespace cw
mbuf_t* mbuf = nullptr; mbuf_t* mbuf = nullptr;
srate_t srate = proc->ctx->sample_rate; srate_t srate = proc->ctx->sample_rate;
bool done_fl = false; bool done_fl = false;
bool print_fl= false;
// get the MIDI input variable // get the MIDI input variable
if((rc = var_register_and_get( proc, kAnyChIdx, if((rc = var_register_and_get( proc, kAnyChIdx,
kInPId, "in", kBaseSfxId, mbuf, kInPId, "in", kBaseSfxId, mbuf,
kGainPId, "gain", kBaseSfxId, p->fixed_gain, kGainPId, "gain", kBaseSfxId, p->fixed_gain,
kChCntPId, "chCnt", kBaseSfxId, p->chN, kChCntPId, "chCnt", kBaseSfxId, p->chN,
kPrintFlPId,"print_fl",kBaseSfxId, print_fl,
kDoneFlPId, "done_fl", kBaseSfxId, done_fl)) != kOkRC ) kDoneFlPId, "done_fl", kBaseSfxId, done_fl)) != kOkRC )
goto errLabel; goto errLabel;
@ -4528,6 +4668,7 @@ namespace cw
rc_t rc = kOkRC; rc_t rc = kOkRC;
abuf_t* abuf = nullptr; abuf_t* abuf = nullptr;
mbuf_t* mbuf = nullptr; mbuf_t* mbuf = nullptr;
bool print_fl = false;
// get the input MIDI buffer // get the input MIDI buffer
if((rc = var_get(proc,kInPId,kAnyChIdx,mbuf)) != kOkRC ) if((rc = var_get(proc,kInPId,kAnyChIdx,mbuf)) != kOkRC )
@ -4537,10 +4678,16 @@ namespace cw
if((rc = var_get(proc,kOutPId,kAnyChIdx,abuf)) != kOkRC ) if((rc = var_get(proc,kOutPId,kAnyChIdx,abuf)) != kOkRC )
goto errLabel; goto errLabel;
var_get(proc,kPrintFlPId,kAnyChIdx,print_fl);
// if there are MIDI messages - update cur_hz and cur_vel // if there are MIDI messages - update cur_hz and cur_vel
for(unsigned i=0; i<mbuf->msgN; ++i) for(unsigned i=0; i<mbuf->msgN; ++i)
{ {
const midi::ch_msg_t* m = mbuf->msgA + i; const midi::ch_msg_t* m = mbuf->msgA + i;
if( print_fl )
cwLogPrint("%2i 0x%2x %3i %3i : %s:%i\n",m->ch, m->status, m->d0, m->d1, cwStringNullGuard(proc->label),proc->label_sfx_id);
switch( m->status ) switch( m->status )
{ {
case midi::kNoteOnMdId: case midi::kNoteOnMdId: