This commit is contained in:
kevin 2022-11-11 14:05:49 -05:00
commit 7b01e1aaec
15 changed files with 512 additions and 55 deletions

View File

@ -67,6 +67,9 @@ libcwSRC += src/libcw/cwIoMidiRecordPlay.cpp src/libcw/cwIoAudioRecordPlay.cpp
libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h
libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp
# libcwHDR += src/libcw/cwCmInterface.h src/libcw/cwScoreFollower.h
# libcwSRC += src/libcw/cwCmInterface.cpp src/libcw/cwScoreFollower.cpp
endif endif

110
cwCmInterface.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "cwCommon.h"
#include "cwLog.h"
#include "cwCommonImpl.h"
#include "cwMem.h"
#include "cwCmInterface.h"
#include "cmGlobal.h"
#include "cmFloatTypes.h"
#include "cmRpt.h"
#include "cmErr.h"
#include "cmCtx.h"
#include "cmMem.h"
#include "cmMallocDebug.h"
#include "cmLinkedHeap.h"
#include "cmTime.h"
#include "cmMidi.h"
#include "cmSymTbl.h"
#include "cmScore.h"
#include "cmText.h"
#include "cmFileSys.h"
extern "C" {
void _cm_print_info( void* arg, const char* text )
{
cwLogInfo(text);
}
void _cm_print_error( void* arg, const char* text )
{
cwLogError(cw::kOpFailRC,text);
}
}
namespace cw
{
namespace cm
{
typedef struct cm_str
{
::cmCtx_t ctx;
} cm_t;
cm_t* _handleToPtr( handle_t h )
{ return handleToPtr<handle_t,cm_t>(h); }
rc_t _destroy( cm_t* p )
{
if( p != nullptr )
{
cmTsFinalize();
cmFsFinalize();
cmMdReport( kIgnoreNormalMmFl );
cmMdFinalize();
mem::release(p);
}
return kOkRC;
}
}
}
cw::rc_t cw::cm::create( handle_t& hRef )
{
rc_t rc = kOkRC;
cm_t* p = nullptr;
bool memDebugFl = 0; //cmDEBUG_FL;
unsigned memGuardByteCnt = memDebugFl ? 8 : 0;
unsigned memAlignByteCnt = 16;
unsigned memFlags = memDebugFl ? kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl : 0;
const cmChar_t* appTitle = "cwtest";
if((rc = destroy(hRef)) != kOkRC )
return rc;
p = mem::allocZ<cm_t>();
cmCtxSetup(&p->ctx,appTitle,_cm_print_info,_cm_print_error,NULL,memGuardByteCnt,memAlignByteCnt,memFlags);
cmMdInitialize( memGuardByteCnt, memAlignByteCnt, memFlags, &p->ctx.rpt );
cmFsInitialize( &p->ctx, appTitle);
cmTsInitialize( &p->ctx );
return rc;
}
cw::rc_t cw::cm::destroy( handle_t& hRef )
{
rc_t rc = kOkRC;
cm_t* p = nullptr;
if( !hRef.isValid() )
return rc;
p = _handleToPtr(hRef);
if((rc = _destroy(p)) != kOkRC )
return rc;
hRef.clear();
return rc;
}
::cmCtx_t* cw::cm::context( handle_t h )
{
cm_t* p = _handleToPtr(h);
return &p->ctx;
}

19
cwCmInterface.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef cwCmInterface_h
#define cwCmInterface_h
namespace cw
{
namespace cm {
extern "C" { struct cmCtx_str; }
typedef handle< struct cm_str > handle_t;
rc_t create( handle_t& hRef );
rc_t destroy( handle_t& hRef );
::cmCtx_t* context( handle_t h );
}
}
#endif

View File

@ -137,6 +137,7 @@ namespace cw
const char* type_str = nullptr; const char* type_str = nullptr;
unsigned type_flag = 0; unsigned type_flag = 0;
bool srcVarFl = false; bool srcVarFl = false;
bool srcOptFl = false;
var_desc_t* vd = mem::allocZ<var_desc_t>(); var_desc_t* vd = mem::allocZ<var_desc_t>();
vd->label = var_obj->pair_label(); vd->label = var_obj->pair_label();
@ -158,7 +159,9 @@ namespace cw
} }
// get the variable description // get the variable description
if((rc = vd->cfg->getv_opt("srcFl", srcVarFl,"value",vd->val_cfg)) != kOkRC ) if((rc = vd->cfg->getv_opt("srcFl", srcVarFl,
"srcOptFl", srcOptFl,
"value",vd->val_cfg)) != kOkRC )
{ {
rc = cwLogError(rc,"Parsing optional fields failed on class:%s variable: '%s'.", cd->label, vd->label ); rc = cwLogError(rc,"Parsing optional fields failed on class:%s variable: '%s'.", cd->label, vd->label );
goto errLabel; goto errLabel;
@ -168,9 +171,10 @@ namespace cw
vd->type |= type_flag; vd->type |= type_flag;
if( srcVarFl ) if( srcVarFl )
{
vd->flags |= kSrcVarFl; vd->flags |= kSrcVarFl;
}
if( srcOptFl )
vd->flags |= kSrcOptVarFl;
vd->link = cd->varDescL; vd->link = cd->varDescL;
cd->varDescL = vd; cd->varDescL = vd;

View File

@ -564,7 +564,7 @@ namespace cw
// print a minutes counter // print a minutes counter
inst->durSmpN += src_abuf->frameN; inst->durSmpN += src_abuf->frameN;
if( inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 ) if( inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 )
printf("%5.1f min\n", inst->durSmpN/(src_abuf->srate*60)); printf("audio file out: %5.1f min\n", inst->durSmpN/(src_abuf->srate*60));
} }
@ -982,35 +982,64 @@ namespace cw
namespace audio_merge namespace audio_merge
{ {
enum { enum {
kIn0PId,
kIn1PId,
kGainPId, kGainPId,
kOutPId, kOutPId,
kInBasePId,
}; };
typedef struct typedef struct
{ {
unsigned srcN;
} inst_t; } inst_t;
rc_t create( instance_t* ctx ) rc_t create( instance_t* ctx )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
const abuf_t* abuf0 = nullptr; //
const abuf_t* abuf1 = nullptr;
unsigned outChN = 0; unsigned outChN = 0;
unsigned frameN = 0;
srate_t srate = 0;
inst_t* inst = mem::allocZ<inst_t>();
ctx->userPtr = inst;
for(unsigned i=0; 1; ++i)
{
const abuf_t* abuf = nullptr; //
char label[32];
snprintf(label,31,"in%i",i);
label[31] = 0;
// TODO: allow non-contiguous source labels
// the source labels must be contiguous
if( !var_has_value( ctx, label, kAnyChIdx ) )
break;
// get the source audio buffer // get the source audio buffer
if((rc = var_register_and_get(ctx, kAnyChIdx, if((rc = var_register_and_get(ctx, kAnyChIdx,kInBasePId+i,label,abuf )) != kOkRC )
kIn0PId,"in0",abuf0,
kIn1PId,"in1",abuf1 )) != kOkRC )
{ {
goto errLabel; goto errLabel;
} }
assert( abuf0->frameN == abuf1->frameN ); if( i == 0 )
{
frameN = abuf->frameN;
srate = abuf->srate;
}
else
{
// TODO: check srate and frameN are same as first src
}
outChN = abuf0->chN + abuf1->chN; inst->srcN += 1;
outChN += abuf->chN;
}
//outChN = abuf0->chN + abuf1->chN;
// register the gain // register the gain
for(unsigned i=0; i<outChN; ++i) for(unsigned i=0; i<outChN; ++i)
@ -1018,14 +1047,20 @@ namespace cw
goto errLabel; goto errLabel;
// create the output audio buffer // create the output audio buffer
rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, abuf0->srate, outChN, abuf0->frameN ); rc = var_register_and_set( ctx, "out", kOutPId, kAnyChIdx, srate, outChN, frameN );
errLabel: errLabel:
return rc; return rc;
} }
rc_t destroy( instance_t* ctx ) rc_t destroy( instance_t* ctx )
{ return kOkRC; } {
inst_t* inst = (inst_t*)ctx->userPtr;
mem::release(inst);
return kOkRC;
}
rc_t value( instance_t* ctx, variable_t* var ) rc_t value( instance_t* ctx, variable_t* var )
{ return kOkRC; } { return kOkRC; }
@ -1052,6 +1087,7 @@ namespace cw
return outChIdx; return outChIdx;
} }
/*
rc_t exec( instance_t* ctx ) rc_t exec( instance_t* ctx )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -1074,6 +1110,31 @@ namespace cw
assert( oChIdx == obuf->chN ); assert( oChIdx == obuf->chN );
errLabel:
return rc;
}
*/
rc_t exec( instance_t* ctx )
{
rc_t rc = kOkRC;
inst_t* inst = (inst_t*)ctx->userPtr;
abuf_t* obuf = nullptr;
unsigned oChIdx = 0;
if((rc = var_get(ctx,kOutPId, kAnyChIdx, obuf)) != kOkRC )
goto errLabel;
for(unsigned i=0; i<inst->srcN; ++i)
{
const abuf_t* ibuf = nullptr;
if((rc = var_get(ctx,kInBasePId+i, kAnyChIdx, ibuf )) != kOkRC )
goto errLabel;
oChIdx = _exec( ctx, ibuf, obuf, oChIdx );
}
errLabel: errLabel:
return rc; return rc;
} }
@ -1088,6 +1149,7 @@ namespace cw
} }
//------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------
// //
// audio_mix // audio_mix

View File

@ -1013,9 +1013,10 @@ void cw::flow::class_dict_print( flow_t* p )
for(; vd!=nullptr; vd=vd->link) for(; vd!=nullptr; vd=vd->link)
{ {
const char* srcFlStr = vd->flags&kSrcVarFl ? "src" : " "; const char* srcFlStr = vd->flags & kSrcVarFl ? "src" : " ";
const char* srcOptFlStr = vd->flags & kSrcOptVarFl ? "srcOpt" : " ";
printf(" %10s 0x%08x %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, cwStringNullGuard(vd->docText) ); printf(" %10s 0x%08x %s %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, srcOptFlStr, cwStringNullGuard(vd->docText) );
} }
} }
} }
@ -1162,6 +1163,17 @@ cw::rc_t cw::flow::var_channelize( instance_t* inst, const char* var_label, uns
bool cw::flow::var_exists( instance_t* inst, const char* label, unsigned chIdx ) bool cw::flow::var_exists( instance_t* inst, const char* label, unsigned chIdx )
{ return _var_find_on_label_and_ch(inst,label,chIdx) != nullptr; } { return _var_find_on_label_and_ch(inst,label,chIdx) != nullptr; }
bool cw::flow::var_has_value( instance_t* inst, const char* label, unsigned chIdx )
{
variable_t* varPtr = nullptr;
rc_t rc;
if((rc = var_find( inst, label, chIdx, varPtr )) != kOkRC )
return false;
return varPtr->value != nullptr;
}
cw::rc_t cw::flow::var_find( instance_t* inst, unsigned vid, unsigned chIdx, variable_t*& varRef ) cw::rc_t cw::flow::var_find( instance_t* inst, unsigned vid, unsigned chIdx, variable_t*& varRef )
{ {

View File

@ -115,7 +115,9 @@ namespace cw
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
}; };
typedef struct class_members_str typedef struct class_members_str
@ -397,6 +399,7 @@ namespace cw
void _var_destroy( variable_t* var ); void _var_destroy( variable_t* var );
bool var_exists( instance_t* inst, const char* label, unsigned chIdx ); bool var_exists( instance_t* inst, const char* label, unsigned chIdx );
bool var_has_value( instance_t* inst, const char* label, unsigned chIdx );
rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, const variable_t*& varRef ); rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, const variable_t*& varRef );
rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, variable_t*& varRef ); rc_t var_find( instance_t* inst, const char* var_label, unsigned chIdx, variable_t*& varRef );

View File

@ -404,6 +404,7 @@ namespace cw
return rc; return rc;
} }
rc_t _transmit_msg( midi_record_play_t* p, const am_midi_msg_t* am, bool log_fl=true ) rc_t _transmit_msg( midi_record_play_t* p, const am_midi_msg_t* am, bool log_fl=true )
{ {
return _event_callback( p, am->id, am->timestamp, am->loc, am->ch, am->status, am->d0, am->d1, log_fl ); return _event_callback( p, am->id, am->timestamp, am->loc, am->ch, am->status, am->d0, am->d1, log_fl );
@ -552,7 +553,7 @@ namespace cw
unsigned fileByteN = 0; // count of bytes in the file unsigned fileByteN = 0; // count of bytes in the file
int version = 0; // version id (always a negative number) int version = 0; // version id (always a negative number)
bool alloc_fl = false; bool alloc_fl = false;
bool print_fl = true; bool print_fl = false;
file::handle_t fH; file::handle_t fH;
if((rc = file::open(fH,fn,file::kReadFl)) != kOkRC ) if((rc = file::open(fH,fn,file::kReadFl)) != kOkRC )
@ -607,6 +608,7 @@ namespace cw
} }
else else
{ {
fileByteN = recordN * sizeof(am_midi_msg_t);
if((rc = file::read(fH,msgArrayRef,fileByteN)) != kOkRC ) if((rc = file::read(fH,msgArrayRef,fileByteN)) != kOkRC )
{ {
rc = cwLogError(kReadFailRC,"Data read failed on Audio-MIDI file: '%s'.", fn ); rc = cwLogError(kReadFailRC,"Data read failed on Audio-MIDI file: '%s'.", fn );
@ -1445,6 +1447,20 @@ void cw::midi_record_play::enable_device( handle_t h, unsigned devIdx, bool enab
} }
} }
cw::rc_t cw::midi_record_play::send_midi_msg( handle_t h, unsigned devIdx, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1 )
{
midi_record_play_t* p = _handleToPtr(h);
if( devIdx >= p->midiDevN )
return cwLogError(kInvalidArgRC,"The MIDI record-play device index '%i' is invalid.",devIdx );
if( p->midiDevA[devIdx].enableFl )
io::midiDeviceSend( p->ioH, p->midiDevA[devIdx].midiOutDevIdx, p->midiDevA[devIdx].midiOutPortIdx, status + ch, d0, d1 );
return kOkRC;
}
void cw::midi_record_play::half_pedal_params( handle_t h, unsigned noteDelayMs, unsigned pitch, unsigned vel, unsigned pedal_vel, unsigned noteDurMs, unsigned downDelayMs ) void cw::midi_record_play::half_pedal_params( handle_t h, unsigned noteDelayMs, unsigned pitch, unsigned vel, unsigned pedal_vel, unsigned noteDurMs, unsigned downDelayMs )
{ {
midi_record_play_t* p = _handleToPtr(h); midi_record_play_t* p = _handleToPtr(h);

View File

@ -66,6 +66,7 @@ namespace cw
unsigned device_count( handle_t h ); unsigned device_count( handle_t h );
bool is_device_enabled( handle_t h, unsigned devIdx ); bool is_device_enabled( handle_t h, unsigned devIdx );
void enable_device( handle_t h, unsigned devIdx, bool enableFl ); void enable_device( handle_t h, unsigned devIdx, bool enableFl );
rc_t send_midi_msg( handle_t h, unsigned devIdx, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1 );
void half_pedal_params( handle_t h, unsigned noteDelayMs, unsigned pitch, unsigned vel, unsigned pedal_vel, unsigned noteDurMs, unsigned downDelayMs ); void half_pedal_params( handle_t h, unsigned noteDelayMs, unsigned pitch, unsigned vel, unsigned pedal_vel, unsigned noteDurMs, unsigned downDelayMs );

View File

@ -40,6 +40,7 @@ namespace cw
kStartBtnId, kStartBtnId,
kStopBtnId, kStopBtnId,
kLiveCheckId,
kPrintMidiCheckId, kPrintMidiCheckId,
kPianoMidiCheckId, kPianoMidiCheckId,
@ -105,8 +106,8 @@ namespace cw
enum enum
{ {
kPiano_MRP_DevIdx = 0, kPiano_MRP_DevIdx = 1,
kSampler_MRP_DevIdx = 1 kSampler_MRP_DevIdx = 0
}; };
enum enum
@ -126,6 +127,7 @@ namespace cw
{ kPanelDivId, kStartBtnId, "startBtnId" }, { kPanelDivId, kStartBtnId, "startBtnId" },
{ kPanelDivId, kStopBtnId, "stopBtnId" }, { kPanelDivId, kStopBtnId, "stopBtnId" },
{ kPanelDivId, kLiveCheckId, "liveCheckId" },
{ kPanelDivId, kPrintMidiCheckId, "printMidiCheckId" }, { kPanelDivId, kPrintMidiCheckId, "printMidiCheckId" },
{ kPanelDivId, kPianoMidiCheckId, "pianoMidiCheckId" }, { kPanelDivId, kPianoMidiCheckId, "pianoMidiCheckId" },
@ -209,6 +211,7 @@ namespace cw
const object_t* midi_play_record_cfg; const object_t* midi_play_record_cfg;
const object_t* frag_panel_cfg; const object_t* frag_panel_cfg;
const object_t* presets_cfg; const object_t* presets_cfg;
object_t* flow_proc_dict;
const object_t* flow_cfg; const object_t* flow_cfg;
midi_record_play::handle_t mrpH; midi_record_play::handle_t mrpH;
@ -250,12 +253,15 @@ namespace cw
unsigned seqFragId; // unsigned seqFragId; //
unsigned seqPresetIdx; // unsigned seqPresetIdx; //
bool useLiveMidiFl;
} app_t; } app_t;
rc_t _parseCfg(app_t* app, const object_t* cfg, const object_t*& params_cfgRef ) rc_t _parseCfg(app_t* app, const object_t* cfg, const object_t*& params_cfgRef )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
const char* flow_proc_dict_fn = nullptr;
if((rc = cfg->getv( "params", params_cfgRef, if((rc = cfg->getv( "params", params_cfgRef,
"flow", app->flow_cfg)) != kOkRC ) "flow", app->flow_cfg)) != kOkRC )
@ -268,6 +274,7 @@ namespace cw
"record_fn", app->record_fn, "record_fn", app->record_fn,
"record_fn_ext", app->record_fn_ext, "record_fn_ext", app->record_fn_ext,
"score_fn", app->scoreFn, "score_fn", app->scoreFn,
"flow_proc_dict_fn",flow_proc_dict_fn,
"midi_play_record", app->midi_play_record_cfg, "midi_play_record", app->midi_play_record_cfg,
"frag_panel", app->frag_panel_cfg, "frag_panel", app->frag_panel_cfg,
"presets", app->presets_cfg, "presets", app->presets_cfg,
@ -291,6 +298,12 @@ namespace cw
goto errLabel; goto errLabel;
} }
if((rc = objectFromFile( flow_proc_dict_fn, app->flow_proc_dict )) != kOkRC )
{
rc = cwLogError(kInvalidArgRC,"The flow proc file '%s' parse failed.",app->flow_proc_dict);
goto errLabel;
}
// verify that the output directory exists // verify that the output directory exists
if((rc = filesys::isDir(app->record_dir)) != kOkRC ) if((rc = filesys::isDir(app->record_dir)) != kOkRC )
if((rc = filesys::makeDir(app->record_dir)) != kOkRC ) if((rc = filesys::makeDir(app->record_dir)) != kOkRC )
@ -338,6 +351,9 @@ namespace cw
rc_t _free( app_t& app ) rc_t _free( app_t& app )
{ {
if( app.flow_proc_dict != nullptr )
app.flow_proc_dict->free();
mem::release((char*&)app.record_dir); mem::release((char*&)app.record_dir);
mem::release((char*&)app.scoreFn); mem::release((char*&)app.scoreFn);
preset_sel::destroy(app.psH); preset_sel::destroy(app.psH);
@ -475,6 +491,46 @@ namespace cw
} }
} }
rc_t _on_live_midi( app_t* app, const io::msg_t& msg )
{
rc_t rc = kOkRC;
if( msg.u.midi != nullptr )
{
const io::midi_msg_t& m = *msg.u.midi;
const midi::packet_t* pkt = m.pkt;
// for each midi msg
for(unsigned j=0; j<pkt->msgCnt; ++j)
{
// if this is a sys-ex msg
if( pkt->msgArray == NULL )
{
cwLogError(kNotImplementedRC,"Sys-ex recording not implemented.");
}
else // this is a triple
{
midi::msg_t* mm = pkt->msgArray + j;
time::spec_t timestamp;
unsigned id = kInvalidId;
unsigned loc = app->beg_play_loc;
time::get(timestamp);
if( midi::isChStatus(mm->status) )
{
if(midi_record_play::send_midi_msg( app->mrpH, kSampler_MRP_DevIdx, mm->status & 0x0f, mm->status & 0xf0, mm->d0, mm->d1 ) == kOkRC )
_midi_play_callback( app, midi_record_play::kMidiEventActionId, id, timestamp, loc, mm->status & 0x0f, mm->status & 0xf0, mm->d0, mm->d1 );
}
}
}
}
return rc;
}
// Find the closest locMap equal to or after 'loc' // Find the closest locMap equal to or after 'loc'
loc_map_t* _find_loc( app_t* app, unsigned loc ) loc_map_t* _find_loc( app_t* app, unsigned loc )
{ {
@ -542,7 +598,7 @@ namespace cw
app->end_play_timestamp = endMap->timestamp; app->end_play_timestamp = endMap->timestamp;
if( !time::isZero(app->beg_play_timestamp) ) if( !time::isZero(app->beg_play_timestamp) && !app->useLiveMidiFl )
{ {
// seek the player to the requested loc // seek the player to the requested loc
if((rc = midi_record_play::seek( app->mrpH, app->beg_play_timestamp )) != kOkRC ) if((rc = midi_record_play::seek( app->mrpH, app->beg_play_timestamp )) != kOkRC )
@ -554,13 +610,15 @@ namespace cw
} }
// apply the preset which is active at the start time // apply the preset which is active at the start time
if((rc = _apply_preset( app, app->beg_play_timestamp, app->beg_play_loc )) != kOkRC ) if((rc = _apply_preset( app, app->beg_play_timestamp, begMap->loc )) != kOkRC )
{ {
rc = cwLogError(rc,"Preset application failed prior to MIDI start."); rc = cwLogError(rc,"Preset application failed prior to MIDI start.");
goto errLabel; goto errLabel;
} }
// start the MIDI playback // start the MIDI playback
if( !app->useLiveMidiFl )
{
if((rc = midi_record_play::start(app->mrpH,rewindFl,&app->end_play_timestamp)) != kOkRC ) if((rc = midi_record_play::start(app->mrpH,rewindFl,&app->end_play_timestamp)) != kOkRC )
{ {
rc = cwLogError(rc,"MIDI start failed."); rc = cwLogError(rc,"MIDI start failed.");
@ -571,6 +629,7 @@ namespace cw
{ {
io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc ); io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc );
} }
}
errLabel: errLabel:
return rc; return rc;
@ -1211,19 +1270,21 @@ namespace cw
// set the range of the global play location controls // set the range of the global play location controls
if( firstLoadFl ) if( firstLoadFl )
{ {
unsigned minLocUuId = io::uiFindElementUuId(app->ioH, kBegPlayLocNumbId); unsigned begPlayLocUuId = io::uiFindElementUuId(app->ioH, kBegPlayLocNumbId);
unsigned maxLocUuId = io::uiFindElementUuId(app->ioH, kEndPlayLocNumbId); unsigned endPlayLocUuId = io::uiFindElementUuId(app->ioH, kEndPlayLocNumbId);
//unsigned end_loc = app->end_play_loc==0 ? app->maxLoc : app->end_play_loc;
//unsigned beg_loc = app->minLoc <= app->beg_play_loc && app->beg_play_loc <= app->maxLoc ? app->beg_play_loc : app->minLoc;
io::uiSetNumbRange( app->ioH, minLocUuId, app->minLoc, app->maxLoc, 1, 0, app->minLoc ); unsigned end_play_loc = app->end_play_loc==0 ? app->maxLoc : app->end_play_loc;
io::uiSetNumbRange( app->ioH, maxLocUuId, app->minLoc, app->maxLoc, 1, 0, app->maxLoc ); unsigned beg_play_loc = app->minLoc <= app->beg_play_loc && app->beg_play_loc <= app->maxLoc ? app->beg_play_loc : app->minLoc;
//io::uiSendValue( app->ioH, minLocUuId, std::max(beg_loc,app->minLoc)); io::uiSetNumbRange( app->ioH, begPlayLocUuId, app->minLoc, app->maxLoc, 1, 0, app->minLoc );
//io::uiSendValue( app->ioH, maxLocUuId, std::min(end_loc,app->maxLoc)); io::uiSetNumbRange( app->ioH, endPlayLocUuId, app->minLoc, app->maxLoc, 1, 0, app->maxLoc );
io::uiSendValue( app->ioH, minLocUuId, app->minLoc); //io::uiSendValue( app->ioH, begPlayLocUuId, app->minLoc);
io::uiSendValue( app->ioH, maxLocUuId, app->maxLoc); //io::uiSendValue( app->ioH, endPlayLocUuId, app->maxLoc);
io::uiSendValue( app->ioH, begPlayLocUuId, beg_play_loc);
io::uiSendValue( app->ioH, endPlayLocUuId, end_play_loc);
// enable the 'End Loc' number box since the score is loaded // enable the 'End Loc' number box since the score is loaded
@ -1236,6 +1297,7 @@ namespace cw
// enable the start/stop buttons // enable the start/stop buttons
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), true );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), true );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), true );
// restore the fragment records // restore the fragment records
if( firstLoadFl ) if( firstLoadFl )
@ -1570,6 +1632,7 @@ namespace cw
// disable start and stop buttons until a score is loaded // disable start and stop buttons until a score is loaded
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), false ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStartBtnId ), false );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), false ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kStopBtnId ), false );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), false );
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), false ); io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), false );
const preset_sel::frag_t* f = preset_sel::get_fragment_base( app->psH ); const preset_sel::frag_t* f = preset_sel::get_fragment_base( app->psH );
@ -1628,6 +1691,10 @@ namespace cw
_do_stop_play(app); _do_stop_play(app);
break; break;
case kLiveCheckId:
app->useLiveMidiFl = m.value->u.b;
break;
case kPrintMidiCheckId: case kPrintMidiCheckId:
app->printMidiFl = m.value->u.b; app->printMidiFl = m.value->u.b;
break; break;
@ -1899,7 +1966,7 @@ namespace cw
rc_t rc = kOkRC; rc_t rc = kOkRC;
app_t* app = reinterpret_cast<app_t*>(arg); app_t* app = reinterpret_cast<app_t*>(arg);
if( app->mrpH.isValid() ) if( app->mrpH.isValid() && !app->useLiveMidiFl )
{ {
midi_record_play::exec( app->mrpH, *m ); midi_record_play::exec( app->mrpH, *m );
if( midi_record_play::is_started(app->mrpH) ) if( midi_record_play::is_started(app->mrpH) )
@ -1928,6 +1995,8 @@ namespace cw
break; break;
case io::kMidiTId: case io::kMidiTId:
if( app->useLiveMidiFl && app->mrpH.isValid() )
_on_live_midi( app, *m );
break; break;
case io::kAudioTId: case io::kAudioTId:
@ -1959,7 +2028,7 @@ namespace cw
} }
cw::rc_t cw::preset_sel_app::main( const object_t* cfg, const object_t* flow_proc_dict ) cw::rc_t cw::preset_sel_app::main( const object_t* cfg )
{ {
rc_t rc; rc_t rc;
@ -1994,7 +2063,7 @@ cw::rc_t cw::preset_sel_app::main( const object_t* cfg, const object_t* flow_pro
} }
// create the IO Flow controller // create the IO Flow controller
if(app.flow_cfg==nullptr || flow_proc_dict==nullptr || (rc = io_flow::create(app.ioFlowH,app.ioH,app.crossFadeSrate,app.crossFadeCnt,*flow_proc_dict,*app.flow_cfg)) != kOkRC ) if(app.flow_cfg==nullptr || app.flow_proc_dict==nullptr || (rc = io_flow::create(app.ioFlowH,app.ioH,app.crossFadeSrate,app.crossFadeCnt,*app.flow_proc_dict,*app.flow_cfg)) != kOkRC )
{ {
rc = cwLogError(rc,"The IO Flow controller create failed."); rc = cwLogError(rc,"The IO Flow controller create failed.");
goto errLabel; goto errLabel;

View File

@ -5,7 +5,7 @@ namespace cw
{ {
namespace preset_sel_app namespace preset_sel_app
{ {
rc_t main( const object_t* cfg, const object_t* flow_proc_dict ); rc_t main( const object_t* cfg );
} }
} }

View File

@ -134,11 +134,17 @@ namespace cw
// if no input // if no input
if( rc == -EAGAIN ) if( rc == -EAGAIN )
{
// TODO: report or at least count error
break; break;
}
// if input buffer overrun // if input buffer overrun
if( rc == -ENOSPC ) if( rc == -ENOSPC )
{
// TODO: report or at least count error
break; break;
}
// get the device this event arrived from // get the device this event arrived from
if( p->prvRcvDev==NULL || p->prvRcvDev->clientId != ev->source.client ) if( p->prvRcvDev==NULL || p->prvRcvDev->clientId != ev->source.client )

130
cwScoreFollower.cpp Normal file
View File

@ -0,0 +1,130 @@
#include "cwCommon.h"
#include "cwLog.h"
#include "cwCommonImpl.h"
#include "cwMem.h"
#include "cwText.h"
#include "cwObject.h"
#include "cwMidi.h"
#include "cwScoreFollower.h"
#include "cmGlobal.h"
#include "cmFloatTypes.h"
#include "cmRpt.h"
#include "cmErr.h"
#include "cmCtx.h"
#include "cmTime.h"
#include "cmMidi.h"
#include "cmSymTbl.h"
#include "cmScore.h"
namespace cw
{
namespace score_follower
{
typedef struct score_follower_str
{
unsigned search_area_locN;
unsigned key_wnd_locN;
char* score_csv_fname;
} score_follower_t;
score_follower_t* _handleToPtr( handle_t h )
{ return handleToPtr<handle_t,score_follower_t>(h); }
rc_t _parse_cfg( score_follower_t* p, const object_t* cfg )
{
rc_t rc = kOkRC;
const char* score_csv_fname;
if((rc = cfg->getv("score_csv_fname", score_csv_fname,
"search_area_locN", p->search_area_locN,
"key_wnd_locN", p->key_wnd_locN )) != kOkRC )
{
rc = cwLogError(kInvalidArgRC, "Score follower argument parsing failed.");
goto errLabel;
}
if((app->score_csv_fname = filesys::expandPath( score_csv_fname )) == nullptr )
{
rc = cwLogError(kOpFailRC,"Score follower score file expansion failed.");
goto errLabel;
}
errLabel:
return rc;
}
rc_t _destroy( score_follower_t* p)
{
mem::release(p->score_csv_fname);
mem::release(p);
return kOkRC;
}
}
}
cw::rc_t cw::score_follower::create( handle_t& hRef, const object_t* cfg, double srate )
{
rc_t rc = kOkRC;
score_follower_t* p = nullptr;
if((rc = destroy(hRef)) != kOkRC )
return rc;
p = mem::allocZ<score_follower_t>();
if((rc = _parse_cfg(p,cfg)) != kOkRC )
goto errLabel;
cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, double srate, const unsigned* dynRefArray, unsigned dynRefCnt, cmScCb_t cbFunc, void* cbArg, cmSymTblH_t stH );
//cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg );
hRef.set(p);
errLabel:
if( rc != kOkRC )
{
_destroy(p);
cwLogError(rc,"Score follower create failed.");
}
return rc;
}
cw::rc_t cw::score_follower::destroy( handle_t& hRef )
{
rc_t rc = kOkRC;
score_follower_t* p = nullptr;
if( !hRef.isValid() )
return rc;
p = _handleToPtr(hRef);
if((rc = _destroy(p)) != kOkRC )
return rc;
hRef.clear();
return rc;
}
cw::rc_t cw::score_follower::reset( handle_t h, unsigned loc )
{
rc_t rc = kOkRC;
return rc;
}
cw::rc_t cw::score_follower::exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, uint8_t d0, uint8_t d1, unsigned* scLocIdxPtr )
{
rc_t rc = kOkRC;
return rc;
}

21
cwScoreFollower.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef cwScoreFollower_h
#define cwScoreFollower_h
namespace cw
{
namespace score_follower
{
typedef handle< struct score_follower_str > handle_t;
rc_t create( handle_t& hRef, const object_t* cfg, double srate );
rc_t destroy( handle_t& hRef );
rc_t reset( handle_t h, unsigned loc );
rc_t exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, uint8_t d0, uint8_t d1, unsigned* scLocIdxPtr );
}
}
#endif

View File

@ -34,6 +34,7 @@
button:{ name: stopBtnId, title:"Stop" }, button:{ name: stopBtnId, title:"Stop" },
number:{ name: begLocNumbId, title:"Loc:", min:0, max:100000, step:1, decpl:0 }, number:{ name: begLocNumbId, title:"Loc:", min:0, max:100000, step:1, decpl:0 },
number:{ name: endLocNumbId, title:"End:", min:0, max:100000, step:1, decpl:0 }, number:{ name: endLocNumbId, title:"End:", min:0, max:100000, step:1, decpl:0 },
check: { name: liveCheckId, title:"Live" },
}, },
row: { row: {