cmScoreMatchGraphic.h/c : Added cmScoreMatchGraphicUpdateMidiFromScore() to set the MIDI note velocities based on the score velocities.

This commit is contained in:
kevin 2016-06-16 12:55:34 -04:00
parent 670edcaec7
commit 3acdeb61a0
2 changed files with 71 additions and 4 deletions

View File

@ -89,7 +89,8 @@ typedef struct
typedef struct
{
cmErr_t err;
cmChar_t* scFn;
cmSmgSc_t* scV; // scV[scN] score bars and notes
unsigned scN;
@ -99,7 +100,8 @@ typedef struct
cmSmgLine_t* lines; // Graphic lines used to indicate that a midi event matches to multiple score notes.
// (Each match after the first gets a line from the box representing the midi event
// to the matching score event)
cmChar_t* mfFn; // MIDI file name
cmSmgMidi_t* mV; // mV[mN] midi note-on events
unsigned mN;
double mfDurSecs; // midi file duration in seconds
@ -120,6 +122,7 @@ cmSmg_t* _cmSmgHandleToPtr( cmSmgH_t h )
cmSmgRC_t _cmSmgFree( cmSmg_t* p )
{
unsigned i;
for(i=0; i<p->mN; ++i)
{
@ -155,7 +158,9 @@ cmSmgRC_t _cmSmgFree( cmSmg_t* p )
cmMemFree(l0);
l0 = l1;
}
cmMemFree(p->scFn);
cmMemFree(p->mfFn);
cmMemFree(p->scV);
cmMemFree(p->mV);
cmMemFree(p->locV);
@ -198,6 +203,7 @@ cmSmgRC_t _cmSmgInitFromScore( cmCtx_t* ctx, cmSmg_t* p, const cmChar_t* scoreFn
if( cmScoreInitialize(ctx,&scH,scoreFn,44100.0, NULL, 0, NULL, NULL, cmSymTblNullHandle ) != kOkScRC )
return cmErrMsg(&p->err,kScoreFailSmgRC,"Score initializatio failed on '%s'.",cmStringNullGuard(scoreFn));
p->scFn = cmMemAllocStr(scoreFn);
p->scN = cmScoreEvtCount(scH);
p->scV = cmMemAllocZ(cmSmgSc_t,p->scN);
@ -269,6 +275,7 @@ cmSmgRC_t _cmSmgInitFromMidi( cmCtx_t* ctx, cmSmg_t* p, const cmChar_t* midiFn )
p->mV = cmMemAllocZ(cmSmgMidi_t,mN);
p->mN = mN;
p->mfDurSecs = cmMidiFileDurSecs(mfH);
p->mfFn = cmMemAllocStr(midiFn);
for(i=0,j=0; i<mN; ++i)
if( (mV[i]!=NULL) && cmMidiIsChStatus(mV[i]->status) && cmMidiIsNoteOn(mV[i]->status) && (mV[i]->u.chMsgPtr->d1>0) )
@ -606,3 +613,57 @@ cmSmgRC_t cmScoreMatchGraphicGenTimeLineBars( cmSmgH_t h, const cmChar_t* fn, un
return rc;
}
cmSmgRC_t cmScoreMatchGraphicUpdateMidiFromScore( cmCtx_t* ctx, cmSmgH_t h, const cmChar_t* newMidiFn )
{
cmSmgRC_t rc = kOkSmgRC;
cmSmg_t* p = _cmSmgHandleToPtr(h);
unsigned i = 0;
cmMidiFileH_t mfH = cmMidiFileNullHandle;
cmScH_t scH = cmScNullHandle;
if( cmMidiFileOpen(ctx, &mfH, p->mfFn ) != kOkMfRC )
return cmErrMsg(&p->err,kMidiFileFailSmgRC,"MIDI file open failed on '%s'.",cmStringNullGuard(p->mfFn));
if( cmScoreInitialize(ctx,&scH,p->scFn,44100.0, NULL, 0, NULL, NULL, cmSymTblNullHandle ) != kOkScRC )
{
rc = cmErrMsg(&p->err,kScoreFailSmgRC,"Score initializatio failed on '%s'.",cmStringNullGuard(p->scFn));
goto errLabel;
}
for(i=0; i<p->mN; ++i)
{
cmSmgMidi_t* mr = p->mV + i;
// only update midi events which were matched exactly once
if( mr->matchV==NULL || mr->matchV->link!=NULL )
continue;
// locate the matched score event
const cmScoreEvt_t* s= cmScoreIdToEvt( scH, mr->matchV->score->csvEventId );
assert( s!=NULL );
// assign the score velocity to the MIDI file
if(cmMidiFileSetVelocity( mfH, mr->uid, s->vel ) != kOkMfRC )
{
rc = cmErrMsg(&p->err,kOpFailSmgRC,"Set velocify operation failed.");
goto errLabel;
}
}
// write the updated MIDI file
if( cmMidiFileWrite( mfH, newMidiFn ) != kOkMfRC )
{
rc = cmErrMsg(&p->err,kMidiFileFailSmgRC,"MIDI file write failed on '%s'.",cmStringNullGuard(newMidiFn));
goto errLabel;
}
errLabel:
cmMidiFileClose(&mfH);
cmScoreFinalize(&scH);
return rc;
}

View File

@ -10,7 +10,8 @@ extern "C" {
kOkSmgRC = cmOkRC,
kFileSmgRC,
kScoreFailSmgRC,
kMidiFileFailSmgRC
kMidiFileFailSmgRC,
kOpFailSmgRC
};
typedef cmRC_t cmSmgRC_t;
@ -27,6 +28,11 @@ extern "C" {
// Generate a set of markers for use in a cmTimeLine file which forms a marked area
// beginning at each bar line and ends at the end of the file.
cmSmgRC_t cmScoreMatchGraphicGenTimeLineBars( cmSmgH_t h, const cmChar_t* fn, unsigned srate );
// Update the MIDI file velocity values and insert pedal events
// from from score into MIDI file and then write the updated MIDI
// file to 'newMidiFn'.
cmSmgRC_t cmScoreMatchGraphicUpdateMidiFromScore( cmCtx_t* ctx, cmSmgH_t h, const cmChar_t* newMidiFn );
#ifdef __cplusplus
}