From 3acdeb61a0c8b61f3bcd51100e25ca1a016a1609 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 16 Jun 2016 12:55:34 -0400 Subject: [PATCH] cmScoreMatchGraphic.h/c : Added cmScoreMatchGraphicUpdateMidiFromScore() to set the MIDI note velocities based on the score velocities. --- app/cmScoreMatchGraphic.c | 67 +++++++++++++++++++++++++++++++++++++-- app/cmScoreMatchGraphic.h | 8 ++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/app/cmScoreMatchGraphic.c b/app/cmScoreMatchGraphic.c index 868c734..06aaafb 100644 --- a/app/cmScoreMatchGraphic.c +++ b/app/cmScoreMatchGraphic.c @@ -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; imN; ++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; istatus) && 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; imN; ++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; + +} diff --git a/app/cmScoreMatchGraphic.h b/app/cmScoreMatchGraphic.h index 267ac41..d34df5b 100644 --- a/app/cmScoreMatchGraphic.h +++ b/app/cmScoreMatchGraphic.h @@ -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 }