cwFlowProc.h/cpp,cwFlow.cpp : Re-write of piano voice to handle new wave-table-bank format.
This commit is contained in:
parent
5b1e7d1b82
commit
c87fc2a9e4
@ -58,7 +58,7 @@ namespace cw
|
|||||||
{ "xfade_ctl", &xfade_ctl::members },
|
{ "xfade_ctl", &xfade_ctl::members },
|
||||||
{ "poly_voice_ctl", &poly_voice_ctl::members },
|
{ "poly_voice_ctl", &poly_voice_ctl::members },
|
||||||
{ "midi_voice", &midi_voice::members },
|
{ "midi_voice", &midi_voice::members },
|
||||||
//{ "piano_voice", &piano_voice::members },
|
{ "piano_voice", &piano_voice::members },
|
||||||
{ "sample_hold", &sample_hold::members },
|
{ "sample_hold", &sample_hold::members },
|
||||||
{ "number", &number::members },
|
{ "number", &number::members },
|
||||||
{ "reg", ®::members },
|
{ "reg", ®::members },
|
||||||
|
351
cwFlowProc.cpp
351
cwFlowProc.cpp
@ -4442,8 +4442,9 @@ namespace cw
|
|||||||
.report = std_report<inst_t>
|
.report = std_report<inst_t>
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef NOT_DEF
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// piano_voice
|
// piano_voice
|
||||||
@ -4451,7 +4452,7 @@ namespace cw
|
|||||||
namespace piano_voice
|
namespace piano_voice
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
kWtbDirPId,
|
kWtbFnPId,
|
||||||
kWtbInstrPId,
|
kWtbInstrPId,
|
||||||
kInPId,
|
kInPId,
|
||||||
kOutPId,
|
kOutPId,
|
||||||
@ -4463,95 +4464,48 @@ namespace cw
|
|||||||
enum {
|
enum {
|
||||||
kChCnt=2
|
kChCnt=2
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct osc_state_str
|
|
||||||
{
|
|
||||||
wt_bank::ch_t* ch;
|
|
||||||
unsigned seg_idx; // current seg index in ch->segA[]
|
|
||||||
unsigned smp_idx; // current smp index in ch->segA[ seg_idx ].aV[]
|
|
||||||
unsigned seg_cnt; // count of segments played so far (increases with each segment loop traversail)
|
|
||||||
} osc_state_t;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
wt_bank::handle_t* wtbH_ptr;
|
wt_bank::handle_t* wtbH_ptr;
|
||||||
unsigned wtb_instr_idx;
|
unsigned wtb_instr_idx;
|
||||||
const wt_bank::wt_t* wt;
|
|
||||||
|
|
||||||
osc_state_t osc[ kChCnt ];
|
// multi-channel wave table oscillator
|
||||||
|
struct dsp::multi_ch_wt_seq_osc::obj_str<sample_t,srate_t> osc;
|
||||||
coeff_t kGainThreshold;
|
|
||||||
coeff_t kSustainGain;
|
|
||||||
coeff_t kReleaseGain;
|
|
||||||
|
|
||||||
coeff_t gain;
|
|
||||||
coeff_t gain_coeff;
|
|
||||||
bool done_fl;
|
|
||||||
|
|
||||||
unsigned test_pitch; // Pitch under test or 0 if not on test mode
|
unsigned test_pitch; // Pitch under test or 0 if not on test mode
|
||||||
unsigned test_key_pitch; // Key associated with lowest velocity when in test mode.
|
unsigned test_key_pitch; // Key associated with lowest velocity when in test mode.
|
||||||
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;
|
||||||
|
coeff_t gain;
|
||||||
|
coeff_t gain_coeff;
|
||||||
|
coeff_t kReleaseGain;
|
||||||
|
coeff_t kGainThreshold;
|
||||||
|
|
||||||
} inst_t;
|
} inst_t;
|
||||||
|
|
||||||
|
rc_t _load_wtb(proc_t* proc, inst_t* p, const char* wtb_fname)
|
||||||
void _create_test_pitch_map( inst_t* p )
|
|
||||||
{
|
{
|
||||||
p->test_pitchN = 0;
|
rc_t rc = kOkRC;
|
||||||
for(unsigned i=0; i<midi::kMidiVelCnt; ++i)
|
const char* wtb_var_label = "wtb";
|
||||||
if( get_wave_table( *p->wtbH_ptr, 0, p->test_pitch, i ) != nullptr )
|
char* exp_wtb_fname = nullptr;
|
||||||
p->test_pitchN += 1;
|
unsigned padSmpN = 1;
|
||||||
|
|
||||||
p->test_pitch_map = mem::allocZ<unsigned>(p->test_pitchN);
|
|
||||||
|
|
||||||
for(unsigned i=0,j=0; i<midi::kMidiVelCnt; ++i)
|
|
||||||
if( get_wave_table( *p->wtbH_ptr, p->wtb_instr_idx, p->test_pitch, i ) != nullptr )
|
|
||||||
{
|
|
||||||
assert( j < p->test_pitchN );
|
|
||||||
p->test_pitch_map[j++] = i;
|
|
||||||
//printf("%i %i %i\n",j-1,i,p->test_pitchN);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
rc_t _create( proc_t* proc, inst_t* p )
|
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
const char* wtb_dir = nullptr;
|
|
||||||
char* exp_wtb_dir = nullptr;
|
|
||||||
const char* wtb_instr = nullptr;
|
|
||||||
mbuf_t* mbuf = nullptr;
|
|
||||||
bool done_fl = false;
|
|
||||||
srate_t srate = proc->ctx->sample_rate;
|
|
||||||
unsigned padSmpN = 1;
|
|
||||||
const char* wtb_var_label = "wtb";
|
|
||||||
|
|
||||||
// get the MIDI input variable
|
|
||||||
if((rc = var_register_and_get( proc, kAnyChIdx,
|
|
||||||
kWtbDirPId, "wtb_dir", kBaseSfxId, wtb_dir,
|
|
||||||
kWtbInstrPId, "wtb_instr", kBaseSfxId, wtb_instr,
|
|
||||||
kInPId, "in", kBaseSfxId, mbuf,
|
|
||||||
kDoneFlPId, "done_fl", kBaseSfxId, done_fl,
|
|
||||||
kTestPitchPId, "test_pitch",kBaseSfxId, p->test_pitch,
|
|
||||||
kKeyPitchPId, "test_key_pitch", kBaseSfxId, p->test_key_pitch)) != kOkRC )
|
|
||||||
{
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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*)network_global_var(proc, wtb_var_label )) == nullptr )
|
||||||
{
|
{
|
||||||
wt_bank::handle_t wtbH;
|
wt_bank::handle_t wtbH;
|
||||||
|
|
||||||
if((exp_wtb_dir = proc_expand_filename(proc,wtb_dir)) == nullptr )
|
if((exp_wtb_fname = proc_expand_filename(proc,wtb_fname)) == nullptr )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kOpFailRC,"The wave-table bank directory expansion failed.");
|
rc = cwLogError(kOpFailRC,"The wave-table bank directory expansion failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the wave table bank
|
// create the wave table bank
|
||||||
if((rc = create( wtbH, exp_wtb_dir, padSmpN )) != kOkRC )
|
if((rc = create( wtbH, padSmpN, exp_wtb_fname)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"The wave table bank global variable creation failed.");
|
rc = cwLogError(rc,"The wave table bank global variable creation failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -4571,7 +4525,65 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Wave table bank load failed on '%s'.",cwStringNullGuard(wtb_fname));
|
||||||
|
|
||||||
|
mem::release(exp_wtb_fname);
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _create_test_pitch_map( proc_t* proc, inst_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
unsigned velA[ midi::kMidiVelCnt ];
|
||||||
|
|
||||||
|
if((rc = instr_pitch_velocities(*p->wtbH_ptr, p->wtb_instr_idx, p->test_pitch, velA, midi::kMidiVelCnt, p->test_pitchN )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Sampled velocity access failed on '%s'.",cwStringNullGuard(proc->label));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->test_pitch_map = mem::allocZ<unsigned>(p->test_pitchN);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<p->test_pitchN; ++i)
|
||||||
|
p->test_pitch_map[i] = velA[i];
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _create( proc_t* proc, inst_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const char* wtb_fname = nullptr;
|
||||||
|
const char* wtb_instr = nullptr;
|
||||||
|
mbuf_t* mbuf = nullptr;
|
||||||
|
bool done_fl = false;
|
||||||
|
srate_t srate = proc->ctx->sample_rate;
|
||||||
|
|
||||||
|
// get the MIDI input variable
|
||||||
|
if((rc = var_register_and_get( proc, kAnyChIdx,
|
||||||
|
kWtbFnPId, "wtb_fname", kBaseSfxId, wtb_fname,
|
||||||
|
kWtbInstrPId, "wtb_instr", kBaseSfxId, wtb_instr,
|
||||||
|
kInPId, "in", kBaseSfxId, mbuf,
|
||||||
|
kDoneFlPId, "done_fl", kBaseSfxId, done_fl,
|
||||||
|
kTestPitchPId, "test_pitch",kBaseSfxId, p->test_pitch,
|
||||||
|
kKeyPitchPId, "test_key_pitch", kBaseSfxId, p->test_key_pitch)) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the wave table bank handle (p->wtbH_ptr(
|
||||||
|
if((rc = _load_wtb(proc, p, wtb_fname)) != kOkRC )
|
||||||
|
{
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// create one output audio buffer
|
// create one output audio buffer
|
||||||
if((rc = var_register_and_set( proc, "out", kBaseSfxId,kOutPId, kAnyChIdx, srate, kChCnt, proc->ctx->framesPerCycle )) != kOkRC )
|
if((rc = var_register_and_set( proc, "out", kBaseSfxId,kOutPId, kAnyChIdx, srate, kChCnt, proc->ctx->framesPerCycle )) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -4580,7 +4592,7 @@ namespace cw
|
|||||||
|
|
||||||
if((p->wtb_instr_idx = wt_bank::instr_index( *p->wtbH_ptr, wtb_instr )) == kInvalidIdx )
|
if((p->wtb_instr_idx = wt_bank::instr_index( *p->wtbH_ptr, wtb_instr )) == kInvalidIdx )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"The wave table bank named '%s' could not be found.",cwStringNullGuard(wtb_instr));
|
rc = cwLogError(rc,"The wave table bank instrument '%s' could not be found.",cwStringNullGuard(wtb_instr));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4588,23 +4600,79 @@ namespace cw
|
|||||||
if( p->test_pitch != 0 )
|
if( p->test_pitch != 0 )
|
||||||
{
|
{
|
||||||
cwLogInfo("%s is in test-pitch mode",proc->label);
|
cwLogInfo("%s is in test-pitch mode",proc->label);
|
||||||
_create_test_pitch_map(p);
|
if((rc = _create_test_pitch_map(proc,p)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate,setup and validate the expected srate of the oscillator
|
||||||
|
if((rc = create(&p->osc,kChCnt)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"multi-ch-wt-seq-osc create failed.");
|
||||||
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->done_fl = true;
|
|
||||||
p->kGainThreshold = 0.01;
|
|
||||||
p->kSustainGain = 0.9995;
|
|
||||||
p->kReleaseGain = 0.9;
|
|
||||||
|
|
||||||
|
p->done_fl = true;
|
||||||
assert(p->wtbH_ptr != nullptr );
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
mem::release(exp_wtb_dir);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _on_note_on( proc_t* proc, inst_t* p, unsigned d0, unsigned d1 )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const struct dsp::multi_ch_wt_seq_osc::multi_ch_wt_seq_str<sample_t,srate_t>* mcs = nullptr;
|
||||||
|
|
||||||
|
// if in voice test mode
|
||||||
|
if( p->test_pitch_map != nullptr )
|
||||||
|
{
|
||||||
|
// if the the pitch is inside the test range
|
||||||
|
if( d0 < p->test_key_pitch || p->test_key_pitch + p->test_pitchN <= d0 )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// ... then the velocity is mapped to a vel for which there is a known vel in the wt-bank
|
||||||
|
// Performed pitches above the test pitch trigger increasing velocities ...
|
||||||
|
d1 = p->test_pitch_map[ d0 - p->test_key_pitch ];
|
||||||
|
|
||||||
|
// ... and the pitch is set to the test pitch
|
||||||
|
d0 = p->test_pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%i %i\n",d0,d1);
|
||||||
|
|
||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"No piano voice for pitch:%i vel:%i",d0,d1);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup the oscillator with a new wave table
|
||||||
|
if((rc = setup(&p->osc,mcs)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Oscilllator setup error on instr:%i pitch:%i vel:%i.",p->wtb_instr_idx,d0,d1);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->done_fl = false;
|
||||||
|
p->kGainThreshold = 0.01;
|
||||||
|
p->kReleaseGain = 0.9;
|
||||||
|
p->gain = 1.0;
|
||||||
|
p->gain_coeff = 1.0;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _on_note_off( inst_t* p )
|
||||||
|
{
|
||||||
|
p->gain_coeff = p->kReleaseGain;
|
||||||
|
//printf("%i nof: %i %i\n",proc->label_sfx_id,m->d0,m->d1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rc_t _destroy( proc_t* proc, inst_t* p )
|
rc_t _destroy( proc_t* proc, inst_t* p )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -4628,15 +4696,20 @@ 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;
|
||||||
|
unsigned actualFrmN = 0;
|
||||||
|
|
||||||
// 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 )
|
||||||
|
{
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
// get the output audio buffer
|
// get the output audio buffer
|
||||||
if((rc = var_get(proc,kOutPId,kAnyChIdx,abuf)) != kOkRC )
|
if((rc = var_get(proc,kOutPId,kAnyChIdx,abuf)) != kOkRC )
|
||||||
|
{
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
// if there are MIDI messages - update the wavetable oscillators
|
// if there are MIDI messages - update the wavetable oscillators
|
||||||
for(unsigned i=0; i<mbuf->msgN; ++i)
|
for(unsigned i=0; i<mbuf->msgN; ++i)
|
||||||
{
|
{
|
||||||
@ -4644,59 +4717,14 @@ namespace cw
|
|||||||
switch( m->status )
|
switch( m->status )
|
||||||
{
|
{
|
||||||
case midi::kNoteOnMdId:
|
case midi::kNoteOnMdId:
|
||||||
|
|
||||||
if( m->d1 > 0 )
|
if( m->d1 > 0 )
|
||||||
{
|
rc = _on_note_on(proc,p,m->d0,m->d1);
|
||||||
unsigned d0 = m->d0;
|
|
||||||
unsigned d1 = m->d1;
|
|
||||||
|
|
||||||
// if in voice test mode
|
|
||||||
if( p->test_pitch_map != nullptr )
|
|
||||||
{
|
|
||||||
// if the the pitch is inside the test range
|
|
||||||
if( d0 < p->test_key_pitch || p->test_key_pitch + p->test_pitchN <= d0 )
|
|
||||||
goto errLabel;
|
|
||||||
|
|
||||||
// then the pitch is set to the test pitch ...
|
|
||||||
d0 = p->test_pitch;
|
|
||||||
|
|
||||||
// ... and the velocity is mapped to a vel for which there is a known vel in the wt-bank
|
|
||||||
// Performed pitches above the test pitch trigger increasing velocities.
|
|
||||||
d1 = p->test_pitch_map[ m->d0 - p->test_key_pitch ];
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the wave-table associated with the pitch and velocity
|
|
||||||
if((p->wt = get_wave_table( *p->wtbH_ptr, p->wtb_instr_idx, d0,d1 )) == nullptr )
|
|
||||||
{
|
|
||||||
cwLogWarning("No piano voice for pitch:%i vel:%i",m->d0,m->d1);
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
p->done_fl = false;
|
|
||||||
p->gain = 1;
|
|
||||||
p->gain_coeff = 1;
|
|
||||||
|
|
||||||
for(unsigned i=0; i<kChCnt; ++i)
|
|
||||||
{
|
|
||||||
p->osc[i].ch = p->wt->chA + i;
|
|
||||||
p->osc[i].seg_idx = 0;
|
|
||||||
p->osc[i].smp_idx = 0;
|
|
||||||
p->osc[i].seg_cnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("%i non: %i %i (%i,%i)\n",proc->label_sfx_id,m->d0,m->d1,d0,d1);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
_on_note_off(p);
|
||||||
p->gain_coeff = p->kReleaseGain;
|
|
||||||
//printf("%i nof: %i %i\n",proc->label_sfx_id,m->d0,m->d1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case midi::kNoteOffMdId:
|
case midi::kNoteOffMdId:
|
||||||
p->gain_coeff = p->kReleaseGain;
|
_on_note_off(p);
|
||||||
//printf("%i nof: %i %i\n",proc->label_sfx_id,m->d0,m->d1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case midi::kPbendMdId:
|
case midi::kPbendMdId:
|
||||||
@ -4707,71 +4735,23 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the voice is off then zero the audio buffer
|
if((rc = process( &p->osc, abuf->buf, abuf->chN, abuf->frameN, actualFrmN )) != kOkRC )
|
||||||
if( p->done_fl )
|
|
||||||
{
|
{
|
||||||
vop::zero(abuf->buf,abuf->frameN);
|
goto errLabel;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
// for each channel
|
vop::mul(abuf->buf, p->gain, abuf->chN * abuf->frameN);
|
||||||
for(unsigned i=0; i<kChCnt; ++i)
|
|
||||||
{
|
|
||||||
// for the output buffer
|
|
||||||
sample_t* yV = abuf->buf + i*abuf->frameN;
|
|
||||||
unsigned yi = 0;
|
|
||||||
|
|
||||||
// get this channels oscillator
|
p->gain *= p->gain_coeff;
|
||||||
osc_state_t* osc = p->osc + i;
|
|
||||||
|
|
||||||
// for each sample in the output buffer
|
|
||||||
while(yi < abuf->frameN)
|
|
||||||
{
|
|
||||||
// locate the current wavetable
|
|
||||||
wt_bank::seg_t* seg = p->wt->chA[i].segA + osc->seg_idx;
|
|
||||||
unsigned n;
|
|
||||||
|
|
||||||
if( seg->aN - osc->smp_idx > abuf->frameN-yi )
|
|
||||||
n = abuf->frameN-yi;
|
|
||||||
else
|
|
||||||
n = seg->aN - osc->smp_idx;
|
|
||||||
|
|
||||||
vop::mul( yV + yi, seg->aV + seg->padN + osc->smp_idx, p->gain, n );
|
|
||||||
|
|
||||||
yi += n;
|
|
||||||
osc->smp_idx += n;
|
|
||||||
|
|
||||||
if( osc->smp_idx >= seg->aN )
|
|
||||||
{
|
|
||||||
osc->smp_idx = 0;
|
|
||||||
|
|
||||||
osc->seg_cnt += 1;
|
|
||||||
|
|
||||||
// if this is the second time through the loop segment
|
|
||||||
// then begin applying the sustain decay
|
|
||||||
if( osc->seg_cnt == 2 )
|
|
||||||
p->gain_coeff = p->kSustainGain;
|
|
||||||
|
|
||||||
if( osc->seg_idx < osc->ch->segN-1 )
|
|
||||||
osc->seg_idx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p->gain *= p->gain_coeff;
|
|
||||||
|
|
||||||
if( p->gain < p->kGainThreshold && !p->done_fl )
|
if( (p->gain < p->kGainThreshold && !p->done_fl) || (actualFrmN < abuf->frameN) )
|
||||||
{
|
{
|
||||||
//printf("done:\n");
|
var_set(proc,kDoneFlPId,kAnyChIdx,true);
|
||||||
var_set(proc,kDoneFlPId,kAnyChIdx,true);
|
p->done_fl = true;
|
||||||
p->done_fl = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _report( proc_t* proc, inst_t* p )
|
rc_t _report( proc_t* proc, inst_t* p )
|
||||||
@ -4786,7 +4766,6 @@ namespace cw
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -30,7 +30,7 @@ namespace cw
|
|||||||
namespace audio_marker { extern class_members_t members; }
|
namespace audio_marker { extern class_members_t members; }
|
||||||
namespace xfade_ctl { extern class_members_t members; }
|
namespace xfade_ctl { extern class_members_t members; }
|
||||||
namespace midi_voice { extern class_members_t members; }
|
namespace midi_voice { extern class_members_t members; }
|
||||||
//namespace piano_voice { extern class_members_t members; }
|
namespace piano_voice { extern class_members_t members; }
|
||||||
namespace poly_voice_ctl { extern class_members_t members; }
|
namespace poly_voice_ctl { extern class_members_t members; }
|
||||||
namespace sample_hold { extern class_members_t members; }
|
namespace sample_hold { extern class_members_t members; }
|
||||||
namespace number { extern class_members_t members; }
|
namespace number { extern class_members_t members; }
|
||||||
|
Loading…
Reference in New Issue
Block a user