diff --git a/app/cmXScore.c b/app/cmXScore.c index 91d2592..d0e9c68 100644 --- a/app/cmXScore.c +++ b/app/cmXScore.c @@ -1842,89 +1842,6 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p ) return rc; } -cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn ) -{ - cmXsRC_t rc = kOkXsRC; - - if((rc = cmXScoreFinalize(hp)) != kOkXsRC ) - return rc; - - cmXScore_t* p = cmMemAllocZ(cmXScore_t,1); - - cmErrSetup(&p->err,&ctx->rpt,"XScore"); - - // create a local linked heap - if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8196,ctx)) == false ) - return cmErrMsg(&p->err,kLHeapFailXsRC,"Lheap create failed."); - - // open the music xml file - if( cmXmlAlloc(ctx, &p->xmlH, xmlFn) != kOkXmlRC ) - { - rc = cmErrMsg(&p->err,kXmlFailXsRC,"Unable to open the MusicXML file '%s'.",cmStringNullGuard(xmlFn)); - goto errLabel; - } - - //cmXmlPrint(p->xmlH,&ctx->rpt); - - // parse the part-list - if((rc = _cmXScoreParsePartList( p )) != kOkXsRC ) - goto errLabel; - - // parse each score 'part' - cmXsPart_t* pp = p->partL; - for(; pp!=NULL; pp=pp->link) - if((rc = _cmXScoreParsePart(p,pp)) != kOkXsRC ) - goto errLabel; - - // fill in the note->slink chain to link the notes in each measure in time order - _cmXScoreSort(p); - - _cmXScoreSpreadGraceNotes(p); - - _cmXScoreSort(p); - - _cmXScoreResolveTiesAndLoc(p); - - _cmXScoreRemoveDuplicateNotes(p); - - _cmXScoreSetMeasGroups(p,kEvenXsFl); - _cmXScoreSetMeasGroups(p,kDynXsFl); - _cmXScoreSetMeasGroups(p,kTempoXsFl); - - //_cmXScoreResolveOctaveShift(p); - - // CSV output initialize failed. - if( cmCsvInitialize(&p->csvH,ctx) != kOkCsvRC ) - rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV output object create failed."); - - errLabel: - if( rc != kOkXsRC ) - _cmXScoreFinalize(p); - else - hp->h = p; - - return rc; -} - -cmXsRC_t cmXScoreFinalize( cmXsH_t* hp ) -{ - cmXsRC_t rc = kOkXsRC; - - if( hp == NULL || cmXScoreIsValid(*hp)==false ) - return kOkXsRC; - - cmXScore_t* p = _cmXScoreHandleToPtr(*hp); - - if((rc = _cmXScoreFinalize(p)) != kOkXsRC ) - return rc; - - hp->h = NULL; - - return rc; -} - -bool cmXScoreIsValid( cmXsH_t h ) -{ return h.h != NULL; } //------------------------------------------------------------------------------------------- @@ -2365,12 +2282,11 @@ cmXsRC_t _cmXScoreReorderParsePitch(cmXScore_t* p, const cmChar_t* b, unsigned return rc; } -cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn ) +cmXsRC_t _cmXsApplyEditFile( cmXScore_t* p, const cmChar_t* fn ) { typedef enum { kFindMeasStId, kFindEventStId, kReadEventStId } stateId_t; cmXsRC_t rc = kOkXsRC; - cmXScore_t* p = _cmXScoreHandleToPtr(h); cmFileH_t fH = cmFileNullHandle; cmChar_t* b = NULL; unsigned bN = 0; @@ -2538,6 +2454,107 @@ cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn ) +cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn, const cmChar_t* editFn ) +{ + cmXsRC_t rc = kOkXsRC; + + if((rc = cmXScoreFinalize(hp)) != kOkXsRC ) + return rc; + + cmXScore_t* p = cmMemAllocZ(cmXScore_t,1); + + cmErrSetup(&p->err,&ctx->rpt,"XScore"); + + // create a local linked heap + if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8196,ctx)) == false ) + return cmErrMsg(&p->err,kLHeapFailXsRC,"Lheap create failed."); + + // open the music xml file + if( cmXmlAlloc(ctx, &p->xmlH, xmlFn) != kOkXmlRC ) + { + rc = cmErrMsg(&p->err,kXmlFailXsRC,"Unable to open the MusicXML file '%s'.",cmStringNullGuard(xmlFn)); + goto errLabel; + } + + //cmXmlPrint(p->xmlH,&ctx->rpt); + + // parse the part-list + if((rc = _cmXScoreParsePartList( p )) != kOkXsRC ) + goto errLabel; + + // parse each score 'part' + cmXsPart_t* pp = p->partL; + for(; pp!=NULL; pp=pp->link) + if((rc = _cmXScoreParsePart(p,pp)) != kOkXsRC ) + goto errLabel; + + // fill in the note->slink chain to link the notes in each measure in time order + _cmXScoreSort(p); + + _cmXScoreSpreadGraceNotes(p); + + _cmXScoreSort(p); + + _cmXScoreResolveTiesAndLoc(p); + + _cmXScoreRemoveDuplicateNotes(p); + + _cmXScoreSetMeasGroups(p,kEvenXsFl); + _cmXScoreSetMeasGroups(p,kDynXsFl); + _cmXScoreSetMeasGroups(p,kTempoXsFl); + + //_cmXScoreResolveOctaveShift(p); + + // CSV output initialize failed. + if( cmCsvInitialize(&p->csvH,ctx) != kOkCsvRC ) + rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV output object create failed."); + + if( editFn != NULL ) + { + if((rc = _cmXsApplyEditFile(p,editFn)) != kOkXsRC ) + { + cmErrMsg(&ctx->err,rc,"XScore reorder failed."); + goto errLabel; + } + } + + // assign durations to pedal down events + _cmXScoreProcessPedals(p); + + // remove some notes which share a pitch and are overlapped or embedded within another note. + _cmXScoreProcessOverlappingNotes(p); + + + errLabel: + if( rc != kOkXsRC ) + _cmXScoreFinalize(p); + else + hp->h = p; + + return rc; +} + +cmXsRC_t cmXScoreFinalize( cmXsH_t* hp ) +{ + cmXsRC_t rc = kOkXsRC; + + if( hp == NULL || cmXScoreIsValid(*hp)==false ) + return kOkXsRC; + + cmXScore_t* p = _cmXScoreHandleToPtr(*hp); + + if((rc = _cmXScoreFinalize(p)) != kOkXsRC ) + return rc; + + hp->h = NULL; + + return rc; +} + +bool cmXScoreIsValid( cmXsH_t h ) +{ return h.h != NULL; } + + /* CSV score columns @@ -3626,32 +3643,21 @@ cmXsRC_t _cmXScoreGenSvg( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cm return _cmXsWriteMidiSvg( ctx, p, &mf, dir, fn ); } + cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, - const cmChar_t* reorderFn, + const cmChar_t* editFn, const cmChar_t* csvOutFn, const cmChar_t* midiOutFn) { cmXsRC_t rc; cmXsH_t h = cmXsNullHandle; - if((rc = cmXScoreInitialize( ctx, &h, xmlFn)) != kOkXsRC ) + // Parse the XML file and apply the changes in editFn. + if((rc = cmXScoreInitialize( ctx, &h, xmlFn,editFn)) != kOkXsRC ) return cmErrMsg(&ctx->err,rc,"XScore alloc failed."); - if( reorderFn != NULL ) - if((rc = cmXScoreReorder(h,reorderFn)) != kOkXsRC ) - { - cmErrMsg(&ctx->err,rc,"XScore reorder failed."); - goto errLabel; - } - - // assign durations to pedal down events - _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h)); - - // remove some notes which share a pitch and are overlapped or embedded within another note. - _cmXScoreProcessOverlappingNotes(_cmXScoreHandleToPtr(h)); - if( csvOutFn != NULL ) { cmScH_t scH = cmScNullHandle; @@ -3694,7 +3700,6 @@ cmXsRC_t cmXScoreTest( //cmXScoreReport(h,&ctx->rpt,true); - errLabel: return cmXScoreFinalize(&h); } diff --git a/app/cmXScore.h b/app/cmXScore.h index 7359b89..3b28c25 100644 --- a/app/cmXScore.h +++ b/app/cmXScore.h @@ -43,26 +43,15 @@ extern "C" { // // M-x load-file ~/src/emacs/proc_music_xml.el // - // 3) How to assigned dynamic markings (they are not attached to notes). (from MIDI file?) - // 4) Tempo syntax is inconsistent (only a problem in full part2 score) - // 5) Heel is being parsed but not used. - // 6) Sostenuto pedal events are not being parsed because they are not pedal events. - // 7) What is a 'pedal-change' event vs. a 'pedal-stop' event. - // 8) Verify the colors. (done) - // 9) Remove blank bars at end (done in xml - do in score) - //10) Need to assign section targets (always default to next section) - //11) Mark tied notes for skip. (done) - //12) Determine note off locations based on ties and slurs - defer 'pedal' to player - //13) Check that the measures are given in sorted order. - //14) Current implementation assumes meter changes only occur at measure boundaries. - //15) Score Fixes: Add meter to bar 1, fix time errors (shown in voice report) - //16) The order of notes is now correct (4/6/16) after applying - // the grace note ordering changed specified in 'score_print_mk_edit.txt', - // via cmXScoreReorder() however the ticks are now incorrect - fix them. - - cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn ); + + // Initialize an cmXScore object from a Sibelius generated MusicXML file. + // Optionally include an 'edit' file to attach additional score information. + // Note that the 'edit' file is created by marking up a file created via + // cmXScoreReport(). + cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn, const cmChar_t* editFn ); cmXsRC_t cmXScoreFinalize( cmXsH_t* hp ); + bool cmXScoreIsValid( cmXsH_t h ); cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, const cmChar_t* csvFn );