cwFlowProc.h/cpp : Added poly_xform_ctl. Fixed pedal handling in midi_voice
This commit is contained in:
parent
0f2a42940e
commit
9c57b3434f
488
cwFlowProc.cpp
488
cwFlowProc.cpp
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "cwFlowDecl.h"
|
#include "cwFlowDecl.h"
|
||||||
#include "cwFlow.h"
|
#include "cwFlow.h"
|
||||||
|
#include "cwFlowValue.h"
|
||||||
#include "cwFlowTypes.h"
|
#include "cwFlowTypes.h"
|
||||||
#include "cwFlowNet.h"
|
#include "cwFlowNet.h"
|
||||||
#include "cwFlowProc.h"
|
#include "cwFlowProc.h"
|
||||||
@ -42,36 +43,6 @@ namespace cw
|
|||||||
namespace flow
|
namespace flow
|
||||||
{
|
{
|
||||||
|
|
||||||
template< typename inst_t >
|
|
||||||
rc_t std_destroy( proc_t* proc )
|
|
||||||
{
|
|
||||||
inst_t* p = (inst_t*)proc->userPtr;
|
|
||||||
rc_t rc = _destroy(proc,p);
|
|
||||||
mem::release(proc->userPtr);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename inst_t >
|
|
||||||
rc_t std_create( proc_t* proc )
|
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
proc->userPtr = mem::allocZ<inst_t>();
|
|
||||||
if((rc = _create(proc,(inst_t*)proc->userPtr)) != kOkRC )
|
|
||||||
std_destroy<inst_t>(proc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename inst_t >
|
|
||||||
rc_t std_value( proc_t* proc, variable_t* var )
|
|
||||||
{ return _value(proc,(inst_t*)proc->userPtr, var); }
|
|
||||||
|
|
||||||
template< typename inst_t >
|
|
||||||
rc_t std_exec( proc_t* proc )
|
|
||||||
{ return _exec(proc,(inst_t*)proc->userPtr); }
|
|
||||||
|
|
||||||
template< typename inst_t >
|
|
||||||
rc_t std_report( proc_t* proc )
|
|
||||||
{ return _report(proc,(inst_t*)proc->userPtr); }
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
@ -240,7 +211,7 @@ namespace cw
|
|||||||
|
|
||||||
} inst_t;
|
} inst_t;
|
||||||
|
|
||||||
rc_t _voice_thread_func( void* arg )
|
rc_t _poly_thread_func( void* arg )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
voice_t* v = (voice_t*)arg;
|
voice_t* v = (voice_t*)arg;
|
||||||
@ -356,7 +327,7 @@ namespace cw
|
|||||||
inst->voiceA[i].voice_idx = i;
|
inst->voiceA[i].voice_idx = i;
|
||||||
inst->voiceA[i].net = net;
|
inst->voiceA[i].net = net;
|
||||||
|
|
||||||
inst->taskA[i].func = _voice_thread_func;
|
inst->taskA[i].func = _poly_thread_func;
|
||||||
inst->taskA[i].arg = inst->voiceA + i;
|
inst->taskA[i].arg = inst->voiceA + i;
|
||||||
|
|
||||||
net = net->poly_link;
|
net = net->poly_link;
|
||||||
@ -408,9 +379,13 @@ namespace cw
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((rc = exec_cycle(*proc->internal_net)) != kOkRC )
|
for(network_t* net=proc->internal_net; net!=nullptr; net=net->poly_link)
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"poly internal network exec failed.");
|
if((rc = exec_cycle(*net)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"poly internal network exec failed.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,6 +524,7 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BUG BUG BUG: why register "out" here when it is apparently registered again below?
|
||||||
if((rc = var_register( proc, kAnyChIdx, kOutPId, "out", kBaseSfxId)) != kOkRC )
|
if((rc = var_register( proc, kAnyChIdx, kOutPId, "out", kBaseSfxId)) != kOkRC )
|
||||||
{
|
{
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -1258,9 +1234,6 @@ namespace cw
|
|||||||
|
|
||||||
typedef struct inst_str
|
typedef struct inst_str
|
||||||
{
|
{
|
||||||
unsigned n;
|
|
||||||
coeff_t vgain;
|
|
||||||
coeff_t gain;
|
|
||||||
} inst_t;
|
} inst_t;
|
||||||
|
|
||||||
rc_t create( proc_t* proc )
|
rc_t create( proc_t* proc )
|
||||||
@ -1295,15 +1268,6 @@ namespace cw
|
|||||||
|
|
||||||
rc_t value( proc_t* proc, variable_t* var )
|
rc_t value( proc_t* proc, variable_t* var )
|
||||||
{
|
{
|
||||||
coeff_t value = 0;
|
|
||||||
inst_t* inst = (inst_t*)proc->userPtr;
|
|
||||||
var_get(proc,kGainPId,0,value);
|
|
||||||
|
|
||||||
if( inst->vgain != value )
|
|
||||||
{
|
|
||||||
inst->vgain = value;
|
|
||||||
//printf("VALUE GAIN: %s %s : %f\n", proc->label, var->label, value );
|
|
||||||
}
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1335,12 +1299,6 @@ namespace cw
|
|||||||
for(unsigned j=0; j<ibuf->frameN; ++j)
|
for(unsigned j=0; j<ibuf->frameN; ++j)
|
||||||
osig[j] = gain * isig[j];
|
osig[j] = gain * isig[j];
|
||||||
|
|
||||||
if( i==0 && gain != inst->gain )
|
|
||||||
{
|
|
||||||
inst->gain = gain;
|
|
||||||
//printf("EXEC GAIN: %s %f\n",proc->label,gain);
|
|
||||||
//proc_print(proc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -4131,7 +4089,6 @@ namespace cw
|
|||||||
unsigned msg_idx; // current count of msg's in msgA[]
|
unsigned msg_idx; // current count of msg's in msgA[]
|
||||||
|
|
||||||
mbuf_t* mbuf; // cached mbuf for this output variable
|
mbuf_t* mbuf; // cached mbuf for this output variable
|
||||||
|
|
||||||
} voice_t;
|
} voice_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -4144,16 +4101,17 @@ namespace cw
|
|||||||
// sizeof of each voice msgA[] (same as voice_t.msgN)
|
// sizeof of each voice msgA[] (same as voice_t.msgN)
|
||||||
unsigned voiceMsgN;
|
unsigned voiceMsgN;
|
||||||
|
|
||||||
|
unsigned midi_fld_idx;
|
||||||
} 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;
|
||||||
mbuf_t* mbuf = nullptr;
|
rbuf_t* rbuf = nullptr;
|
||||||
|
|
||||||
if((rc = var_register_and_get(proc,kAnyChIdx,
|
if((rc = var_register_and_get(proc,kAnyChIdx,
|
||||||
kInPId, "in", kBaseSfxId, mbuf,
|
kInPId, "in", kBaseSfxId, rbuf,
|
||||||
kVoiceCntPId, "voice_cnt", kBaseSfxId, p->voiceN)) != kOkRC )
|
kVoiceCntPId, "voice_cnt", kBaseSfxId, p->voiceN)) != kOkRC )
|
||||||
{
|
{
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -4169,6 +4127,12 @@ namespace cw
|
|||||||
p->voiceMsgN = kVoiceMsgN;
|
p->voiceMsgN = kVoiceMsgN;
|
||||||
p->voiceA = mem::allocZ<voice_t>(p->voiceN);
|
p->voiceA = mem::allocZ<voice_t>(p->voiceN);
|
||||||
|
|
||||||
|
if((p->midi_fld_idx = recd_type_field_index( rbuf->type, "midi")) == kInvalidIdx )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The 'in' record does not have a 'midi' field.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
for(unsigned i=0; i<p->voiceN; ++i)
|
for(unsigned i=0; i<p->voiceN; ++i)
|
||||||
{
|
{
|
||||||
// create one output MIDI variable per voice
|
// create one output MIDI variable per voice
|
||||||
@ -4206,12 +4170,12 @@ namespace cw
|
|||||||
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
|
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
/*
|
||||||
if( p->baseDoneFlPId <= var->vid && var->vid < p->baseDoneFlPId + p->voiceN )
|
if( p->baseDoneFlPId <= var->vid && var->vid < p->baseDoneFlPId + p->voiceN )
|
||||||
{
|
{
|
||||||
p->voiceA[ var->vid - p->baseDoneFlPId ].activeFl = false;
|
p->voiceA[ var->vid - p->baseDoneFlPId ].activeFl = false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4274,6 +4238,8 @@ namespace cw
|
|||||||
v->activeFl = true;
|
v->activeFl = true;
|
||||||
v->pitch = m->d0;
|
v->pitch = m->d0;
|
||||||
|
|
||||||
|
//printf("v_idx:%i non\n",voice_idx);
|
||||||
|
|
||||||
rc = _update_voice_msg(proc,p,voice_idx,m);
|
rc = _update_voice_msg(proc,p,voice_idx,m);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -4310,7 +4276,7 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _exec( proc_t* proc, inst_t* p )
|
rc_t _exec0( proc_t* proc, inst_t* p )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
mbuf_t* mbuf = nullptr;
|
mbuf_t* mbuf = nullptr;
|
||||||
@ -4359,6 +4325,71 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _exec( proc_t* proc, inst_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
rbuf_t* rbuf = nullptr;
|
||||||
|
|
||||||
|
// update the voice array
|
||||||
|
for(unsigned i=0; i<p->voiceN; ++i)
|
||||||
|
{
|
||||||
|
bool done_fl;
|
||||||
|
|
||||||
|
var_get(proc,p->baseDoneFlPId+i,kAnyChIdx,done_fl);
|
||||||
|
|
||||||
|
if( p->voiceA[i].activeFl && done_fl )
|
||||||
|
p->voiceA[i].activeFl = false;
|
||||||
|
|
||||||
|
if( p->voiceA[i].activeFl )
|
||||||
|
p->voiceA[i].age += 1;
|
||||||
|
|
||||||
|
p->voiceA[i].msg_idx = 0;
|
||||||
|
p->voiceA[i].mbuf->msgN = 0;
|
||||||
|
p->voiceA[i].mbuf->msgA = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the input MIDI buffer
|
||||||
|
if((rc = var_get(proc,kInPId,kAnyChIdx,rbuf)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// process the incoming MIDI messages
|
||||||
|
for(unsigned i=0; i<rbuf->recdN; ++i)
|
||||||
|
{
|
||||||
|
//const midi::ch_msg_t* m = mbuf->msgA + 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 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Record 'midi' field read failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( m->status )
|
||||||
|
{
|
||||||
|
case midi::kNoteOnMdId:
|
||||||
|
if( m->d1 == 0 )
|
||||||
|
rc = _on_note_off(proc,p,m);
|
||||||
|
else
|
||||||
|
rc = _on_note_on(proc,p,m);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case midi::kNoteOffMdId:
|
||||||
|
rc = _on_note_off(proc,p,m);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rc = _send_to_all_voices(proc,p,m);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _report( proc_t* proc, inst_t* p )
|
rc_t _report( proc_t* proc, inst_t* p )
|
||||||
{ return kOkRC; }
|
{ return kOkRC; }
|
||||||
|
|
||||||
@ -4380,6 +4411,8 @@ namespace cw
|
|||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
kInPId,
|
kInPId,
|
||||||
|
kGainPId,
|
||||||
|
kChCntPId,
|
||||||
kOutPId,
|
kOutPId,
|
||||||
kDoneFlPId
|
kDoneFlPId
|
||||||
};
|
};
|
||||||
@ -4387,6 +4420,8 @@ namespace cw
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
||||||
|
unsigned chN;
|
||||||
|
|
||||||
unsigned wtAllocN; // wtAlloc[ wtAllocN ]
|
unsigned wtAllocN; // wtAlloc[ wtAllocN ]
|
||||||
sample_t* wtAllocA; // total allocated WT space with extra leading and trailing samples
|
sample_t* wtAllocA; // total allocated WT space with extra leading and trailing samples
|
||||||
|
|
||||||
@ -4406,6 +4441,10 @@ namespace cw
|
|||||||
coeff_t gain;
|
coeff_t gain;
|
||||||
coeff_t gain_coeff;
|
coeff_t gain_coeff;
|
||||||
coeff_t gain_thresh;
|
coeff_t gain_thresh;
|
||||||
|
coeff_t fixed_gain;
|
||||||
|
|
||||||
|
bool isSustainDownFl;
|
||||||
|
bool heldByPedalFl;
|
||||||
|
|
||||||
} inst_t;
|
} inst_t;
|
||||||
|
|
||||||
@ -4415,17 +4454,18 @@ namespace cw
|
|||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
mbuf_t* mbuf = nullptr;
|
mbuf_t* mbuf = nullptr;
|
||||||
srate_t srate = proc->ctx->sample_rate;
|
srate_t srate = proc->ctx->sample_rate;
|
||||||
const unsigned ch_cnt = 1;
|
|
||||||
bool done_fl = false;
|
bool done_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,
|
||||||
|
kChCntPId, "chCnt", kBaseSfxId, p->chN,
|
||||||
kDoneFlPId, "done_fl", kBaseSfxId, done_fl)) != kOkRC )
|
kDoneFlPId, "done_fl", kBaseSfxId, done_fl)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
// create one output audio buffer
|
// create one output audio buffer
|
||||||
if((rc = var_register_and_set( proc, "out", kBaseSfxId,kOutPId, kAnyChIdx, srate, ch_cnt, proc->ctx->framesPerCycle )) != kOkRC )
|
if((rc = var_register_and_set( proc, "out", kBaseSfxId,kOutPId, kAnyChIdx, srate, p->chN, proc->ctx->framesPerCycle )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
// create the wave table
|
// create the wave table
|
||||||
@ -4470,8 +4510,19 @@ namespace cw
|
|||||||
void _on_note_off( inst_t* p )
|
void _on_note_off( inst_t* p )
|
||||||
{
|
{
|
||||||
p->gain_coeff = 0.9;
|
p->gain_coeff = 0.9;
|
||||||
|
|
||||||
|
if( p->isSustainDownFl )
|
||||||
|
p->heldByPedalFl = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _on_sustain_pedal(proc_t* proc, inst_t* p, bool pedal_down_fl )
|
||||||
|
{
|
||||||
|
p->isSustainDownFl = pedal_down_fl;
|
||||||
|
|
||||||
|
if( !p->isSustainDownFl && !p->heldByPedalFl )
|
||||||
|
_on_note_off(p);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -4504,6 +4555,9 @@ namespace cw
|
|||||||
p->gain = (coeff_t)p->cur_vel / 127;
|
p->gain = (coeff_t)p->cur_vel / 127;
|
||||||
p->gain_coeff = 1.0;
|
p->gain_coeff = 1.0;
|
||||||
p->gain_thresh = 0.001;
|
p->gain_thresh = 0.001;
|
||||||
|
var_set(proc,kDoneFlPId,kAnyChIdx,false);
|
||||||
|
|
||||||
|
//printf("NO: %i\n",proc->label_sfx_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4511,6 +4565,11 @@ namespace cw
|
|||||||
_on_note_off(p);
|
_on_note_off(p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case midi::kCtlMdId:
|
||||||
|
if( midi::isSustainPedal( m->status, m->d0 ) )
|
||||||
|
_on_sustain_pedal(proc,p, midi::isPedalDown(m->d1) );
|
||||||
|
break;
|
||||||
|
|
||||||
case midi::kPbendMdId:
|
case midi::kPbendMdId:
|
||||||
p->cur_pbend = midi::toPbend(m->d0,m->d1) / 8192.0;
|
p->cur_pbend = midi::toPbend(m->d0,m->d1) / 8192.0;
|
||||||
break;
|
break;
|
||||||
@ -4529,19 +4588,25 @@ namespace cw
|
|||||||
{
|
{
|
||||||
|
|
||||||
// fill in the audio buffer
|
// fill in the audio buffer
|
||||||
for(unsigned i=0; i<abuf->frameN; ++i)
|
for(unsigned ch_idx=0; ch_idx<abuf->chN; ++ch_idx)
|
||||||
{
|
{
|
||||||
unsigned j = (unsigned)floor(p->wtPhase);
|
sample_t* obuf = abuf->buf + (ch_idx * abuf->frameN);
|
||||||
double frac = p->wtPhase - j;
|
coeff_t gain = p->gain*p->fixed_gain;
|
||||||
sample_t smp = p->wtA[j] + (p->wtA[j+1] - p->wtA[j]) * frac;
|
|
||||||
|
for(unsigned i=0; i<abuf->frameN; ++i)
|
||||||
abuf->buf[i] = p->gain*smp;
|
{
|
||||||
|
unsigned j = (unsigned)floor(p->wtPhase);
|
||||||
|
double frac = p->wtPhase - j;
|
||||||
|
sample_t smp = p->wtA[j] + (p->wtA[j+1] - p->wtA[j]) * frac;
|
||||||
|
|
||||||
|
obuf[i] = gain*smp;
|
||||||
|
|
||||||
|
p->wtPhase += p->cur_hz + (p->cur_hz * p->cur_pbend);
|
||||||
|
if( p->wtPhase >= p->wtN )
|
||||||
|
p->wtPhase -= p->wtN;
|
||||||
|
}
|
||||||
|
|
||||||
p->wtPhase += p->cur_hz + (p->cur_hz * p->cur_pbend);
|
|
||||||
if( p->wtPhase >= p->wtN )
|
|
||||||
p->wtPhase -= p->wtN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p->gain *= p->gain_coeff;
|
p->gain *= p->gain_coeff;
|
||||||
|
|
||||||
if( p->gain < p->gain_thresh )
|
if( p->gain < p->gain_thresh )
|
||||||
@ -4603,11 +4668,13 @@ namespace cw
|
|||||||
unsigned test_pitchN; // Count of valid velocities for test_pitch
|
unsigned test_pitchN; // Count of valid velocities for test_pitch
|
||||||
unsigned* test_pitch_map; // test_pitch_map[ test_pitch_N ]
|
unsigned* test_pitch_map; // test_pitch_map[ test_pitch_N ]
|
||||||
|
|
||||||
bool done_fl;
|
bool done_fl;
|
||||||
coeff_t gain;
|
coeff_t gain;
|
||||||
coeff_t gain_coeff;
|
coeff_t gain_coeff;
|
||||||
coeff_t kReleaseGain;
|
coeff_t kReleaseGain;
|
||||||
coeff_t kGainThreshold;
|
coeff_t kGainThreshold;
|
||||||
|
bool isSustainDownFl;
|
||||||
|
bool heldByPedalFl;
|
||||||
|
|
||||||
} inst_t;
|
} inst_t;
|
||||||
|
|
||||||
@ -4619,7 +4686,7 @@ namespace cw
|
|||||||
unsigned padSmpN = 1;
|
unsigned padSmpN = 1;
|
||||||
|
|
||||||
// if the global wave table bank has not yet been created
|
// if the global wave table bank has not yet been created
|
||||||
if((p->wtbH_ptr = (wt_bank::handle_t*)network_global_var(proc, wtb_var_label )) == nullptr )
|
if((p->wtbH_ptr = (wt_bank::handle_t*)global_var(proc, wtb_var_label )) == nullptr )
|
||||||
{
|
{
|
||||||
wt_bank::handle_t wtbH;
|
wt_bank::handle_t wtbH;
|
||||||
|
|
||||||
@ -4637,13 +4704,13 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store the wave table bank global var
|
// store the wave table bank global var
|
||||||
if((rc = network_global_var_alloc(proc, wtb_var_label, &wtbH, sizeof(wtbH) )) != kOkRC )
|
if((rc = global_var_alloc(proc, wtb_var_label, &wtbH, sizeof(wtbH) )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"The wave table bank global variable allocation failed.");
|
rc = cwLogError(rc,"The wave table bank global variable allocation failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((p->wtbH_ptr = (wt_bank::handle_t*)network_global_var(proc, wtb_var_label )) == nullptr )
|
if((p->wtbH_ptr = (wt_bank::handle_t*)global_var(proc, wtb_var_label )) == nullptr )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"The wave table bank global variable store failed.");
|
rc = cwLogError(rc,"The wave table bank global variable store failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -4764,7 +4831,7 @@ namespace cw
|
|||||||
d0 = p->test_pitch;
|
d0 = p->test_pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%i %i\n",d0,d1);
|
//printf("%s:%i %i %i\n",proc->label,proc->label_sfx_id,d0,d1);
|
||||||
|
|
||||||
// get the wave-table associated with the pitch and velocity
|
// get the wave-table associated with the pitch and velocity
|
||||||
if((rc = get_wave_table( *p->wtbH_ptr, p->wtb_instr_idx, d0, d1, mcs)) != kOkRC )
|
if((rc = get_wave_table( *p->wtbH_ptr, p->wtb_instr_idx, d0, d1, mcs)) != kOkRC )
|
||||||
@ -4782,21 +4849,43 @@ namespace cw
|
|||||||
|
|
||||||
p->done_fl = false;
|
p->done_fl = false;
|
||||||
p->kGainThreshold = 0.01;
|
p->kGainThreshold = 0.01;
|
||||||
p->kReleaseGain = 0.9;
|
p->kReleaseGain = 0.98;
|
||||||
p->gain = 1.0;
|
p->gain = 1.0;
|
||||||
p->gain_coeff = 1.0;
|
p->gain_coeff = 1.0;
|
||||||
|
p->heldByPedalFl = false;
|
||||||
|
|
||||||
|
var_set(proc,kDoneFlPId,kAnyChIdx,false);
|
||||||
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _on_note_off( inst_t* p )
|
void _begin_note_release( inst_t* p )
|
||||||
{
|
{
|
||||||
p->gain_coeff = p->kReleaseGain;
|
p->gain_coeff = p->kReleaseGain;
|
||||||
//printf("%i nof: %i %i\n",proc->label_sfx_id,m->d0,m->d1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _on_note_off( inst_t* p )
|
||||||
|
{
|
||||||
|
if( p->isSustainDownFl )
|
||||||
|
p->heldByPedalFl = true;
|
||||||
|
else
|
||||||
|
_begin_note_release(p);
|
||||||
|
|
||||||
|
//printf("%i nof: %i %i\n",proc->label_sfx_id,m->d0,m->d1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _on_sustain_pedal(proc_t* proc, inst_t* p, bool pedal_down_fl )
|
||||||
|
{
|
||||||
|
p->isSustainDownFl = pedal_down_fl;
|
||||||
|
|
||||||
|
if( !p->isSustainDownFl && !p->heldByPedalFl )
|
||||||
|
_begin_note_release(p);
|
||||||
|
|
||||||
|
//printf("%s:%i %s\n",proc->label,proc->label_sfx_id,pedal_down_fl ? "V" : "^");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _destroy( proc_t* proc, inst_t* p )
|
rc_t _destroy( proc_t* proc, inst_t* p )
|
||||||
{
|
{
|
||||||
@ -4854,6 +4943,11 @@ namespace cw
|
|||||||
|
|
||||||
case midi::kPbendMdId:
|
case midi::kPbendMdId:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case midi::kCtlMdId:
|
||||||
|
if( midi::isSustainPedal( m->status, m->d0 ) )
|
||||||
|
_on_sustain_pedal(proc,p, midi::isPedalDown(m->d1) );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -4871,8 +4965,8 @@ namespace cw
|
|||||||
|
|
||||||
if( (p->gain < p->kGainThreshold && !p->done_fl) || (actualFrmN < abuf->frameN) )
|
if( (p->gain < p->kGainThreshold && !p->done_fl) || (actualFrmN < abuf->frameN) )
|
||||||
{
|
{
|
||||||
var_set(proc,kDoneFlPId,kAnyChIdx,true);
|
|
||||||
p->done_fl = true;
|
p->done_fl = true;
|
||||||
|
var_set(proc,kDoneFlPId,kAnyChIdx,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -7170,7 +7264,7 @@ namespace cw
|
|||||||
if((rc = var_get(proc,vid,kAnyChIdx,v)) != kOkRC )
|
if((rc = var_get(proc,vid,kAnyChIdx,v)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
if( 0 <= v && v <= max_val )
|
if( v <= max_val )
|
||||||
midi_byte_ref = (uint8_t)v;
|
midi_byte_ref = (uint8_t)v;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -7718,6 +7812,236 @@ namespace cw
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// poly_xform_ctl
|
||||||
|
//
|
||||||
|
namespace poly_xform_ctl
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
kOutChCntPId,
|
||||||
|
kOutChIdxPId,
|
||||||
|
kInBasePId,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct in_var_str
|
||||||
|
{
|
||||||
|
unsigned out_idx;
|
||||||
|
} in_var_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned inVarN;
|
||||||
|
in_var_t* inVarA;
|
||||||
|
|
||||||
|
unsigned outVarN;
|
||||||
|
|
||||||
|
unsigned midiBasePId;
|
||||||
|
unsigned doneFlBasePId;
|
||||||
|
unsigned outBasePId;
|
||||||
|
|
||||||
|
} inst_t;
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _create( proc_t* proc, inst_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
srate_t srate = 0;
|
||||||
|
unsigned audioFrameN = 0;
|
||||||
|
unsigned chCntPerInputSignal = 0;
|
||||||
|
unsigned aSfxIdAllocN = var_mult_count(proc,"in");
|
||||||
|
unsigned aSfxIdA[ aSfxIdAllocN ];
|
||||||
|
|
||||||
|
// get the the sfx_id's of the input audio variables
|
||||||
|
if((rc = var_mult_sfx_id_array(proc, "in", aSfxIdA, aSfxIdAllocN, p->inVarN )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
p->midiBasePId = kInBasePId + p->inVarN;
|
||||||
|
p->doneFlBasePId = p->midiBasePId + p->inVarN;
|
||||||
|
p->outBasePId = p->doneFlBasePId + p->inVarN;
|
||||||
|
p->inVarA = mem::allocZ<in_var_t>( p->inVarN );
|
||||||
|
|
||||||
|
// for each audio input var
|
||||||
|
for(unsigned i=0; i<p->inVarN; ++i)
|
||||||
|
{
|
||||||
|
abuf_t* abuf = nullptr;
|
||||||
|
|
||||||
|
// register the input audio variable
|
||||||
|
if((rc = var_register_and_get(proc,kAnyChIdx,kInBasePId+i,"in",aSfxIdA[i],abuf)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
assert(abuf != nullptr );
|
||||||
|
|
||||||
|
// the sample rate of the input audio signals must be the same
|
||||||
|
if( i != 0 && abuf->srate != srate )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"All signals on a poly merge must have the same sample rate.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
srate = abuf->srate;
|
||||||
|
|
||||||
|
// the count of frames in all audio signals must be the same
|
||||||
|
if( audioFrameN != 0 && abuf->frameN != audioFrameN )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"All signals on a poly merge must have the same frame count.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioFrameN = abuf->frameN;
|
||||||
|
|
||||||
|
// track the max channel count among all audio input variables
|
||||||
|
if( abuf->chN > chCntPerInputSignal )
|
||||||
|
chCntPerInputSignal = abuf->chN;
|
||||||
|
|
||||||
|
if((rc = var_register(proc,kAnyChIdx,p->midiBasePId + i, "midi", aSfxIdA[i])) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
if((rc = var_register(proc,kAnyChIdx,p->doneFlBasePId + i, "donefl", aSfxIdA[i])) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// initialize the ith input channels
|
||||||
|
p->inVarA[i].out_idx = kInvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the count of output vars
|
||||||
|
if((rc = var_register_and_get( proc, kAnyChIdx, kOutChCntPId, "out_ch_cnt", kBaseSfxId, p->outVarN )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// register the output selector var
|
||||||
|
if((rc = var_register( proc, kAnyChIdx, kOutChIdxPId,"out_ch_idx", kBaseSfxId )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// create the output audio var's
|
||||||
|
for(unsigned i=0; i<p->outVarN; ++i)
|
||||||
|
if((rc = var_register_and_set( proc, "out", kBaseSfxId + i, p->outBasePId+i, kAnyChIdx, srate, chCntPerInputSignal, audioFrameN )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _destroy( proc_t* proc, inst_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
mem::release(p->inVarA);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _mix( unsigned out_var_idx, abuf_t* obuf, const abuf_t* ibuf )
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned chN = std::min(ibuf->chN, obuf->chN );
|
||||||
|
sample_t sum = 0;
|
||||||
|
|
||||||
|
for(unsigned i=0; i<chN; ++i)
|
||||||
|
{
|
||||||
|
const sample_t* isig = ibuf->buf + i*ibuf->frameN;
|
||||||
|
sample_t* osig = obuf->buf + i*obuf->frameN;
|
||||||
|
|
||||||
|
for(unsigned j=0; j<obuf->frameN; ++j)
|
||||||
|
{
|
||||||
|
osig[j] += isig[j];
|
||||||
|
if( isig[j] != 0.0f )
|
||||||
|
{
|
||||||
|
sum += std::fabs(isig[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if( sum > 0 )
|
||||||
|
// printf("MTR:%i %i %f\n",out_var_idx,obuf->frameN,sum);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _exec( proc_t* proc, inst_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
abuf_t* outAudioBufA[ p->outVarN ];
|
||||||
|
unsigned out_var_idx;
|
||||||
|
|
||||||
|
if((var_get(proc,kOutChIdxPId,kAnyChIdx,out_var_idx)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// get the audio output buffers
|
||||||
|
for(unsigned i=0; i<p->outVarN; ++i)
|
||||||
|
{
|
||||||
|
if((rc = var_get(proc,p->outBasePId + i, kAnyChIdx, outAudioBufA[i] )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
vop::zero(outAudioBufA[i]->buf,outAudioBufA[i]->chN * outAudioBufA[i]->frameN );
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each input signal var
|
||||||
|
for(unsigned i=0; i<p->inVarN; ++i)
|
||||||
|
{
|
||||||
|
mbuf_t* mbuf = nullptr;
|
||||||
|
bool done_fl = false;
|
||||||
|
|
||||||
|
// get the incoming midi msg's
|
||||||
|
if((rc = var_get(proc,p->midiBasePId + i,kAnyChIdx,mbuf)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// for each received note-on msg set the output var of the associated output channel
|
||||||
|
for(unsigned j=0; j<mbuf->msgN; ++j)
|
||||||
|
if( midi::isNoteOn(mbuf->msgA[j].status,mbuf->msgA[j].d1) )
|
||||||
|
{
|
||||||
|
p->inVarA[i].out_idx = out_var_idx;
|
||||||
|
//printf("VA: %i->%i\n",i,out_var_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the state of the 'done_fl'
|
||||||
|
if((rc = var_get(proc,p->doneFlBasePId + i,kAnyChIdx,done_fl)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
|
||||||
|
// if this input channel is no longer active
|
||||||
|
if( p->inVarA[i].out_idx != kInvalidIdx && done_fl )
|
||||||
|
{
|
||||||
|
p->inVarA[i].out_idx = kInvalidIdx;
|
||||||
|
//printf("D:%i\n",i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this channel has a valid out var index
|
||||||
|
if( p->inVarA[i].out_idx != kInvalidIdx )
|
||||||
|
{
|
||||||
|
abuf_t* abuf = nullptr;
|
||||||
|
|
||||||
|
// get the input audio buffer
|
||||||
|
if((rc = var_get(proc,kInBasePId + i, kAnyChIdx, abuf)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// mix the input into the output
|
||||||
|
_mix(p->inVarA[i].out_idx, outAudioBufA[ p->inVarA[i].out_idx ], abuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _report( proc_t* proc, inst_t* p )
|
||||||
|
{ return kOkRC; }
|
||||||
|
|
||||||
|
class_members_t members = {
|
||||||
|
.create = std_create<inst_t>,
|
||||||
|
.destroy = std_destroy<inst_t>,
|
||||||
|
.value = std_value<inst_t>,
|
||||||
|
.exec = std_exec<inst_t>,
|
||||||
|
.report = std_report<inst_t>
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // flow
|
} // flow
|
||||||
|
34
cwFlowProc.h
34
cwFlowProc.h
@ -4,6 +4,39 @@ namespace cw
|
|||||||
{
|
{
|
||||||
namespace flow
|
namespace flow
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template< typename inst_t >
|
||||||
|
rc_t std_destroy( proc_t* proc )
|
||||||
|
{
|
||||||
|
inst_t* p = (inst_t*)proc->userPtr;
|
||||||
|
rc_t rc = _destroy(proc,p);
|
||||||
|
mem::release(proc->userPtr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename inst_t >
|
||||||
|
rc_t std_create( proc_t* proc )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
proc->userPtr = mem::allocZ<inst_t>();
|
||||||
|
if((rc = _create(proc,(inst_t*)proc->userPtr)) != kOkRC )
|
||||||
|
std_destroy<inst_t>(proc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename inst_t >
|
||||||
|
rc_t std_value( proc_t* proc, variable_t* var )
|
||||||
|
{ return _value(proc,(inst_t*)proc->userPtr, var); }
|
||||||
|
|
||||||
|
template< typename inst_t >
|
||||||
|
rc_t std_exec( proc_t* proc )
|
||||||
|
{ return _exec(proc,(inst_t*)proc->userPtr); }
|
||||||
|
|
||||||
|
template< typename inst_t >
|
||||||
|
rc_t std_report( proc_t* proc )
|
||||||
|
{ return _report(proc,(inst_t*)proc->userPtr); }
|
||||||
|
|
||||||
|
|
||||||
namespace user_def_proc { extern class_members_t members; }
|
namespace user_def_proc { extern class_members_t members; }
|
||||||
namespace poly { extern class_members_t members; }
|
namespace poly { extern class_members_t members; }
|
||||||
namespace midi_in { extern class_members_t members; }
|
namespace midi_in { extern class_members_t members; }
|
||||||
@ -48,6 +81,7 @@ namespace cw
|
|||||||
namespace midi_split { extern class_members_t members; }
|
namespace midi_split { extern class_members_t members; }
|
||||||
namespace midi_file { extern class_members_t members; }
|
namespace midi_file { extern class_members_t members; }
|
||||||
namespace midi_merge { extern class_members_t members; }
|
namespace midi_merge { extern class_members_t members; }
|
||||||
|
namespace poly_xform_ctl { extern class_members_t members; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user