|
@@ -1,6 +1,7 @@
|
1
|
1
|
#include "cmPrefix.h"
|
2
|
2
|
#include "cmGlobal.h"
|
3
|
3
|
#include "cmFloatTypes.h"
|
|
4
|
+#include "cmComplexTypes.h"
|
4
|
5
|
#include "cmRpt.h"
|
5
|
6
|
#include "cmErr.h"
|
6
|
7
|
#include "cmCtx.h"
|
|
@@ -16,6 +17,16 @@
|
16
|
17
|
#include "cmLex.h"
|
17
|
18
|
#include "cmCsv.h"
|
18
|
19
|
|
|
20
|
+#include "cmFile.h"
|
|
21
|
+#include "cmSymTbl.h"
|
|
22
|
+#include "cmAudioFile.h"
|
|
23
|
+#include "cmAudioFile.h"
|
|
24
|
+#include "cmProcObj.h"
|
|
25
|
+#include "cmProcTemplate.h"
|
|
26
|
+#include "cmProc.h"
|
|
27
|
+#include "cmProc2.h"
|
|
28
|
+#include "cmProc5.h"
|
|
29
|
+
|
19
|
30
|
cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
|
20
|
31
|
|
21
|
32
|
enum
|
|
@@ -51,9 +62,10 @@ typedef struct cmXsNote_str
|
51
|
62
|
cmChar_t step; // A-G
|
52
|
63
|
unsigned octave; // sci pitch octave
|
53
|
64
|
int alter; // +n=sharps,-n=flats
|
54
|
|
- unsigned staff;
|
|
65
|
+ unsigned staff; // 1=treble 2=bass
|
55
|
66
|
unsigned tick; //
|
56
|
67
|
unsigned duration; // duration in ticks
|
|
68
|
+ unsigned locIdx; // location index (chords share the same location index)
|
57
|
69
|
double rvalue; // 1/rvalue = rythmic value (1/0.5 double whole 1/1 whole 1/2 half 1/4=quarter note, 1/8=eighth note, ...)
|
58
|
70
|
const cmChar_t* tvalue; // text value
|
59
|
71
|
|
|
@@ -706,6 +718,8 @@ cmXsRC_t _cmXScoreParsePart( cmXScore_t* p, cmXsPart_t* pp )
|
706
|
718
|
return rc;
|
707
|
719
|
}
|
708
|
720
|
|
|
721
|
+// Insert note 'np' into the sorted note list based at 's0'.
|
|
722
|
+// Return a pointer to the base of the list after the insertion.
|
709
|
723
|
cmXsNote_t* _cmXScoreInsertSortedNote( cmXsNote_t* s0, cmXsNote_t* np )
|
710
|
724
|
{
|
711
|
725
|
if( s0 == NULL )
|
|
@@ -740,9 +754,11 @@ cmXsNote_t* _cmXScoreInsertSortedNote( cmXsNote_t* s0, cmXsNote_t* np )
|
740
|
754
|
|
741
|
755
|
void _cmXScoreSort( cmXScore_t* p )
|
742
|
756
|
{
|
|
757
|
+ // for each part
|
743
|
758
|
cmXsPart_t* pp = p->partL;
|
744
|
759
|
for(; pp!=NULL; pp=pp->link)
|
745
|
760
|
{
|
|
761
|
+ // for each measure in this part
|
746
|
762
|
cmXsMeas_t* mp = pp->measL;
|
747
|
763
|
for(; mp!=NULL; mp=mp->link)
|
748
|
764
|
{
|
|
@@ -750,6 +766,7 @@ void _cmXScoreSort( cmXScore_t* p )
|
750
|
766
|
cmXsVoice_t* vp = mp->voiceL;
|
751
|
767
|
for(; vp!=NULL; vp=vp->link)
|
752
|
768
|
{
|
|
769
|
+ // for each note in this measure
|
753
|
770
|
cmXsNote_t* np = vp->noteL;
|
754
|
771
|
for(; np!=NULL; np=np->mlink)
|
755
|
772
|
mp->noteL = _cmXScoreInsertSortedNote(mp->noteL,np);
|
|
@@ -797,27 +814,44 @@ bool _cmXScoreFindTiedNote( cmXScore_t* p, cmXsMeas_t* mp, cmXsNote_t* np )
|
797
|
814
|
return false;
|
798
|
815
|
}
|
799
|
816
|
|
800
|
|
-void _cmXScoreProcessTies( cmXScore_t* p )
|
|
817
|
+void _cmXScoreResolveTiesAndLoc( cmXScore_t* p )
|
801
|
818
|
{
|
802
|
|
- unsigned n = 0;
|
803
|
|
- unsigned m = 0;
|
|
819
|
+ unsigned n = 0;
|
|
820
|
+ unsigned m = 0;
|
804
|
821
|
|
805
|
822
|
cmXsPart_t* pp = p->partL;
|
806
|
823
|
for(; pp!=NULL; pp=pp->link)
|
807
|
824
|
{
|
|
825
|
+ unsigned locIdx = 1;
|
808
|
826
|
cmXsMeas_t* mp = pp->measL;
|
809
|
827
|
for(; mp!=NULL; mp=mp->link)
|
810
|
828
|
{
|
|
829
|
+ cmXsNote_t* n0 = NULL;
|
811
|
830
|
cmXsNote_t* np = mp->noteL;
|
812
|
831
|
|
813
|
832
|
for(; np!=NULL; np=np->slink)
|
|
833
|
+ {
|
|
834
|
+ // if this note begins a tie and has not yet been processed
|
|
835
|
+ // (A note that continues a tie and therefore has a kTieBegXsFl set
|
|
836
|
+ // may have already been processed by an earlier tied note.)
|
814
|
837
|
if( cmIsFlag(np->flags,kTieBegXsFl) && cmIsNotFlag(np->flags,kTieProcXsFl))
|
815
|
838
|
{
|
816
|
839
|
if( _cmXScoreFindTiedNote(p,mp,np) )
|
817
|
840
|
m += 1;
|
818
|
841
|
n += 1;
|
819
|
|
- }
|
820
|
|
-
|
|
842
|
+ }
|
|
843
|
+
|
|
844
|
+ // set the location
|
|
845
|
+ if( cmIsFlag(np->flags,kOnsetXsFl) )
|
|
846
|
+ {
|
|
847
|
+ if( n0!=NULL && n0->tick!=np->tick)
|
|
848
|
+ locIdx += 1;
|
|
849
|
+
|
|
850
|
+ np->locIdx = locIdx;
|
|
851
|
+ n0 = np;
|
|
852
|
+ }
|
|
853
|
+
|
|
854
|
+ }
|
821
|
855
|
}
|
822
|
856
|
}
|
823
|
857
|
|
|
@@ -911,6 +945,7 @@ cmXsNote_t* _cmXScoreNextNote( cmXsPart_t* pp, cmXsNote_t* note )
|
911
|
945
|
return note;
|
912
|
946
|
}
|
913
|
947
|
|
|
948
|
+
|
914
|
949
|
cmXsRC_t _cmXScoreProcessMidi(cmXScore_t* p, cmCtx_t* ctx, const cmChar_t* midiFn)
|
915
|
950
|
{
|
916
|
951
|
cmXsRC_t rc = kOkXsRC;
|
|
@@ -924,6 +959,8 @@ cmXsRC_t _cmXScoreProcessMidi(cmXScore_t* p, cmCtx_t* ctx, const cmChar_t* mi
|
924
|
959
|
if( cmMidiFileOpen(ctx, &mfH, midiFn ) != kOkMfRC )
|
925
|
960
|
return cmErrMsg(&p->err,kMidiFailXsRC,"The MIDI file object could not be opened from '%s'.",cmStringNullGuard(midiFn));
|
926
|
961
|
|
|
962
|
+ cmMidiFilePrintMsgs(mfH, p->err.rpt );
|
|
963
|
+
|
927
|
964
|
if( (m = cmMidiFileMsgArray(mfH)) == NULL || (mN = cmMidiFileMsgCount(mfH)) == 0 )
|
928
|
965
|
{
|
929
|
966
|
rc = cmErrMsg(&p->err,kMidiFailXsRC,"The MIDI file object appears to be empty.");
|
|
@@ -936,6 +973,37 @@ cmXsRC_t _cmXScoreProcessMidi(cmXScore_t* p, cmCtx_t* ctx, const cmChar_t* mi
|
936
|
973
|
goto errLabel;
|
937
|
974
|
}
|
938
|
975
|
|
|
976
|
+ cmCtx* c = cmCtxAlloc( NULL, p->err.rpt, cmLHeapNullHandle, cmSymTblNullHandle );
|
|
977
|
+ cmSeqAlign_t* s = cmSeqAlignAlloc(c,NULL);
|
|
978
|
+ unsigned offs = 0;
|
|
979
|
+
|
|
980
|
+ for(; note!=NULL; note=_cmXScoreNextNote(p->partL,note))
|
|
981
|
+ {
|
|
982
|
+ if( cmIsFlag(note->flags,kGraceXsFl) )
|
|
983
|
+ offs += 1;
|
|
984
|
+
|
|
985
|
+ cmSeqAlignInsert(s,0,note->locIdx+offs,note->pitch);
|
|
986
|
+ }
|
|
987
|
+
|
|
988
|
+ unsigned locIdx = 1;
|
|
989
|
+ for(i=0,j=0; i<mN; ++i)
|
|
990
|
+ if( (m[i]!=NULL) && cmMidiIsChStatus(m[i]->status) && cmMidiIsNoteOn(m[i]->status) && (m[i]->u.chMsgPtr->d1>0) )
|
|
991
|
+ {
|
|
992
|
+ if( m[j]->atick != m[i]->atick )
|
|
993
|
+ locIdx += 1;
|
|
994
|
+
|
|
995
|
+ cmSeqAlignInsert(s,1,locIdx,m[i]->u.chMsgPtr->d0);
|
|
996
|
+
|
|
997
|
+ //printf("%i : %s\n",locIdx,cmMidiToSciPitch(m[i]->u.chMsgPtr->d0,NULL,0));
|
|
998
|
+
|
|
999
|
+ j = i;
|
|
1000
|
+ }
|
|
1001
|
+
|
|
1002
|
+ cmSeqAlignReport(s,p->err.rpt);
|
|
1003
|
+ cmSeqAlignFree(&s);
|
|
1004
|
+ cmCtxFree(&c);
|
|
1005
|
+ goto errLabel;
|
|
1006
|
+
|
939
|
1007
|
printf(" i j score midi\n");
|
940
|
1008
|
printf("---- ---- --- ---- --- ----\n");
|
941
|
1009
|
|
|
@@ -1002,7 +1070,7 @@ cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn, c
|
1002
|
1070
|
// fill in the note->slink chain to link the notes in each measure in time order
|
1003
|
1071
|
_cmXScoreSort(p);
|
1004
|
1072
|
|
1005
|
|
- _cmXScoreProcessTies(p);
|
|
1073
|
+ _cmXScoreResolveTiesAndLoc(p);
|
1006
|
1074
|
|
1007
|
1075
|
//_cmXScoreResolveOctaveShift(p);
|
1008
|
1076
|
|
|
@@ -1065,9 +1133,8 @@ void _cmXScoreReportNote( cmRpt_t* rpt, const cmXsNote_t* note )
|
1065
|
1133
|
cmChar_t N[] = {'\0','\0','\0','\0'};
|
1066
|
1134
|
cmChar_t acc = note->alter==-1?'b':(note->alter==1?'#':' ');
|
1067
|
1135
|
snprintf(N,4,"%c%c%1i",note->step,acc,note->octave);
|
1068
|
|
-
|
1069
|
|
-
|
1070
|
|
- cmRptPrintf(rpt," %3i %5i %5i %4.1f %3s %s%s%s%s%s%s%s%s%s%s%s%s%s",note->voice->id,note->tick,note->duration,note->rvalue,N,B,R,G,D,C,e,d,t,P,S,H,T0,T1);
|
|
1136
|
+
|
|
1137
|
+ cmRptPrintf(rpt," %3i %5i %5i %5i %4.1f %3s %s%s%s%s%s%s%s%s%s%s%s%s%s",note->voice->id,note->locIdx,note->tick,note->duration,note->rvalue,N,B,R,G,D,C,e,d,t,P,S,H,T0,T1);
|
1071
|
1138
|
|
1072
|
1139
|
if( cmIsFlag(note->flags,kSectionXsFl) )
|
1073
|
1140
|
cmRptPrintf(rpt," %s",cmStringNullGuard(note->tvalue));
|
|
@@ -1474,7 +1541,7 @@ cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* midi
|
1474
|
1541
|
return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
|
1475
|
1542
|
|
1476
|
1543
|
cmXScoreWriteCsv(h,"/Users/kevin/temp/a0.csv");
|
1477
|
|
- cmXScoreReport(h,&ctx->rpt,false);
|
|
1544
|
+ cmXScoreReport(h,&ctx->rpt,true);
|
1478
|
1545
|
|
1479
|
1546
|
return cmXScoreFinalize(&h);
|
1480
|
1547
|
|