|
@@ -12,6 +12,8 @@
|
12
|
12
|
#include "cmXScore.h"
|
13
|
13
|
#include "cmTime.h"
|
14
|
14
|
#include "cmMidi.h"
|
|
15
|
+#include "cmLex.h"
|
|
16
|
+#include "cmCsv.h"
|
15
|
17
|
|
16
|
18
|
cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
|
17
|
19
|
|
|
@@ -33,7 +35,6 @@ enum
|
33
|
35
|
};
|
34
|
36
|
|
35
|
37
|
|
36
|
|
-
|
37
|
38
|
typedef struct cmXsNote_str
|
38
|
39
|
{
|
39
|
40
|
unsigned flags; // See k???XsFl
|
|
@@ -41,11 +42,11 @@ typedef struct cmXsNote_str
|
41
|
42
|
unsigned tick; //
|
42
|
43
|
unsigned duration; // duration in ticks
|
43
|
44
|
unsigned rvalue; // 1/type = rythmic value (1/4=quarter note, 1/8=eighth note, ...)
|
|
45
|
+ const cmChar_t* tvalue; // text value
|
44
|
46
|
struct cmXsNote_str* mlink; // measure note list
|
45
|
47
|
struct cmXsNote_str* slink; // time sorted event list
|
46
|
48
|
} cmXsNote_t;
|
47
|
49
|
|
48
|
|
-
|
49
|
50
|
typedef struct cmXsVoice_str
|
50
|
51
|
{
|
51
|
52
|
unsigned id; // Voice id
|
|
@@ -55,14 +56,13 @@ typedef struct cmXsVoice_str
|
55
|
56
|
|
56
|
57
|
typedef struct cmXsMeas_str
|
57
|
58
|
{
|
58
|
|
- unsigned number; // Measure number
|
59
|
|
-
|
60
|
|
- unsigned divisions;
|
61
|
|
- unsigned beats;
|
62
|
|
- unsigned beat_type;
|
|
59
|
+ unsigned number; // Measure number
|
|
60
|
+ unsigned divisions; // ticks-per-quarter-note
|
|
61
|
+ unsigned beats; // beats per measure
|
|
62
|
+ unsigned beat_type; // whole/half/quarter/eighth ...
|
63
|
63
|
|
64
|
|
- cmXsVoice_t* voiceL; // List of voices in this measure
|
65
|
|
- cmXsNote_t* noteL; // List of time sorted notes in this measure
|
|
64
|
+ cmXsVoice_t* voiceL; // List of voices in this measure
|
|
65
|
+ cmXsNote_t* noteL; // List of time sorted notes in this measure
|
66
|
66
|
|
67
|
67
|
struct cmXsMeas_str* link; // Link to other measures in this part.
|
68
|
68
|
} cmXsMeas_t;
|
|
@@ -76,10 +76,11 @@ typedef struct cmXsPart_str
|
76
|
76
|
|
77
|
77
|
typedef struct
|
78
|
78
|
{
|
79
|
|
- cmErr_t err;
|
80
|
|
- cmXmlH_t xmlH;
|
81
|
|
- cmLHeapH_t lhH;
|
82
|
|
- cmXsPart_t* partL;
|
|
79
|
+ cmErr_t err;
|
|
80
|
+ cmXmlH_t xmlH;
|
|
81
|
+ cmLHeapH_t lhH;
|
|
82
|
+ cmXsPart_t* partL;
|
|
83
|
+ cmCsvH_t csvH;
|
83
|
84
|
} cmXScore_t;
|
84
|
85
|
|
85
|
86
|
cmXScore_t* _cmXScoreHandleToPtr( cmXsH_t h )
|
|
@@ -94,12 +95,13 @@ cmXsRC_t _cmXScoreFinalize( cmXScore_t* p )
|
94
|
95
|
cmXsRC_t rc = kOkXsRC;
|
95
|
96
|
|
96
|
97
|
// release the XML file
|
97
|
|
- if( cmXmlIsValid(p->xmlH) )
|
98
|
|
- cmXmlFree( &p->xmlH );
|
|
98
|
+ cmXmlFree( &p->xmlH );
|
99
|
99
|
|
100
|
100
|
// release the local linked heap memory
|
101
|
|
- if( cmLHeapIsValid(p->lhH) )
|
102
|
|
- cmLHeapDestroy(&p->lhH);
|
|
101
|
+ cmLHeapDestroy(&p->lhH);
|
|
102
|
+
|
|
103
|
+ // release the CSV output object
|
|
104
|
+ cmCsvFinalize(&p->csvH);
|
103
|
105
|
|
104
|
106
|
cmMemFree(p);
|
105
|
107
|
|
|
@@ -241,6 +243,7 @@ unsigned _cmXScoreParseNoteRValue( cmXScore_t* p, const cmXmlNode_t* nnp, const
|
241
|
243
|
|
242
|
244
|
map_t mapV[] =
|
243
|
245
|
{
|
|
246
|
+ { -1, "measure" }, // whole measure rest
|
244
|
247
|
{ 1, "whole" },
|
245
|
248
|
{ 2, "half" },
|
246
|
249
|
{ 4, "quarter" },
|
|
@@ -254,7 +257,15 @@ unsigned _cmXScoreParseNoteRValue( cmXScore_t* p, const cmXmlNode_t* nnp, const
|
254
|
257
|
|
255
|
258
|
const cmChar_t* str;
|
256
|
259
|
if((str = cmXmlNodeValue(nnp,label,NULL)) == NULL)
|
|
260
|
+ {
|
|
261
|
+ if((nnp = cmXmlSearch(nnp,"rest",NULL,0)) != NULL )
|
|
262
|
+ {
|
|
263
|
+ const cmXmlAttr_t* a;
|
|
264
|
+ if((a = cmXmlFindAttrib(nnp,"measure")) != NULL && cmTextCmp(a->value,"yes")==0)
|
|
265
|
+ return -1;
|
|
266
|
+ }
|
257
|
267
|
return 0;
|
|
268
|
+ }
|
258
|
269
|
|
259
|
270
|
unsigned i;
|
260
|
271
|
for(i=0; mapV[i].rvalue!=0; ++i)
|
|
@@ -354,7 +365,7 @@ cmXsRC_t _cmXScoreParseNote(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t*
|
354
|
365
|
return _cmXScorePushNote(p, meas, voiceId, note );
|
355
|
366
|
}
|
356
|
367
|
|
357
|
|
-cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, unsigned duration, unsigned rvalue, unsigned flags )
|
|
368
|
+cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, unsigned duration, unsigned rvalue, const cmChar_t* tvalue, unsigned flags )
|
358
|
369
|
{
|
359
|
370
|
cmXsNote_t* note = cmLhAllocZ(p->lhH,cmXsNote_t,1);
|
360
|
371
|
unsigned voiceId = 0; // non-note's are always assigned to voiceId=0;
|
|
@@ -362,6 +373,7 @@ cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, u
|
362
|
373
|
note->tick = tick;
|
363
|
374
|
note->flags = flags;
|
364
|
375
|
note->rvalue = rvalue;
|
|
376
|
+ note->tvalue = tvalue;
|
365
|
377
|
note->duration = duration;
|
366
|
378
|
|
367
|
379
|
return _cmXScorePushNote(p, meas, voiceId, note );
|
|
@@ -374,6 +386,7 @@ cmXsRC_t _cmXScoreParseDirection(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNo
|
374
|
386
|
unsigned flags = 0;
|
375
|
387
|
int offset = 0;
|
376
|
388
|
unsigned rvalue = 0;
|
|
389
|
+ const cmChar_t* tvalue = NULL;
|
377
|
390
|
unsigned duration = 0;
|
378
|
391
|
|
379
|
392
|
|
|
@@ -419,16 +432,14 @@ cmXsRC_t _cmXScoreParseDirection(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNo
|
419
|
432
|
{
|
420
|
433
|
if((a = cmXmlFindAttrib(np,"enclosure")) != NULL && cmTextCmp(a->value,"rectangle")==0 )
|
421
|
434
|
{
|
422
|
|
- if( cmXmlNodeUInt(np,&rvalue,NULL) != kOkXsRC )
|
423
|
|
- return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Error reading section number on line %i.",np->line);
|
|
435
|
+ if( cmTextIsEmpty( tvalue = np->dataStr ) )
|
|
436
|
+ return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Section number is blank or missing on line %i.",np->line);
|
424
|
437
|
|
425
|
|
- printf("rvalue=%i\n",rvalue);
|
426
|
|
-
|
427
|
438
|
flags = kSectionXsFl;
|
428
|
439
|
}
|
429
|
440
|
}
|
430
|
441
|
|
431
|
|
- return _cmXScorePushNonNote(p,meas,tick+offset,duration,rvalue,flags);
|
|
442
|
+ return _cmXScorePushNonNote(p,meas,tick+offset,duration,rvalue,tvalue,flags);
|
432
|
443
|
|
433
|
444
|
}
|
434
|
445
|
|
|
@@ -458,16 +469,15 @@ cmXsRC_t _cmXScoreParseMeasure(cmXScore_t* p, cmXsPart_t* pp, const cmXmlNode_t*
|
458
|
469
|
}
|
459
|
470
|
|
460
|
471
|
// get measure attributes node
|
461
|
|
- if((np = cmXmlSearch(mnp,"attributes",NULL,0)) == NULL)
|
462
|
|
- return rc; // (this measure does not have any attributes)
|
463
|
|
-
|
464
|
|
-
|
465
|
|
- cmXmlNodeUInt(np,&meas->divisions,"divisions",NULL);
|
466
|
|
- cmXmlNodeUInt(np,&meas->beats, "time","beats",NULL);
|
467
|
|
- cmXmlNodeUInt(np,&meas->beat_type,"time","beat-type",NULL);
|
468
|
|
-
|
|
472
|
+ if((np = cmXmlSearch(mnp,"attributes",NULL,0)) != NULL)
|
|
473
|
+ {
|
|
474
|
+ cmXmlNodeUInt(np,&meas->divisions,"divisions",NULL);
|
|
475
|
+ cmXmlNodeUInt(np,&meas->beats, "time","beats",NULL);
|
|
476
|
+ cmXmlNodeUInt(np,&meas->beat_type,"time","beat-type",NULL);
|
|
477
|
+ }
|
|
478
|
+
|
469
|
479
|
// store the bar line
|
470
|
|
- if((rc = _cmXScorePushNonNote(p,meas,tick,0,0,kBarXsFl)) != kOkXsRC )
|
|
480
|
+ if((rc = _cmXScorePushNonNote(p,meas,tick,0,0,NULL,kBarXsFl)) != kOkXsRC )
|
471
|
481
|
return rc;
|
472
|
482
|
|
473
|
483
|
|
|
@@ -595,6 +605,8 @@ cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn )
|
595
|
605
|
goto errLabel;
|
596
|
606
|
}
|
597
|
607
|
|
|
608
|
+ //cmXmlPrint(p->xmlH,&ctx->rpt);
|
|
609
|
+
|
598
|
610
|
// parse the part-list
|
599
|
611
|
if((rc = _cmXScoreParsePartList( p )) != kOkXsRC )
|
600
|
612
|
goto errLabel;
|
|
@@ -606,7 +618,11 @@ cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn )
|
606
|
618
|
goto errLabel;
|
607
|
619
|
|
608
|
620
|
// fill in the note->slink chain to link the notes in each measure in time order
|
609
|
|
- _cmXScoreSort(p);
|
|
621
|
+ _cmXScoreSort(p);
|
|
622
|
+
|
|
623
|
+ // CSV output initialize failed.
|
|
624
|
+ if( cmCsvInitialize(&p->csvH,ctx) != kOkCsvRC )
|
|
625
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV output object create failed.");
|
610
|
626
|
|
611
|
627
|
errLabel:
|
612
|
628
|
if( rc != kOkXsRC )
|
|
@@ -655,17 +671,326 @@ void _cmXScoreReportNote( cmRpt_t* rpt, const cmXsNote_t* note )
|
655
|
671
|
cmRptPrintf(rpt," %5i %5i %2i %3s %s%s%s%s%s%s%s%s%s",note->tick,note->duration,note->rvalue,N,B,R,G,D,C,e,d,t,P);
|
656
|
672
|
|
657
|
673
|
if( cmIsFlag(note->flags,kSectionXsFl) )
|
658
|
|
- cmRptPrintf(rpt," %i",note->rvalue);
|
|
674
|
+ cmRptPrintf(rpt," %i",cmStringNullGuard(note->tvalue));
|
659
|
675
|
|
660
|
676
|
printf("\n");
|
661
|
677
|
|
662
|
678
|
}
|
663
|
679
|
|
664
|
|
-void cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
|
|
680
|
+/*
|
|
681
|
+ kMidiFileIdColScIdx= 0,
|
|
682
|
+ kTypeLabelColScIdx = 3,
|
|
683
|
+ kDSecsColScIdx = 4,
|
|
684
|
+ kSecsColScIdx = 5,
|
|
685
|
+ kD0ColScIdx = 9,
|
|
686
|
+ kD1ColScIdx = 10,
|
|
687
|
+ kPitchColScIdx = 11,
|
|
688
|
+ kBarColScIdx = 13,
|
|
689
|
+ kSkipColScIdx = 14,
|
|
690
|
+ kEvenColScIdx = 15,
|
|
691
|
+ kGraceColScIdx = 16,
|
|
692
|
+ kTempoColScIdx = 17,
|
|
693
|
+ kFracColScIdx = 18,
|
|
694
|
+ kDynColScIdx = 19,
|
|
695
|
+ kSectionColScIdx = 20,
|
|
696
|
+ kRecdPlayColScIdx = 21,
|
|
697
|
+ kRemarkColScIdx = 22
|
|
698
|
+ */
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+cmXsRC_t _cmXScoreWriteCsvHdr( cmXScore_t* p )
|
665
|
702
|
{
|
666
|
|
- cmXScore_t* p = _cmXScoreHandleToPtr(h);
|
|
703
|
+ const cmChar_t* s[] =
|
|
704
|
+ {
|
|
705
|
+ "id","trk","evt","opcode","dticks","micros","status",
|
|
706
|
+ "meta","ch","d0","d1","arg0","arg1","bar","skip",
|
|
707
|
+ "even","grace","tempo","t frac","dyn","section","play_recd","remark",NULL
|
|
708
|
+ };
|
667
|
709
|
|
|
710
|
+ cmCsvCell_t* lcp = NULL;
|
|
711
|
+
|
|
712
|
+ if( cmCsvAppendRow( p->csvH, &lcp, cmCsvInsertSymText(p->csvH,s[0]), 0, 0 ) != kOkCsvRC )
|
|
713
|
+ return cmErrMsg(&p->err,kCsvFailXsRC,"CSV append row failed.");
|
|
714
|
+
|
|
715
|
+ unsigned i;
|
|
716
|
+ for(i=1; s[i]!=NULL; ++i)
|
|
717
|
+ {
|
|
718
|
+ if( cmCsvInsertTextColAfter(p->csvH, lcp, &lcp, s[i], 0 ) != kOkCsvRC )
|
|
719
|
+ return cmErrMsg(&p->err,kCsvFailXsRC,"CSV error inserting CSV title %i.\n",i);
|
|
720
|
+
|
|
721
|
+ }
|
|
722
|
+
|
|
723
|
+ return kOkXsRC;
|
|
724
|
+}
|
|
725
|
+
|
|
726
|
+cmXsRC_t _cmXScoreWriteCsvBlankCols( cmXScore_t* p, unsigned cnt, cmCsvCell_t** leftCellPtrPtr )
|
|
727
|
+{
|
|
728
|
+ unsigned i;
|
|
729
|
+ for(i=0; i<cnt; ++i)
|
|
730
|
+ if( cmCsvInsertTextColAfter(p->csvH,*leftCellPtrPtr,leftCellPtrPtr,0,0) != kOkCsvRC )
|
|
731
|
+ return cmErrMsg(&p->err,kCsvFailXsRC,"CSV output failed on blank column.");
|
|
732
|
+
|
|
733
|
+ return kOkCsvRC;
|
|
734
|
+}
|
|
735
|
+
|
|
736
|
+cmXsRC_t _cmXScoreWriteCsvRow(
|
|
737
|
+ cmXScore_t* p,
|
|
738
|
+ unsigned rowIdx,
|
|
739
|
+ unsigned bar,
|
|
740
|
+ const cmChar_t* sectionStr,
|
|
741
|
+ const cmChar_t* opCodeStr,
|
|
742
|
+ double dsecs,
|
|
743
|
+ double secs,
|
|
744
|
+ unsigned d0,
|
|
745
|
+ unsigned d1,
|
|
746
|
+ unsigned pitch,
|
|
747
|
+ double frac,
|
|
748
|
+ unsigned flags )
|
|
749
|
+{
|
|
750
|
+ cmXsRC_t rc = kOkXsRC;
|
|
751
|
+ cmCsvCell_t* lcp = NULL;
|
|
752
|
+
|
|
753
|
+ // append an empty row to the CSV object
|
|
754
|
+ if( cmCsvAppendRow( p->csvH, &lcp, cmCsvInsertSymUInt(p->csvH, rowIdx ), 0, 0 ) != kOkCsvRC )
|
|
755
|
+ {
|
|
756
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV append row failed.");
|
|
757
|
+ goto errLabel;
|
|
758
|
+ }
|
|
759
|
+
|
|
760
|
+ /*
|
|
761
|
+ // col 0 : blanks
|
|
762
|
+ if( cmCsvInsertUIntColAfter(p->csvH, lcp, &lcp, rowIdx, 0 ) != kOkCsvRC )
|
|
763
|
+ {
|
|
764
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV output row index failed.");
|
|
765
|
+ goto errLabel;
|
|
766
|
+ }
|
|
767
|
+ */
|
|
768
|
+
|
|
769
|
+ // cols 1,2
|
|
770
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,2,&lcp)) != kOkXsRC )
|
|
771
|
+ goto errLabel;
|
|
772
|
+
|
|
773
|
+ // col 3 : output the opcode
|
|
774
|
+ if( cmCsvInsertTextColAfter(p->csvH,lcp,&lcp,opCodeStr,0) != kOkCsvRC )
|
|
775
|
+ {
|
|
776
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on opcode label.");
|
|
777
|
+ goto errLabel;
|
|
778
|
+ }
|
|
779
|
+
|
|
780
|
+ // col 4 : dsecs
|
|
781
|
+ if( cmCsvInsertDoubleColAfter(p->csvH,lcp,&lcp,dsecs,0) != kOkCsvRC )
|
|
782
|
+ {
|
|
783
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 'dsecs'.");
|
|
784
|
+ goto errLabel;
|
|
785
|
+ }
|
|
786
|
+
|
|
787
|
+ // col 5 : secs
|
|
788
|
+ if( cmCsvInsertDoubleColAfter(p->csvH,lcp,&lcp,secs,0) != kOkCsvRC )
|
|
789
|
+ {
|
|
790
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 'secs'.");
|
|
791
|
+ goto errLabel;
|
|
792
|
+ }
|
|
793
|
+
|
|
794
|
+ // cols 6,7,8 blanks
|
|
795
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,3,&lcp)) != kOkXsRC )
|
|
796
|
+ goto errLabel;
|
|
797
|
+
|
|
798
|
+ // col 9 : d0
|
|
799
|
+ if( cmCsvInsertUIntColAfter(p->csvH,lcp,&lcp,d0,0) != kOkCsvRC )
|
|
800
|
+ {
|
|
801
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 'd0'.");
|
|
802
|
+ goto errLabel;
|
|
803
|
+ }
|
|
804
|
+
|
|
805
|
+ // col 10 : d1
|
|
806
|
+ if( cmCsvInsertUIntColAfter(p->csvH,lcp,&lcp,d1,0) != kOkCsvRC )
|
|
807
|
+ {
|
|
808
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 'd1'.");
|
|
809
|
+ goto errLabel;
|
|
810
|
+ }
|
|
811
|
+
|
|
812
|
+ // col 11 : pitch
|
|
813
|
+ if( cmCsvInsertUIntColAfter(p->csvH,lcp,&lcp,pitch,0) != kOkCsvRC )
|
|
814
|
+ {
|
|
815
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 'pitch'.");
|
|
816
|
+ goto errLabel;
|
|
817
|
+ }
|
|
818
|
+
|
|
819
|
+ // col 12 : blanks
|
|
820
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,1 + (cmIsFlag(flags,kBarXsFl) ? 0 : 1), &lcp)) != kOkXsRC )
|
|
821
|
+ goto errLabel;
|
|
822
|
+
|
|
823
|
+ // col 13 : bar number
|
|
824
|
+ if( cmIsFlag(flags,kBarXsFl) )
|
|
825
|
+ {
|
|
826
|
+ if( cmCsvInsertUIntColAfter(p->csvH,lcp,&lcp,bar,0) != kOkCsvRC )
|
|
827
|
+ {
|
|
828
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 'pitch'.");
|
|
829
|
+ goto errLabel;
|
|
830
|
+ }
|
|
831
|
+ }
|
|
832
|
+
|
|
833
|
+ // col 14 : skip (blank for now)
|
|
834
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,1,&lcp)) != kOkXsRC )
|
|
835
|
+ goto errLabel;
|
|
836
|
+
|
|
837
|
+ // col 15: even
|
|
838
|
+ if( cmCsvInsertTextColAfter(p->csvH,lcp,&lcp,cmIsFlag(flags,kEvenXsFl) ? "e" : "",0) != kOkCsvRC )
|
|
839
|
+ {
|
|
840
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on eveness flag label.");
|
|
841
|
+ goto errLabel;
|
|
842
|
+ }
|
|
843
|
+
|
|
844
|
+ // col 16: grace
|
|
845
|
+ if( cmCsvInsertTextColAfter(p->csvH,lcp,&lcp,cmIsFlag(flags,kGraceXsFl) ? "g" : "",0) != kOkCsvRC )
|
|
846
|
+ {
|
|
847
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on eveness flag label.");
|
|
848
|
+ goto errLabel;
|
|
849
|
+ }
|
|
850
|
+
|
|
851
|
+ // col 17: tempo
|
|
852
|
+ if( cmCsvInsertTextColAfter(p->csvH,lcp,&lcp,cmIsFlag(flags,kTempoXsFl) ? "t" : "",0) != kOkCsvRC )
|
|
853
|
+ {
|
|
854
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on eveness flag label.");
|
|
855
|
+ goto errLabel;
|
|
856
|
+ }
|
|
857
|
+
|
|
858
|
+ // col 18: frac
|
|
859
|
+ if( frac == 0 )
|
|
860
|
+ {
|
|
861
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,1,&lcp)) != kOkXsRC )
|
|
862
|
+ goto errLabel;
|
|
863
|
+ }
|
|
864
|
+ else
|
|
865
|
+ {
|
|
866
|
+ if( cmCsvInsertDoubleColAfter(p->csvH,lcp,&lcp,1.0/frac,0) != kOkCsvRC )
|
|
867
|
+ {
|
|
868
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on 't frac'.");
|
|
869
|
+ goto errLabel;
|
|
870
|
+ }
|
|
871
|
+ }
|
|
872
|
+
|
|
873
|
+ // col 19: dynamic marking (blank for now)
|
|
874
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,1,&lcp)) != kOkXsRC )
|
|
875
|
+ goto errLabel;
|
|
876
|
+
|
|
877
|
+ // col 20: section
|
|
878
|
+ if( cmCsvInsertTextColAfter(p->csvH,lcp,&lcp,cmIsFlag(flags,kSectionXsFl) ? sectionStr : "",0) != kOkCsvRC )
|
|
879
|
+ {
|
|
880
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"CSV insert failed on eveness flag label.");
|
|
881
|
+ goto errLabel;
|
|
882
|
+ }
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+ // col 21, 22 : recd-play, remark (blank for now)
|
|
886
|
+ if((rc = _cmXScoreWriteCsvBlankCols(p,2,&lcp)) != kOkXsRC )
|
|
887
|
+ goto errLabel;
|
|
888
|
+
|
|
889
|
+ errLabel:
|
|
890
|
+ return rc;
|
|
891
|
+
|
|
892
|
+}
|
|
893
|
+
|
|
894
|
+cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, const cmChar_t* csvFn )
|
|
895
|
+{
|
|
896
|
+ cmXsRC_t rc = kOkXsRC;
|
|
897
|
+ cmXScore_t* p = _cmXScoreHandleToPtr(h);
|
|
898
|
+ unsigned rowIdx = 1;
|
|
899
|
+ double tpqn = 0; // ticks per quarter note
|
|
900
|
+ double tps = 0; // ticks per second
|
|
901
|
+ double sec = 0; // current time in seconds
|
|
902
|
+ const cmChar_t* sectionIdStr = NULL;
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+ if( !cmCsvIsValid(p->csvH) )
|
|
906
|
+ return cmErrMsg(&p->err,kCsvFailXsRC,"The CSV output object is not initialized.");
|
|
907
|
+
|
|
908
|
+ if((rc = _cmXScoreWriteCsvHdr( p )) != kOkXsRC )
|
|
909
|
+ goto errLabel;
|
|
910
|
+
|
|
911
|
+ cmXsPart_t* pp = p->partL;
|
|
912
|
+ for(; pp!=NULL; pp=pp->link)
|
|
913
|
+ {
|
|
914
|
+ cmXsMeas_t* mp = pp->measL;
|
|
915
|
+ for(; mp!=NULL; mp=mp->link)
|
|
916
|
+ {
|
|
917
|
+ if( mp->divisions != 0 )
|
|
918
|
+ tpqn = mp->divisions;
|
|
919
|
+
|
|
920
|
+ cmXsNote_t* np = mp->noteL;
|
|
921
|
+
|
|
922
|
+ double sec0 = sec;
|
|
923
|
+
|
|
924
|
+ for(; np!=NULL; np=np->slink)
|
|
925
|
+ {
|
|
926
|
+
|
|
927
|
+ //
|
|
928
|
+ if( cmIsFlag(np->flags,kMetronomeXsFl) )
|
|
929
|
+ {
|
|
930
|
+ double bpm = np->duration;
|
|
931
|
+ double bps = bpm / 60.0;
|
|
932
|
+ tps = bps * tpqn;
|
|
933
|
+ }
|
|
934
|
+
|
|
935
|
+ double meas_sec = tps == 0 ? 0 : np->tick / tps;
|
|
936
|
+ double sec1 = sec + meas_sec;
|
|
937
|
+ double dsecs = sec1 - sec0;
|
|
938
|
+ sec0 = sec1;
|
|
939
|
+
|
|
940
|
+ // if this is a section event
|
|
941
|
+ if( cmIsFlag(np->flags,kSectionXsFl) )
|
|
942
|
+ sectionIdStr = np->tvalue;
|
|
943
|
+
|
|
944
|
+ // if this is a bar event
|
|
945
|
+ if( cmIsFlag(np->flags,kBarXsFl) )
|
|
946
|
+ {
|
|
947
|
+ _cmXScoreWriteCsvRow(p,rowIdx,mp->number,NULL,"bar",dsecs,sec1,0,0,0,0,np->flags);
|
|
948
|
+ }
|
|
949
|
+ else
|
|
950
|
+
|
|
951
|
+ // if this is a pedal event
|
|
952
|
+ if( cmIsFlag(np->flags,kPedalDnXsFl|kPedalUpXsFl|kPedalUpDnXsFl) )
|
|
953
|
+ {
|
|
954
|
+ unsigned d0 = 64; // pedal MIDI ctl id
|
|
955
|
+ unsigned d1 = cmIsFlag(np->flags,kPedalDnXsFl) ? 64 : 0; // pedal-dn: d1>=64 pedal-up:<64
|
|
956
|
+ _cmXScoreWriteCsvRow(p,rowIdx,mp->number,NULL,"ctl",dsecs,sec1,d0,d1,0,0,np->flags);
|
|
957
|
+ }
|
|
958
|
+ else
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+ // if this is a sounding note event
|
|
962
|
+ if( cmIsNotFlag(np->flags,kRestXsFl) )
|
|
963
|
+ {
|
|
964
|
+ double frac = np->rvalue + (cmIsFlag(np->flags,kDotXsFl) ? (np->rvalue/2) : 0);
|
|
965
|
+
|
|
966
|
+ //
|
|
967
|
+ _cmXScoreWriteCsvRow(p,rowIdx,mp->number,sectionIdStr,"non",dsecs,sec1,0,0,np->pitch,frac,np->flags);
|
|
968
|
+ sectionIdStr = NULL;
|
|
969
|
+ }
|
|
970
|
+
|
|
971
|
+ rowIdx += 1;
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+ }
|
|
975
|
+
|
|
976
|
+ sec = sec0;
|
|
977
|
+ }
|
|
978
|
+
|
|
979
|
+ }
|
|
980
|
+
|
|
981
|
+ if( cmCsvWrite( p->csvH, csvFn ) != kOkCsvRC )
|
|
982
|
+ rc = cmErrMsg(&p->err,kCsvFailXsRC,"The CSV output write failed on file '%s'.",csvFn);
|
|
983
|
+
|
|
984
|
+ errLabel:
|
|
985
|
+ return rc;
|
|
986
|
+}
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+void cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
|
|
990
|
+{
|
|
991
|
+ cmXScore_t* p = _cmXScoreHandleToPtr(h);
|
668
|
992
|
cmXsPart_t* pp = p->partL;
|
|
993
|
+
|
669
|
994
|
for(; pp!=NULL; pp=pp->link)
|
670
|
995
|
{
|
671
|
996
|
cmRptPrintf(rpt,"Part:%s\n",pp->idStr);
|
|
@@ -708,6 +1033,7 @@ cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
|
708
|
1033
|
if((rc = cmXScoreInitialize( ctx, &h, fn)) != kOkXsRC )
|
709
|
1034
|
return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
|
710
|
1035
|
|
|
1036
|
+ cmXScoreWriteCsv(h,"/home/kevin/temp/a0.csv");
|
711
|
1037
|
cmXScoreReport(h,&ctx->rpt,true);
|
712
|
1038
|
|
713
|
1039
|
return cmXScoreFinalize(&h);
|