cmTakeSeqBldr.h/c : Partial implementation of cmTakeSeqBldrLoadTake().
This commit is contained in:
parent
9e11eb49b8
commit
4873885874
@ -18,35 +18,79 @@
|
|||||||
#include "cmTakeSeqBldr.h"
|
#include "cmTakeSeqBldr.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct cmNoteTsb_str
|
// Map a score event to a MIDI event.
|
||||||
|
typedef struct cmScTrkMidiTsb_str
|
||||||
{
|
{
|
||||||
unsigned mni; // midi note index as an offset from the take marker
|
unsigned mni; // midi note index as an offset from the take marker
|
||||||
unsigned scEvtIdx; // score event index this not is assoc'd with or -1 if it did not match
|
unsigned scEvtIdx; // score event index this not is assoc'd with or -1 if it did not match
|
||||||
unsigned flags; // flags from cmScMatcherResult_t
|
unsigned flags; // flags from cmScMatcherResult_t
|
||||||
} cmNoteTsb_t;
|
} cmScTrkMidiTsb_t;
|
||||||
|
|
||||||
typedef struct cmTakeTsb_str
|
|
||||||
|
// Score Tracking info. from a single take (time-line marker)
|
||||||
|
typedef struct cmScTrkTakeTsb_str
|
||||||
{
|
{
|
||||||
unsigned markerUid; // marker time line uid assoc'd with this take
|
unsigned markerUid; // marker time line uid assoc'd with this take
|
||||||
cmNoteTsb_t* noteV; // noteV[noteN] score to midi file map recd. array.
|
cmScTrkMidiTsb_t* midiV; // midiV[midiN] score to midi file map recd. array.
|
||||||
unsigned noteN;
|
unsigned midiN;
|
||||||
bool failFl;
|
bool failFl;
|
||||||
} cmTakeTsb_t;
|
} cmScTrkTakeTsb_t;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kNoteTsbFl = 0x01,
|
||||||
|
kPedalTsbFl = 0x02,
|
||||||
|
kEnableTsbFl = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
typedef struct cmMidiEvt_str
|
||||||
|
{
|
||||||
|
unsigned srcId; // marker uid or -1 if this event was manually inserted
|
||||||
|
unsigned flags; // note | pedal | enable
|
||||||
|
struct cmMidiEvt_str* ref; // previous MIDI event in time
|
||||||
|
unsigned offsetSmp; // time offset from *ref
|
||||||
|
unsigned durSmp; // duration of this MIDI event
|
||||||
|
unsigned d0; // d0 MIDI channel msg data.
|
||||||
|
unsigned d1; // d1 MIDI channel msg data
|
||||||
|
struct cmMidiEvt_str* link; // pointer to next MIDI event in list
|
||||||
|
} cmMidiEvt_t;
|
||||||
|
|
||||||
|
// This record represents a note or pedal score event
|
||||||
|
typedef struct cmScEvtTsb_str
|
||||||
|
{
|
||||||
|
unsigned flags; // note | pedal
|
||||||
|
unsigned scEvtIdx; // score event index (into scH)
|
||||||
|
cmMidiEvt_t* evtList; // list of alternate MIDI events which may render this event
|
||||||
|
} cmScEvtTsb_t;
|
||||||
|
|
||||||
|
// This record contains all the score events and and score synchronized MIDI events
|
||||||
|
// associated with a given take. Each call to cmTakeSeqBldrLoadTake() creates
|
||||||
|
// one of these records.
|
||||||
|
typedef struct cmTakeScEvtArrayTsb_str
|
||||||
|
{
|
||||||
|
unsigned tlMarkerUid; // time-line marker uid associated with this take
|
||||||
|
cmScEvtTsb_t* scEvtV; // scEvtV[scEvtN] array of score events contained by this take
|
||||||
|
unsigned scEvtN; // count of score events in this take
|
||||||
|
} cmTakeScEvtArrayTsb_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
cmCtx_t ctx;
|
cmCtx_t ctx; // application context
|
||||||
cmErr_t err;
|
cmErr_t err; // internal error object
|
||||||
cmJsonH_t jsH;
|
cmJsonH_t jsH; // JSON tree used to hold score tracker info.
|
||||||
const cmChar_t* tlFn;
|
const cmChar_t* tlFn; // time line filename
|
||||||
const cmChar_t* scFn;
|
const cmChar_t* scFn; // score file name
|
||||||
const cmChar_t* tlPrefixPath;
|
const cmChar_t* tlPrefixPath; // path to time line audio and MIDI files
|
||||||
|
cmTlH_t tlH; // time-line handle
|
||||||
|
cmScH_t scH; // score handle
|
||||||
|
|
||||||
cmTakeTsb_t* takeV; // takeV[ takeN ]
|
cmScTrkTakeTsb_t* scTrkTakeV; // score tracker scTrkTakeV[ scTrkTakeN ]
|
||||||
unsigned takeN;
|
unsigned scTrkTakeN;
|
||||||
|
|
||||||
|
cmTakeScEvtArrayTsb_t* takes; // list of scEvt arrays used by this sequence
|
||||||
|
cmTakeScEvtArrayTsb_t* manual; // list of manually inserted MIDI events
|
||||||
|
|
||||||
cmTlH_t tlH;
|
|
||||||
cmScH_t scH;
|
|
||||||
|
|
||||||
} cmTsb_t;
|
} cmTsb_t;
|
||||||
|
|
||||||
@ -69,10 +113,10 @@ cmTsbRC_t _cmTsbScoreTrkFree( cmTsb_t* p )
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i<p->takeN; ++i)
|
for(i=0; i<p->scTrkTakeN; ++i)
|
||||||
cmMemPtrFree(&p->takeV[i].noteV);
|
cmMemPtrFree(&p->scTrkTakeV[i].midiV);
|
||||||
|
|
||||||
cmMemPtrFree(&p->takeV);
|
cmMemPtrFree(&p->scTrkTakeV);
|
||||||
|
|
||||||
if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
|
if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
|
||||||
rc = cmErrMsg(&p->err,kTimeLineFailTsbRC,"Time line object finalize failed.");
|
rc = cmErrMsg(&p->err,kTimeLineFailTsbRC,"Time line object finalize failed.");
|
||||||
@ -131,13 +175,13 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// count of take records
|
// count of take records
|
||||||
p->takeN = cmJsonChildCount(tkArrObj);
|
p->scTrkTakeN = cmJsonChildCount(tkArrObj);
|
||||||
|
|
||||||
// array of take records
|
// array of take records
|
||||||
p->takeV = cmMemAllocZ(cmTakeTsb_t,p->takeN);
|
p->scTrkTakeV = cmMemAllocZ(cmScTrkTakeTsb_t,p->scTrkTakeN);
|
||||||
|
|
||||||
// for each take record
|
// for each take record
|
||||||
for(i=0; i<p->takeN; ++i)
|
for(i=0; i<p->scTrkTakeN; ++i)
|
||||||
{
|
{
|
||||||
cmJsonNode_t* takeObj = NULL;
|
cmJsonNode_t* takeObj = NULL;
|
||||||
cmJsonNode_t* noteArrObj = NULL;
|
cmJsonNode_t* noteArrObj = NULL;
|
||||||
@ -152,8 +196,8 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
|
|||||||
|
|
||||||
// parse the take record
|
// parse the take record
|
||||||
if((jsRC = cmJsonMemberValues( takeObj, &errMsg,
|
if((jsRC = cmJsonMemberValues( takeObj, &errMsg,
|
||||||
"markerUid",kIntTId, &p->takeV[i].markerUid,
|
"markerUid",kIntTId, &p->scTrkTakeV[i].markerUid,
|
||||||
"failFl", kIntTId, &p->takeV[i].failFl,
|
"failFl", kIntTId, &p->scTrkTakeV[i].failFl,
|
||||||
"array", kArrayTId, ¬eArrObj,
|
"array", kArrayTId, ¬eArrObj,
|
||||||
0)) != kOkJsRC )
|
0)) != kOkJsRC )
|
||||||
{
|
{
|
||||||
@ -166,13 +210,13 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the count of note records
|
// get the count of note records
|
||||||
p->takeV[i].noteN = cmJsonChildCount(noteArrObj);
|
p->scTrkTakeV[i].midiN = cmJsonChildCount(noteArrObj);
|
||||||
|
|
||||||
// allocate a note record array for this take
|
// allocate a note record array for this take
|
||||||
p->takeV[i].noteV = cmMemAllocZ(cmNoteTsb_t, p->takeV[i].noteN);
|
p->scTrkTakeV[i].midiV = cmMemAllocZ(cmScTrkMidiTsb_t, p->scTrkTakeV[i].midiN);
|
||||||
|
|
||||||
// for each note record
|
// for each note record
|
||||||
for(j=0; j<p->takeV[i].noteN; ++j)
|
for(j=0; j<p->scTrkTakeV[i].midiN; ++j)
|
||||||
{
|
{
|
||||||
cmJsonNode_t* noteObj = NULL;
|
cmJsonNode_t* noteObj = NULL;
|
||||||
|
|
||||||
@ -185,9 +229,9 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
|
|||||||
|
|
||||||
// parse the note record
|
// parse the note record
|
||||||
if((jsRC = cmJsonMemberValues( noteObj, &errMsg,
|
if((jsRC = cmJsonMemberValues( noteObj, &errMsg,
|
||||||
"mni", kIntTId, &p->takeV[i].noteV[j].mni,
|
"mni", kIntTId, &p->scTrkTakeV[i].midiV[j].mni,
|
||||||
"scEvtIdx", kIntTId, &p->takeV[i].noteV[j].scEvtIdx,
|
"scEvtIdx", kIntTId, &p->scTrkTakeV[i].midiV[j].scEvtIdx,
|
||||||
"flags", kIntTId, &p->takeV[i].noteV[j].flags,
|
"flags", kIntTId, &p->scTrkTakeV[i].midiV[j].flags,
|
||||||
0)) != kOkJsRC )
|
0)) != kOkJsRC )
|
||||||
{
|
{
|
||||||
if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
|
if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
|
||||||
@ -207,6 +251,30 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the count of score events inside a given marker.
|
||||||
|
unsigned _cmTsbScoreTrkMarkerEventCount( cmTsb_t* p, unsigned markUid )
|
||||||
|
{
|
||||||
|
unsigned i,j;
|
||||||
|
unsigned minScEvtIdx = INT_MAX;
|
||||||
|
unsigned maxScEvtIdx = 0;
|
||||||
|
|
||||||
|
for(i=0; i<p->scTrkTakeN; ++i)
|
||||||
|
for(j=0; j<p->scTrkTakeV[i].midiN; ++j)
|
||||||
|
{
|
||||||
|
if( p->scTrkTakeV[i].midiV[j].scEvtIdx < minScEvtIdx )
|
||||||
|
minScEvtIdx = p->scTrkTakeV[i].midiV[j].scEvtIdx;
|
||||||
|
|
||||||
|
if( p->scTrkTakeV[i].midiV[j].scEvtIdx > maxScEvtIdx )
|
||||||
|
maxScEvtIdx = p->scTrkTakeV[i].midiV[j].scEvtIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( maxScEvtIdx < minScEvtIdx )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (maxScEvtIdx - minScEvtIdx) + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
cmTsbRC_t cmTakeSeqBldrAlloc( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp )
|
cmTsbRC_t cmTakeSeqBldrAlloc( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp )
|
||||||
{
|
{
|
||||||
cmTsbRC_t rc;
|
cmTsbRC_t rc;
|
||||||
@ -287,6 +355,76 @@ cmTsbRC_t cmTakeSeqBldrInitialize( cmTakeSeqBldrH_t h, const cmChar_t* scoreTrkF
|
|||||||
cmTsbRC_t cmTakeSeqBldrLoadTake( cmTakeSeqBldrH_t h, unsigned tlMarkUid, bool overwriteFL )
|
cmTsbRC_t cmTakeSeqBldrLoadTake( cmTakeSeqBldrH_t h, unsigned tlMarkUid, bool overwriteFL )
|
||||||
{
|
{
|
||||||
cmTsbRC_t rc = kOkTsbRC;
|
cmTsbRC_t rc = kOkTsbRC;
|
||||||
|
cmTsb_t* p = _cmTsbHandleToPtr(h);
|
||||||
|
cmTlMarker_t* mark = NULL;
|
||||||
|
cmTlMidiFile_t* mf = NULL;
|
||||||
|
cmMidiFileH_t mfH = cmMidiFileNullHandle;
|
||||||
|
|
||||||
|
// get a pointer to the time-line marker object
|
||||||
|
if((mark = cmTlMarkerObjPtr( p->tlH, cmTimeLineIdToObj( p->tlH, cmInvalidId, tlMarkUid))) == NULL )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"The time-line marker uid '%i' is not valid.",tlMarkUid);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the name of the MIDI file which contains the marker
|
||||||
|
if((mf = cmTimeLineMidiFileAtTime( p->tlH, mark->obj.seqId, mark->obj.seqSmpIdx )) == NULL )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"The time-line marker '%i' does not intersect with a MIDI file.",tlMarkUid);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the MIDI file
|
||||||
|
if( cmMidiFileOpen( cmMidiFileName(mf->h), &mfH, &p->ctx ) != kOkMfRC )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"The MIDI file '%s' could not be opened.", cmStringNullGuard(cmMidiFileName(mf->h)));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the dtick field to absolute sample indexes
|
||||||
|
cmMidiFileTickToSamples( mfH, cmTimeLineSampleRate(p->tlH), true );
|
||||||
|
|
||||||
|
// calculate MIDI note and pedal durations (see cmMidiChMsg_t.durTicks)
|
||||||
|
cmMidiFileCalcNoteDurations( mfH );
|
||||||
|
|
||||||
|
// convert the marker beg/end sample position to be relative to the MIDI file start time
|
||||||
|
unsigned bsi = mark->obj.seqSmpIdx - mf->obj.seqSmpIdx;
|
||||||
|
unsigned esi = mark->obj.seqSmpIdx + mark->obj.durSmpCnt - mf->obj.seqSmpIdx;
|
||||||
|
unsigned i = 0;
|
||||||
|
unsigned n = cmMidiFileMsgCount(mfH);
|
||||||
|
const cmMidiTrackMsg_t** a = cmMidiFileMsgArray(mfH);
|
||||||
|
|
||||||
|
// seek to the first MIDI msg after bsi
|
||||||
|
for(i=0; i<n; ++i)
|
||||||
|
if( a[i]->dtick >= bsi )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( i == n )
|
||||||
|
{
|
||||||
|
rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"No MIDI events were found in the marker.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each MIDI message between bsi and esi
|
||||||
|
for(; i<n && a[i]->dtick < esi; ++i)
|
||||||
|
{
|
||||||
|
const cmMidiTrackMsg_t* m = a[i];
|
||||||
|
switch( m->status )
|
||||||
|
{
|
||||||
|
case kNoteOffMdId:
|
||||||
|
case kNoteOnMdId:
|
||||||
|
case kCtlMdId:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( cmMidiFileClose(&mfH) != kOkMfRC )
|
||||||
|
rc = cmErrMsg(&p->err,kMidiFileFailTsbRC,"MIDI file close failed.");
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,9 @@ extern "C" {
|
|||||||
kJsonFailTsbRC,
|
kJsonFailTsbRC,
|
||||||
kParseFailTsbRC,
|
kParseFailTsbRC,
|
||||||
kTimeLineFailTsbRC,
|
kTimeLineFailTsbRC,
|
||||||
kScoreFailTsbRC
|
kScoreFailTsbRC,
|
||||||
|
kInvalidArgTsbRC,
|
||||||
|
kMidiFileFailTsbRC
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef cmRC_t cmTsbRC_t;
|
typedef cmRC_t cmTsbRC_t;
|
||||||
@ -47,7 +49,7 @@ extern "C" {
|
|||||||
cmTsbRC_t cmTakeSeqBldrInsertScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
|
cmTsbRC_t cmTakeSeqBldrInsertScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
|
||||||
cmTsbRC_t cmTakeSeqBldrRemoveScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
|
cmTsbRC_t cmTakeSeqBldrRemoveScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
|
||||||
|
|
||||||
enum { kMarkTsbFl = 0x01, kTlNoteTsbFl=0x02, kScoreNoteTsbFl = 0x04, kPedalTsbFl = 0x08 };
|
//enum { kMarkTsbFl = 0x01, kTlNoteTsbFl=0x02, kScoreNoteTsbFl = 0x04, kPedalTsbFl = 0x08 };
|
||||||
cmTsbRC_t cmTakeSeqBldrSelectEnable( cmTakeSeqBldrH_t h, unsigned flags, unsigned id, bool selectFl );
|
cmTsbRC_t cmTakeSeqBldrSelectEnable( cmTakeSeqBldrH_t h, unsigned flags, unsigned id, bool selectFl );
|
||||||
cmTsbRC_t cmTakeSeqBldrEnableNote( cmTakeSeqBldrH_t h, unsigned ssqId, bool enableFl );
|
cmTsbRC_t cmTakeSeqBldrEnableNote( cmTakeSeqBldrH_t h, unsigned ssqId, bool enableFl );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user