Merge branch 'master' of https://gitea.larke.org/kevin/libcw
This commit is contained in:
commit
7b01e1aaec
@ -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
|
||||
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
|
||||
|
||||
|
||||
|
110
cwCmInterface.cpp
Normal file
110
cwCmInterface.cpp
Normal 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
19
cwCmInterface.h
Normal 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
|
10
cwFlow.cpp
10
cwFlow.cpp
@ -137,6 +137,7 @@ namespace cw
|
||||
const char* type_str = nullptr;
|
||||
unsigned type_flag = 0;
|
||||
bool srcVarFl = false;
|
||||
bool srcOptFl = false;
|
||||
var_desc_t* vd = mem::allocZ<var_desc_t>();
|
||||
|
||||
vd->label = var_obj->pair_label();
|
||||
@ -158,7 +159,9 @@ namespace cw
|
||||
}
|
||||
|
||||
// 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 );
|
||||
goto errLabel;
|
||||
@ -168,9 +171,10 @@ namespace cw
|
||||
vd->type |= type_flag;
|
||||
|
||||
if( srcVarFl )
|
||||
{
|
||||
vd->flags |= kSrcVarFl;
|
||||
}
|
||||
|
||||
if( srcOptFl )
|
||||
vd->flags |= kSrcOptVarFl;
|
||||
|
||||
vd->link = cd->varDescL;
|
||||
cd->varDescL = vd;
|
||||
|
@ -564,7 +564,7 @@ namespace cw
|
||||
// print a minutes counter
|
||||
inst->durSmpN += src_abuf->frameN;
|
||||
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
|
||||
{
|
||||
enum {
|
||||
kIn0PId,
|
||||
kIn1PId,
|
||||
kGainPId,
|
||||
kOutPId,
|
||||
kInBasePId,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned srcN;
|
||||
} inst_t;
|
||||
|
||||
|
||||
rc_t create( instance_t* ctx )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const abuf_t* abuf0 = nullptr; //
|
||||
const abuf_t* abuf1 = nullptr;
|
||||
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
|
||||
if((rc = var_register_and_get(ctx, kAnyChIdx,
|
||||
kIn0PId,"in0",abuf0,
|
||||
kIn1PId,"in1",abuf1 )) != kOkRC )
|
||||
if((rc = var_register_and_get(ctx, kAnyChIdx,kInBasePId+i,label,abuf )) != kOkRC )
|
||||
{
|
||||
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
|
||||
for(unsigned i=0; i<outChN; ++i)
|
||||
@ -1018,14 +1047,20 @@ namespace cw
|
||||
goto errLabel;
|
||||
|
||||
// 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:
|
||||
return rc;
|
||||
}
|
||||
|
||||
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 )
|
||||
{ return kOkRC; }
|
||||
@ -1052,6 +1087,7 @@ namespace cw
|
||||
return outChIdx;
|
||||
}
|
||||
|
||||
/*
|
||||
rc_t exec( instance_t* ctx )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
@ -1074,6 +1110,31 @@ namespace cw
|
||||
|
||||
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:
|
||||
return rc;
|
||||
}
|
||||
@ -1088,6 +1149,7 @@ namespace cw
|
||||
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// audio_mix
|
||||
|
@ -1013,9 +1013,10 @@ void cw::flow::class_dict_print( flow_t* p )
|
||||
|
||||
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 )
|
||||
{ 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 )
|
||||
{
|
||||
|
@ -115,7 +115,9 @@ namespace cw
|
||||
typedef rc_t (*member_value_func_t)( struct instance_str* ctx, struct variable_str* var );
|
||||
enum
|
||||
{
|
||||
kSrcVarFl = 0x01
|
||||
kSrcVarFl = 0x01,
|
||||
kSrcOptVarFl = 0x02
|
||||
|
||||
};
|
||||
|
||||
typedef struct class_members_str
|
||||
@ -397,6 +399,7 @@ namespace cw
|
||||
void _var_destroy( variable_t* var );
|
||||
|
||||
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, variable_t*& varRef );
|
||||
|
@ -404,6 +404,7 @@ namespace cw
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
@ -552,7 +553,7 @@ namespace cw
|
||||
unsigned fileByteN = 0; // count of bytes in the file
|
||||
int version = 0; // version id (always a negative number)
|
||||
bool alloc_fl = false;
|
||||
bool print_fl = true;
|
||||
bool print_fl = false;
|
||||
file::handle_t fH;
|
||||
|
||||
if((rc = file::open(fH,fn,file::kReadFl)) != kOkRC )
|
||||
@ -607,6 +608,7 @@ namespace cw
|
||||
}
|
||||
else
|
||||
{
|
||||
fileByteN = recordN * sizeof(am_midi_msg_t);
|
||||
if((rc = file::read(fH,msgArrayRef,fileByteN)) != kOkRC )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
midi_record_play_t* p = _handleToPtr(h);
|
||||
|
@ -66,6 +66,7 @@ namespace cw
|
||||
unsigned device_count( handle_t h );
|
||||
bool is_device_enabled( handle_t h, unsigned devIdx );
|
||||
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 );
|
||||
|
||||
|
@ -40,6 +40,7 @@ namespace cw
|
||||
|
||||
kStartBtnId,
|
||||
kStopBtnId,
|
||||
kLiveCheckId,
|
||||
|
||||
kPrintMidiCheckId,
|
||||
kPianoMidiCheckId,
|
||||
@ -105,8 +106,8 @@ namespace cw
|
||||
|
||||
enum
|
||||
{
|
||||
kPiano_MRP_DevIdx = 0,
|
||||
kSampler_MRP_DevIdx = 1
|
||||
kPiano_MRP_DevIdx = 1,
|
||||
kSampler_MRP_DevIdx = 0
|
||||
};
|
||||
|
||||
enum
|
||||
@ -126,6 +127,7 @@ namespace cw
|
||||
|
||||
{ kPanelDivId, kStartBtnId, "startBtnId" },
|
||||
{ kPanelDivId, kStopBtnId, "stopBtnId" },
|
||||
{ kPanelDivId, kLiveCheckId, "liveCheckId" },
|
||||
|
||||
{ kPanelDivId, kPrintMidiCheckId, "printMidiCheckId" },
|
||||
{ kPanelDivId, kPianoMidiCheckId, "pianoMidiCheckId" },
|
||||
@ -209,6 +211,7 @@ namespace cw
|
||||
const object_t* midi_play_record_cfg;
|
||||
const object_t* frag_panel_cfg;
|
||||
const object_t* presets_cfg;
|
||||
object_t* flow_proc_dict;
|
||||
const object_t* flow_cfg;
|
||||
|
||||
midi_record_play::handle_t mrpH;
|
||||
@ -250,12 +253,15 @@ namespace cw
|
||||
unsigned seqFragId; //
|
||||
unsigned seqPresetIdx; //
|
||||
|
||||
bool useLiveMidiFl;
|
||||
|
||||
|
||||
} app_t;
|
||||
|
||||
rc_t _parseCfg(app_t* app, const object_t* cfg, const object_t*& params_cfgRef )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const char* flow_proc_dict_fn = nullptr;
|
||||
|
||||
if((rc = cfg->getv( "params", params_cfgRef,
|
||||
"flow", app->flow_cfg)) != kOkRC )
|
||||
@ -268,6 +274,7 @@ namespace cw
|
||||
"record_fn", app->record_fn,
|
||||
"record_fn_ext", app->record_fn_ext,
|
||||
"score_fn", app->scoreFn,
|
||||
"flow_proc_dict_fn",flow_proc_dict_fn,
|
||||
"midi_play_record", app->midi_play_record_cfg,
|
||||
"frag_panel", app->frag_panel_cfg,
|
||||
"presets", app->presets_cfg,
|
||||
@ -291,6 +298,12 @@ namespace cw
|
||||
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
|
||||
if((rc = filesys::isDir(app->record_dir)) != kOkRC )
|
||||
if((rc = filesys::makeDir(app->record_dir)) != kOkRC )
|
||||
@ -338,6 +351,9 @@ namespace cw
|
||||
|
||||
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.scoreFn);
|
||||
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'
|
||||
loc_map_t* _find_loc( app_t* app, unsigned loc )
|
||||
{
|
||||
@ -542,7 +598,7 @@ namespace cw
|
||||
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
|
||||
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
|
||||
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.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// start the MIDI playback
|
||||
if( !app->useLiveMidiFl )
|
||||
{
|
||||
if((rc = midi_record_play::start(app->mrpH,rewindFl,&app->end_play_timestamp)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"MIDI start failed.");
|
||||
@ -571,6 +629,7 @@ namespace cw
|
||||
{
|
||||
io::uiSendValue( app->ioH, uiFindElementUuId(app->ioH,kCurMidiEvtCntId), cur_loc );
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
@ -1211,19 +1270,21 @@ namespace cw
|
||||
// set the range of the global play location controls
|
||||
if( firstLoadFl )
|
||||
{
|
||||
unsigned minLocUuId = io::uiFindElementUuId(app->ioH, kBegPlayLocNumbId);
|
||||
unsigned maxLocUuId = 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;
|
||||
unsigned begPlayLocUuId = io::uiFindElementUuId(app->ioH, kBegPlayLocNumbId);
|
||||
unsigned endPlayLocUuId = io::uiFindElementUuId(app->ioH, kEndPlayLocNumbId);
|
||||
|
||||
io::uiSetNumbRange( app->ioH, minLocUuId, app->minLoc, app->maxLoc, 1, 0, app->minLoc );
|
||||
io::uiSetNumbRange( app->ioH, maxLocUuId, app->minLoc, app->maxLoc, 1, 0, app->maxLoc );
|
||||
unsigned end_play_loc = app->end_play_loc==0 ? app->maxLoc : app->end_play_loc;
|
||||
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::uiSendValue( app->ioH, maxLocUuId, std::min(end_loc,app->maxLoc));
|
||||
io::uiSetNumbRange( app->ioH, begPlayLocUuId, app->minLoc, app->maxLoc, 1, 0, app->minLoc );
|
||||
io::uiSetNumbRange( app->ioH, endPlayLocUuId, app->minLoc, app->maxLoc, 1, 0, app->maxLoc );
|
||||
|
||||
io::uiSendValue( app->ioH, minLocUuId, app->minLoc);
|
||||
io::uiSendValue( app->ioH, maxLocUuId, app->maxLoc);
|
||||
//io::uiSendValue( app->ioH, begPlayLocUuId, app->minLoc);
|
||||
//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
|
||||
@ -1236,6 +1297,7 @@ namespace cw
|
||||
// enable the start/stop buttons
|
||||
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, kLiveCheckId ), true );
|
||||
|
||||
// restore the fragment records
|
||||
if( firstLoadFl )
|
||||
@ -1570,6 +1632,7 @@ namespace cw
|
||||
// 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, kStopBtnId ), false );
|
||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kLiveCheckId ), false );
|
||||
io::uiSetEnable( app->ioH, io::uiFindElementUuId( app->ioH, kSaveBtnId ), false );
|
||||
|
||||
const preset_sel::frag_t* f = preset_sel::get_fragment_base( app->psH );
|
||||
@ -1628,6 +1691,10 @@ namespace cw
|
||||
_do_stop_play(app);
|
||||
break;
|
||||
|
||||
case kLiveCheckId:
|
||||
app->useLiveMidiFl = m.value->u.b;
|
||||
break;
|
||||
|
||||
case kPrintMidiCheckId:
|
||||
app->printMidiFl = m.value->u.b;
|
||||
break;
|
||||
@ -1899,7 +1966,7 @@ namespace cw
|
||||
rc_t rc = kOkRC;
|
||||
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 );
|
||||
if( midi_record_play::is_started(app->mrpH) )
|
||||
@ -1928,6 +1995,8 @@ namespace cw
|
||||
break;
|
||||
|
||||
case io::kMidiTId:
|
||||
if( app->useLiveMidiFl && app->mrpH.isValid() )
|
||||
_on_live_midi( app, *m );
|
||||
break;
|
||||
|
||||
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;
|
||||
@ -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
|
||||
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.");
|
||||
goto errLabel;
|
||||
|
@ -5,7 +5,7 @@ namespace cw
|
||||
{
|
||||
namespace preset_sel_app
|
||||
{
|
||||
rc_t main( const object_t* cfg, const object_t* flow_proc_dict );
|
||||
rc_t main( const object_t* cfg );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,11 +134,17 @@ namespace cw
|
||||
|
||||
// if no input
|
||||
if( rc == -EAGAIN )
|
||||
{
|
||||
// TODO: report or at least count error
|
||||
break;
|
||||
}
|
||||
|
||||
// if input buffer overrun
|
||||
if( rc == -ENOSPC )
|
||||
{
|
||||
// TODO: report or at least count error
|
||||
break;
|
||||
}
|
||||
|
||||
// get the device this event arrived from
|
||||
if( p->prvRcvDev==NULL || p->prvRcvDev->clientId != ev->source.client )
|
||||
|
130
cwScoreFollower.cpp
Normal file
130
cwScoreFollower.cpp
Normal 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
21
cwScoreFollower.h
Normal 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
|
@ -34,6 +34,7 @@
|
||||
button:{ name: stopBtnId, title:"Stop" },
|
||||
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 },
|
||||
check: { name: liveCheckId, title:"Live" },
|
||||
},
|
||||
|
||||
row: {
|
||||
|
Loading…
Reference in New Issue
Block a user