Multi-preset configurations flags 'kPriPresetProbFl,kSecPresetProbFl,kPresetInterpFl`
can now be used to configure preset application from the cwIoPresetSelApp UI.
This commit is contained in:
parent
64df75d9aa
commit
14a6a9b2d1
244
cwFlow.cpp
244
cwFlow.cpp
@ -1305,6 +1305,88 @@ namespace cw
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned _select_ranked_ele_by_rank_prob( const preset_order_t* presetA, const bool* selV , unsigned presetN )
|
||||
{
|
||||
|
||||
// get a count of the candidate presets
|
||||
unsigned rankN = selV==nullptr ? presetN : std::count_if(selV,selV+presetN,[](const bool& x){ return x; });
|
||||
|
||||
if( rankN == 0 )
|
||||
{
|
||||
cwLogWarning("All preset candidates have been eliminated.");
|
||||
return kInvalidIdx;
|
||||
}
|
||||
|
||||
unsigned rankV[ rankN ];
|
||||
unsigned idxMapA[ rankN ];
|
||||
|
||||
// fill rankV[] with candidates 'order' value
|
||||
for(unsigned i=0,j=0; i<presetN; ++i)
|
||||
if( selV==nullptr || selV[i] )
|
||||
{
|
||||
assert( j < rankN );
|
||||
rankV[j] = presetA[i].order;
|
||||
idxMapA[j] = i;
|
||||
++j;
|
||||
}
|
||||
|
||||
// if only one element remains to be selected
|
||||
if( rankN == 1 )
|
||||
return idxMapA[0];
|
||||
|
||||
assert( rankN > 1 );
|
||||
|
||||
unsigned threshV[ rankN ];
|
||||
unsigned uniqueRankV[ rankN ];
|
||||
unsigned uniqueRankN = 0;
|
||||
unsigned sel_idx = rankN - 1; //
|
||||
|
||||
// for each possible rank value
|
||||
for(unsigned i=0; i<rankN; ++i)
|
||||
{
|
||||
// locate the rank in the uniqueRankV[]
|
||||
unsigned j=0;
|
||||
for(; j<uniqueRankN; ++j)
|
||||
if( uniqueRankV[j]==rankV[i] )
|
||||
break;
|
||||
|
||||
// if the rank was not found then include it here
|
||||
if( j == uniqueRankN )
|
||||
uniqueRankV[uniqueRankN++] = rankV[i];
|
||||
|
||||
}
|
||||
|
||||
// uniqueRankV[] now includes the set of possible rank values
|
||||
|
||||
// Take the product of all possible values.
|
||||
// (this will be evenly divisible by all values)
|
||||
unsigned prod = vop::prod(uniqueRankV,uniqueRankN);
|
||||
|
||||
unsigned thresh = 0;
|
||||
for(unsigned i=0; i<rankN; ++i)
|
||||
threshV[i] = (thresh += rankV[i] * prod);
|
||||
|
||||
// Thresh is now set to the max possible random value.
|
||||
|
||||
// Generate a random number between 0 and thresh
|
||||
double fval = (double)std::rand() * thresh / RAND_MAX;
|
||||
|
||||
unsigned thresh0 = 0;
|
||||
for(unsigned i=0; i<rankN; ++i)
|
||||
{
|
||||
if( thresh0 <= fval && fval < threshV[i] )
|
||||
{
|
||||
sel_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert( sel_idx < rankN );
|
||||
|
||||
return idxMapA[sel_idx];
|
||||
}
|
||||
|
||||
/*
|
||||
unsigned _select_ranked_ele_by_rank_prob( const preset_order_t* rankV, unsigned rankN )
|
||||
{
|
||||
unsigned threshV[ rankN ];
|
||||
@ -1335,7 +1417,7 @@ namespace cw
|
||||
|
||||
// uniqueRankV[] now includes the set of possible rank values
|
||||
|
||||
// Take the produce of all possible values.
|
||||
// Take the product of all possible values.
|
||||
// (this will be evenly divisible by all values)
|
||||
unsigned prod = vop::prod(uniqueRankV,uniqueRankN);
|
||||
|
||||
@ -1360,6 +1442,22 @@ namespace cw
|
||||
|
||||
return sel_idx;
|
||||
}
|
||||
*/
|
||||
|
||||
const char* _select_ranked_ele_label_by_rank_prob( const preset_order_t* rankV, const bool* selA, unsigned rankN )
|
||||
{
|
||||
unsigned sel_idx;
|
||||
|
||||
if((sel_idx = _select_ranked_ele_by_rank_prob( rankV, selA, rankN )) == kInvalidIdx )
|
||||
{
|
||||
cwLogWarning("The multi-preset select function failed. Selecting preset 0.");
|
||||
sel_idx = 0;
|
||||
}
|
||||
|
||||
return rankV[sel_idx].preset_label;
|
||||
|
||||
}
|
||||
|
||||
|
||||
double _calc_multi_preset_dual_coeff( const multi_preset_selector_t& mps )
|
||||
{
|
||||
@ -1486,7 +1584,8 @@ cw::rc_t cw::flow::create( handle_t& hRef,
|
||||
|
||||
// parse the main audio file processor cfg record
|
||||
if((rc = networkCfg.getv("framesPerCycle", p->framesPerCycle,
|
||||
"multiPresetProbFl", p->multiPresetProbFl,
|
||||
"multiPriPresetProbFl", p->multiPriPresetProbFl,
|
||||
"multiSecPresetProbFl", p->multiSecPresetProbFl,
|
||||
"multiPresetInterpFl", p->multiPresetInterpFl,
|
||||
"network", network)) != kOkRC )
|
||||
{
|
||||
@ -1553,6 +1652,23 @@ cw::rc_t cw::flow::destroy( handle_t& hRef )
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned cw::flow::preset_cfg_flags( handle_t h )
|
||||
{
|
||||
flow_t* p = _handleToPtr(h);
|
||||
unsigned flags = 0;
|
||||
|
||||
if( p->multiPriPresetProbFl )
|
||||
flags |= kPriPresetProbFl;
|
||||
|
||||
if( p->multiSecPresetProbFl )
|
||||
flags |= kSecPresetProbFl;
|
||||
|
||||
if( p->multiPresetInterpFl )
|
||||
flags |= kInterpPresetFl;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::flow::exec_cycle( handle_t h )
|
||||
{
|
||||
@ -1657,7 +1773,7 @@ cw::rc_t cw::flow::apply_dual_preset( handle_t h, const char* presetLabel_0, con
|
||||
flow_t* p = _handleToPtr(h);
|
||||
const object_t* net_preset_value_0;
|
||||
|
||||
printf("*** Applying dual: %s %s : %f\n",presetLabel_0, presetLabel_1, coeff );
|
||||
cwLogInfo("*** Applying dual: %s %s : %f\n",presetLabel_0, presetLabel_1, coeff );
|
||||
|
||||
// locate the cfg of the requested preset
|
||||
if((net_preset_value_0 = _find_network_preset(p, presetLabel_0 )) == nullptr )
|
||||
@ -1746,14 +1862,122 @@ cw::rc_t cw::flow::apply_dual_preset( handle_t h, const char* presetLabel_0, con
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& mps )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const char* label0 = nullptr;
|
||||
const char* label1 = nullptr;
|
||||
bool priProbFl = cwIsFlag(mps.flags, kPriPresetProbFl );
|
||||
bool secProbFl = cwIsFlag(mps.flags, kSecPresetProbFl );
|
||||
bool interpFl = cwIsFlag(mps.flags, kInterpPresetFl );
|
||||
|
||||
printf("preset flags: pri:%i sec:%i interp:%i\n",priProbFl,secProbFl,interpFl);
|
||||
|
||||
// verify that the set of candidate presets is not empty
|
||||
if( mps.presetN == 0 )
|
||||
{
|
||||
cwLogError(kInvalidArgRC,"A multi-preset application was requested but no presets were provided.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// if only a single candidate preset exists or needs to be selected
|
||||
if( interpFl==false || mps.presetN==1 )
|
||||
{
|
||||
// if only a single candidate preset is available or pri. probablity is not enabled
|
||||
if( mps.presetN == 1 || priProbFl==false )
|
||||
label0 = mps.presetA[0].preset_label;
|
||||
else
|
||||
{
|
||||
if( priProbFl )
|
||||
label0 = _select_ranked_ele_label_by_rank_prob( mps.presetA, nullptr, mps.presetN );
|
||||
else
|
||||
label0 = mps.presetA[0].preset_label;
|
||||
}
|
||||
}
|
||||
else // interpolation has been selected and at least 2 presets exist
|
||||
{
|
||||
unsigned pri_sel_idx = 0;
|
||||
|
||||
// select the primary preset
|
||||
if( priProbFl )
|
||||
pri_sel_idx = _select_ranked_ele_by_rank_prob( mps.presetA, nullptr, mps.presetN );
|
||||
else
|
||||
{
|
||||
// select all presets assigned to order == 1
|
||||
bool selA[ mps.presetN ];
|
||||
for(unsigned i=0; i<mps.presetN; ++i)
|
||||
selA[i]= mps.presetA[i].order==1;
|
||||
|
||||
// select the preset among all presets marked as 1
|
||||
pri_sel_idx = _select_ranked_ele_by_rank_prob( mps.presetA, selA, mps.presetN );
|
||||
}
|
||||
|
||||
if( pri_sel_idx == kInvalidIdx )
|
||||
pri_sel_idx = 0;
|
||||
|
||||
// the primary preset has now been selected
|
||||
|
||||
// if there is only one candidate secondary preset
|
||||
if( mps.presetN == 2)
|
||||
{
|
||||
assert( pri_sel_idx <= 1 );
|
||||
label1 = mps.presetA[ pri_sel_idx == 0 ? 1 : 0 ].preset_label;
|
||||
}
|
||||
else // at least two remaining presets exist to select between
|
||||
{
|
||||
// mark the selected primary preset as not-available
|
||||
bool selA[ mps.presetN ];
|
||||
vop::fill(selA,mps.presetN,true);
|
||||
selA[pri_sel_idx] = false;
|
||||
|
||||
// if the second preset should be selected probabilistically
|
||||
if( secProbFl )
|
||||
label1 = _select_ranked_ele_label_by_rank_prob( mps.presetA, selA, mps.presetN );
|
||||
else
|
||||
{
|
||||
// select the best preset that is not the primary preset
|
||||
for(unsigned i=0; i<mps.presetN; ++i)
|
||||
if( i != pri_sel_idx )
|
||||
{
|
||||
label1 = mps.presetA[i].preset_label;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
assert( pri_sel_idx != kInvalidIdx );
|
||||
label0 = mps.presetA[ pri_sel_idx ].preset_label;
|
||||
}
|
||||
|
||||
assert(label0 != nullptr );
|
||||
|
||||
if( label1 == nullptr )
|
||||
{
|
||||
rc = apply_preset( h, label0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
double coeff = _calc_multi_preset_dual_coeff(mps);
|
||||
rc = apply_dual_preset( h, label0, label1, coeff );
|
||||
}
|
||||
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& multi_preset_sel )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const char* label0 = nullptr;
|
||||
const char* label1 = nullptr;
|
||||
const char* prob_label = nullptr;
|
||||
|
||||
flow_t* p = _handleToPtr(h);
|
||||
bool multiPriPresetProbFl = cwIsFlag(multi_preset_sel.flags, kPriPresetProbFl );
|
||||
bool multiSecPresetProbFl = cwIsFlag(multi_preset_sel.flags, kSecPresetProbFl );
|
||||
bool multiPresetInterpFl = cwIsFlag(multi_preset_sel.flags, kInterpPresetFl );
|
||||
|
||||
// verify that the set of presets to select from is not empty
|
||||
if( multi_preset_sel.presetN == 0 )
|
||||
@ -1763,14 +1987,14 @@ cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& mult
|
||||
}
|
||||
|
||||
// if probabistic selection was requested and is possible
|
||||
if( p->multiPresetProbFl && multi_preset_sel.presetN > 1 )
|
||||
if( multiPresetProbFl && multi_preset_sel.presetN > 1 )
|
||||
{
|
||||
auto presetA = multi_preset_sel.presetA;
|
||||
auto presetN = multi_preset_sel.presetN;
|
||||
|
||||
// if we are interpolating then the base preset is always the first one in presetA[]
|
||||
// so do not include it as a candidate for probabilistic selection
|
||||
if( p->multiPresetInterpFl )
|
||||
if( multiPresetInterpFl )
|
||||
{
|
||||
presetA += 1;
|
||||
presetN -= 1;
|
||||
@ -1820,12 +2044,12 @@ cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& mult
|
||||
if( prob_label == nullptr )
|
||||
{
|
||||
label0 = multi_preset_sel.presetA[0].preset_label;
|
||||
label1 = p->multiPresetInterpFl ? multi_preset_sel.presetA[1].preset_label : nullptr;
|
||||
label1 = multiPresetInterpFl ? multi_preset_sel.presetA[1].preset_label : nullptr;
|
||||
}
|
||||
else // ... and a prob. selection exists
|
||||
{
|
||||
// if we need two presets
|
||||
if( p->multiPresetInterpFl )
|
||||
if( multiPresetInterpFl )
|
||||
{
|
||||
label0 = multi_preset_sel.presetA[0].preset_label;
|
||||
label1 = prob_label;
|
||||
@ -1857,7 +2081,7 @@ cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& mult
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, bool value )
|
||||
{ return _set_variable_value( _handleToPtr(h), inst_label, var_label, chIdx, value ); }
|
||||
|
1
cwFlow.h
1
cwFlow.h
@ -59,6 +59,7 @@ namespace cw
|
||||
|
||||
rc_t destroy( handle_t& hRef );
|
||||
|
||||
unsigned preset_cfg_flags( handle_t h );
|
||||
|
||||
// Run one cycle of the network.
|
||||
rc_t exec_cycle( handle_t h );
|
||||
|
@ -356,6 +356,15 @@ cw::rc_t cw::flow_cross::destroy( handle_t& hRef )
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned cw::flow_cross::preset_cfg_flags( handle_t h )
|
||||
{
|
||||
flow_cross_t* p = _handleToPtr(h);
|
||||
if( p->netN > 0 )
|
||||
return preset_cfg_flags( p->netA[0].flowH );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::flow_cross::exec_cycle( handle_t h )
|
||||
{
|
||||
|
@ -25,6 +25,8 @@ namespace cw
|
||||
|
||||
rc_t destroy( handle_t& hRef );
|
||||
|
||||
unsigned preset_cfg_flags( handle_t h );
|
||||
|
||||
// Run one cycle of the network.
|
||||
rc_t exec_cycle( handle_t h );
|
||||
|
||||
|
@ -5,6 +5,12 @@ namespace cw
|
||||
{
|
||||
namespace flow
|
||||
{
|
||||
enum {
|
||||
kPriPresetProbFl = 0x01,
|
||||
kSecPresetProbFl = 0x02,
|
||||
kInterpPresetFl = 0x04
|
||||
};
|
||||
|
||||
typedef struct preset_order_str
|
||||
{
|
||||
const char* preset_label;
|
||||
@ -13,7 +19,7 @@ namespace cw
|
||||
|
||||
typedef struct multi_preset_selector_str
|
||||
{
|
||||
unsigned type_id;
|
||||
unsigned flags;
|
||||
const double* coeffV;
|
||||
const double* coeffMinV;
|
||||
const double* coeffMaxV;
|
||||
|
@ -211,7 +211,8 @@ namespace cw
|
||||
const object_t* presetCfg; // presets designed for this network
|
||||
|
||||
unsigned framesPerCycle; // sample frames per cycle (64)
|
||||
bool multiPresetProbFl; // If set then probability is used to choose presets on multi-preset application
|
||||
bool multiPriPresetProbFl; // If set then probability is used to choose presets on multi-preset application
|
||||
bool multiSecPresetProbFl; //
|
||||
bool multiPresetInterpFl; // If set then interpolation is applied between two selectedd presets on multi-preset application
|
||||
unsigned cycleIndex; // Incremented with each processing cycle
|
||||
unsigned maxCycleCount; // count of cycles to run on flow::exec() or 0 if there is no limit.
|
||||
|
@ -388,6 +388,12 @@ cw::rc_t cw::io_flow::destroy( handle_t& hRef )
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned cw::io_flow::preset_cfg_flags( handle_t h )
|
||||
{
|
||||
io_flow_t* p = _handleToPtr(h);
|
||||
return preset_cfg_flags(p->crossFlowH);
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::io_flow::exec( handle_t h, const io::msg_t& msg )
|
||||
{
|
||||
|
@ -10,6 +10,8 @@ namespace cw
|
||||
rc_t create( handle_t& hRef, io::handle_t ioH, double srate, unsigned crossFadeCnt, const object_t& flow_class_dict, const object_t& cfg );
|
||||
rc_t destroy( handle_t& hRef );
|
||||
|
||||
unsigned preset_cfg_flags( handle_t h );
|
||||
|
||||
rc_t exec( handle_t h, const io::msg_t& msg );
|
||||
|
||||
|
||||
|
@ -51,6 +51,7 @@ namespace cw
|
||||
kReportBtnId,
|
||||
kLatencyBtnId,
|
||||
|
||||
|
||||
kStartBtnId,
|
||||
kStopBtnId,
|
||||
kLiveCheckId,
|
||||
@ -77,6 +78,11 @@ namespace cw
|
||||
kPerfSelId,
|
||||
kAltSelId,
|
||||
|
||||
kPriPresetProbCheckId,
|
||||
kSecPresetProbCheckId,
|
||||
kPresetInterpCheckId,
|
||||
|
||||
|
||||
kEnaRecordCheckId,
|
||||
kMidiSaveBtnId,
|
||||
kMidiLoadBtnId,
|
||||
@ -176,6 +182,9 @@ namespace cw
|
||||
{ kPanelDivId, kLoadBtnId, "loadBtnId" },
|
||||
{ kPanelDivId, kPerfSelId, "perfSelId" },
|
||||
{ kPanelDivId, kAltSelId, "altSelId" },
|
||||
{ kPanelDivId, kPriPresetProbCheckId, "presetProbPriCheckId" },
|
||||
{ kPanelDivId, kSecPresetProbCheckId, "presetProbSecCheckId" },
|
||||
{ kPanelDivId, kPresetInterpCheckId, "presetInterpCheckId" },
|
||||
|
||||
{ kPanelDivId, kEnaRecordCheckId, "enaRecordCheckId" },
|
||||
{ kPanelDivId, kMidiSaveBtnId, "midiSaveBtnId" },
|
||||
@ -322,6 +331,8 @@ namespace cw
|
||||
|
||||
bool printMidiFl;
|
||||
|
||||
unsigned multiPresetFlags;
|
||||
|
||||
bool seqActiveFl; // true if the sequence is currently active (set by 'Play Seq' btn)
|
||||
unsigned seqStartedFl; // set by the first seq idle callback
|
||||
unsigned seqFragId; //
|
||||
@ -899,7 +910,7 @@ namespace cw
|
||||
//unsigned coeffN = sizeof(coeffV)/sizeof(coeffV[0]);
|
||||
|
||||
flow::multi_preset_selector_t mp_sel =
|
||||
{ .type_id=0,
|
||||
{ .flags = app->multiPresetFlags,
|
||||
.coeffV = score_evt->featV,
|
||||
.coeffMinV = score_evt->featMinV,
|
||||
.coeffMaxV = score_evt->featMaxV,
|
||||
@ -3002,6 +3013,18 @@ namespace cw
|
||||
_on_alt_select(app,m.value->u.u);
|
||||
break;
|
||||
|
||||
case kPriPresetProbCheckId:
|
||||
app->multiPresetFlags = cwEnaFlag(app->multiPresetFlags,flow::kPriPresetProbFl,m.value->u.b);
|
||||
break;
|
||||
|
||||
case kSecPresetProbCheckId:
|
||||
app->multiPresetFlags = cwEnaFlag(app->multiPresetFlags,flow::kSecPresetProbFl,m.value->u.b);
|
||||
break;
|
||||
|
||||
case kPresetInterpCheckId:
|
||||
app->multiPresetFlags = cwEnaFlag(app->multiPresetFlags,flow::kInterpPresetFl,m.value->u.b);
|
||||
break;
|
||||
|
||||
case kMidiThruCheckId:
|
||||
cwLogInfo("MIDI thru:%i",m.value->u.b);
|
||||
_set_midi_thru_state(app, m.value->u.b);
|
||||
@ -3238,6 +3261,18 @@ namespace cw
|
||||
_on_echo_midi_enable( app, m.uuId, midi_record_play::kSampler_MRP_DevIdx );
|
||||
break;
|
||||
|
||||
case kPriPresetProbCheckId:
|
||||
io::uiSendValue( app->ioH, m.uuId, preset_cfg_flags(app->ioFlowH) & flow::kPriPresetProbFl );
|
||||
break;
|
||||
|
||||
case kSecPresetProbCheckId:
|
||||
io::uiSendValue( app->ioH, m.uuId, preset_cfg_flags(app->ioFlowH) & flow::kSecPresetProbFl );
|
||||
break;
|
||||
|
||||
case kPresetInterpCheckId:
|
||||
io::uiSendValue( app->ioH, m.uuId, preset_cfg_flags(app->ioFlowH) & flow::kInterpPresetFl );
|
||||
break;
|
||||
|
||||
case kWetInGainId:
|
||||
_on_echo_master_value( app, preset_sel::kMasterWetInGainVarId, m.uuId );
|
||||
break;
|
||||
@ -3594,6 +3629,7 @@ cw::rc_t cw::preset_sel_app::main( const object_t* cfg, int argc, const char* ar
|
||||
rc = cwLogError(rc,"The IO Flow controller create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
app.multiPresetFlags = preset_cfg_flags(app.ioFlowH);
|
||||
}
|
||||
|
||||
printf("ioFlow is %s valid.\n",app.ioFlowH.isValid() ? "" : "not");
|
||||
|
@ -20,6 +20,12 @@
|
||||
|
||||
},
|
||||
|
||||
row: {
|
||||
check: { name: presetProbPriCheckId, title: "Pri Prob::" },
|
||||
check: { name: presetProbSecCheckId, title: "Sec Prob:" },
|
||||
check: { name: presetInterpCheckId, title: "Interp:"}
|
||||
},
|
||||
|
||||
row: {
|
||||
check: { name: printMidiCheckId, title: "Print MIDI" },
|
||||
check: { name: pianoMidiCheckId, title: "Piano MIDI" },
|
||||
|
Loading…
Reference in New Issue
Block a user