|
@@ -1303,17 +1303,186 @@ cmXsRC_t cmXScoreFinalize( cmXsH_t* hp )
|
1303
|
1303
|
return rc;
|
1304
|
1304
|
}
|
1305
|
1305
|
|
1306
|
|
-
|
1307
|
1306
|
bool cmXScoreIsValid( cmXsH_t h )
|
1308
|
1307
|
{ return h.h != NULL; }
|
1309
|
1308
|
|
1310
|
|
-/*
|
|
1309
|
+//-------------------------------------------------------------------------------------------
|
|
1310
|
+typedef struct
|
|
1311
|
+{
|
|
1312
|
+ unsigned voice;
|
|
1313
|
+ unsigned locIdx;
|
|
1314
|
+ unsigned tick;
|
|
1315
|
+ unsigned durtn;
|
|
1316
|
+ float rval;
|
|
1317
|
+ unsigned midi;
|
|
1318
|
+ cmXsNote_t* note;
|
|
1319
|
+} cmXsReorder_t;
|
|
1320
|
+
|
|
1321
|
+cmXsNote_t* _cmXsReorderFindNote( cmXScore_t* p, unsigned measNumb, const cmXsReorder_t* r )
|
|
1322
|
+{
|
|
1323
|
+ cmXsPart_t* pp = p->partL;
|
|
1324
|
+ for(; pp!=NULL; pp=pp->link)
|
|
1325
|
+ {
|
|
1326
|
+ cmXsMeas_t* mp = pp->measL;
|
|
1327
|
+ for(; mp!=NULL; mp=mp->link)
|
|
1328
|
+ if( mp->number == measNumb)
|
|
1329
|
+ {
|
|
1330
|
+ cmXsNote_t* np = mp->noteL;
|
|
1331
|
+ for(; np!=NULL; np=np->slink)
|
|
1332
|
+ if( np->voice->id == r->voice &&
|
|
1333
|
+ np->locIdx == r->locIdx &&
|
|
1334
|
+ np->tick == r->tick &&
|
|
1335
|
+ np->duration == r->durtn &&
|
|
1336
|
+ np->rvalue == r->rval &&
|
|
1337
|
+ np->pitch == r->midi )
|
|
1338
|
+ {
|
|
1339
|
+ return np;
|
|
1340
|
+ }
|
|
1341
|
+ }
|
|
1342
|
+ }
|
|
1343
|
+
|
|
1344
|
+ cmErrMsg(&p->err,kSyntaxErrorXsRC,"Reorder note not found.");
|
|
1345
|
+ return NULL;
|
|
1346
|
+}
|
|
1347
|
+
|
|
1348
|
+cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, unsigned measNumb, cmXsReorder_t* rV, unsigned rN )
|
|
1349
|
+{
|
|
1350
|
+ unsigned i;
|
|
1351
|
+
|
|
1352
|
+ if( rN == 0 )
|
|
1353
|
+ return kOkXsRC;
|
|
1354
|
+
|
|
1355
|
+ // set the 'note' field on each cmXsReorder_t record
|
|
1356
|
+ for(i=0; i<rN; ++i)
|
|
1357
|
+ if((rV[i].note = _cmXsReorderFindNote(p,measNumb,rV+i)) == NULL )
|
|
1358
|
+ return kSyntaxErrorXsRC;
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+ cmXsMeas_t* mp = rV[0].note->meas;
|
|
1362
|
+ cmXsNote_t* n0p = NULL;
|
|
1363
|
+
|
|
1364
|
+ assert( mp->number == measNumb );
|
|
1365
|
+
|
|
1366
|
+ // Reassign the slink of the cmXsNote_t records in this measure
|
|
1367
|
+ // according to their order in rV[].
|
|
1368
|
+ for(i=0; i<rN; ++i)
|
|
1369
|
+ {
|
|
1370
|
+ if( n0p == NULL )
|
|
1371
|
+ mp->noteL = rV[i].note;
|
|
1372
|
+ else
|
|
1373
|
+ n0p->slink = rV[i].note;
|
|
1374
|
+
|
|
1375
|
+ n0p = rV[i].note;
|
|
1376
|
+ n0p->slink = NULL;
|
|
1377
|
+ }
|
|
1378
|
+
|
|
1379
|
+ return kOkXsRC;
|
|
1380
|
+
|
|
1381
|
+}
|
|
1382
|
+
|
|
1383
|
+cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn )
|
|
1384
|
+{
|
|
1385
|
+ typedef enum { kFindMeasStId, kFindEventStId, kReadEventStId } stateId_t;
|
|
1386
|
+
|
|
1387
|
+ cmXsRC_t rc = kOkXsRC;
|
|
1388
|
+ cmXScore_t* p = _cmXScoreHandleToPtr(h);
|
|
1389
|
+ cmFileH_t fH = cmFileNullHandle;
|
|
1390
|
+ cmChar_t* b = NULL;
|
|
1391
|
+ unsigned bN = 0;
|
|
1392
|
+ unsigned ln = 0;
|
|
1393
|
+ stateId_t stateId = kFindMeasStId;
|
|
1394
|
+ unsigned rN = 1024;
|
|
1395
|
+ unsigned ri = 0;
|
|
1396
|
+ unsigned measNumb = 0;
|
|
1397
|
+ cmXsReorder_t rV[ rN ];
|
|
1398
|
+
|
|
1399
|
+ if( cmFileOpen(&fH,fn,kReadFileFl,p->err.rpt) != kOkFileRC )
|
|
1400
|
+ {
|
|
1401
|
+ rc = cmErrMsg(&p->err,kFileFailXsRC,"The reordering file '%s' could not be opened.",cmStringNullGuard(fn));
|
|
1402
|
+ return rc;
|
|
1403
|
+ }
|
|
1404
|
+
|
|
1405
|
+ for(; cmFileGetLineAuto(fH,&b,&bN)==kOkFileRC; ++ln)
|
|
1406
|
+ {
|
|
1407
|
+ switch( stateId )
|
|
1408
|
+ {
|
|
1409
|
+ case kFindEventStId:
|
|
1410
|
+ {
|
|
1411
|
+ unsigned voice,loc;
|
|
1412
|
+ if( sscanf(b,"%i %i",&voice,&loc) != 2 )
|
|
1413
|
+ continue;
|
|
1414
|
+
|
|
1415
|
+ stateId = kReadEventStId;
|
|
1416
|
+ }
|
|
1417
|
+ // fall through
|
|
1418
|
+
|
|
1419
|
+ case kReadEventStId:
|
|
1420
|
+ {
|
|
1421
|
+ cmXsReorder_t r;
|
|
1422
|
+ char pitchStr[4];
|
|
1423
|
+
|
|
1424
|
+ if( sscanf(b,"%i %i %i %i %f %c%c%c",&r.voice,&r.locIdx,&r.tick,&r.durtn,&r.rval,pitchStr,pitchStr+1,pitchStr+2) == 8 )
|
|
1425
|
+ {
|
|
1426
|
+ pitchStr[3] = 0;
|
|
1427
|
+ if( !isdigit(pitchStr[2]) )
|
|
1428
|
+ r.midi = 0;
|
|
1429
|
+ else
|
|
1430
|
+ {
|
|
1431
|
+ if( pitchStr[1] == ' ')
|
|
1432
|
+ {
|
|
1433
|
+ pitchStr[1] = pitchStr[2];
|
|
1434
|
+ pitchStr[2] = 0;
|
|
1435
|
+ }
|
|
1436
|
+
|
|
1437
|
+ r.midi = cmSciPitchToMidi(pitchStr);
|
|
1438
|
+ }
|
|
1439
|
+
|
|
1440
|
+ assert( ri < rN );
|
|
1441
|
+ rV[ri++] = r;
|
|
1442
|
+
|
|
1443
|
+ continue;
|
|
1444
|
+ }
|
|
1445
|
+
|
|
1446
|
+ if((rc = _cmXScoreReorderMeas(p, measNumb, rV, ri )) != kOkXsRC )
|
|
1447
|
+ goto errLabel;
|
|
1448
|
+
|
|
1449
|
+ ri = 0;
|
|
1450
|
+
|
|
1451
|
+ stateId = kFindMeasStId;
|
|
1452
|
+ // fall through
|
|
1453
|
+ }
|
|
1454
|
+
|
|
1455
|
+ case kFindMeasStId:
|
|
1456
|
+ {
|
|
1457
|
+ char colon;
|
|
1458
|
+ if( sscanf(b,"%i %c",&measNumb,&colon) == 2 && colon == ':' )
|
|
1459
|
+ {
|
|
1460
|
+ //printf("meas: %i \n",measNumb);
|
|
1461
|
+ stateId = kFindEventStId;
|
|
1462
|
+
|
|
1463
|
+ }
|
|
1464
|
+ }
|
|
1465
|
+ break;
|
|
1466
|
+ }
|
|
1467
|
+
|
|
1468
|
+ }
|
|
1469
|
+
|
|
1470
|
+ errLabel:
|
|
1471
|
+ cmFileClose(&fH);
|
|
1472
|
+ cmMemFree(b);
|
|
1473
|
+ return rc;
|
|
1474
|
+}
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+/*-------------------------------------------------------------------------------------------
|
1311
|
1478
|
Dynamics File Format:
|
1312
|
1479
|
<blk>*
|
1313
|
1480
|
<blk> -> <hdr-line> <note-line> <blank-line>
|
1314
|
1481
|
<hdr-line> -> <int> "|"
|
1315
|
1482
|
<note-line> -> <float> <sci-pitch> ":" <int>
|
1316
|
1483
|
<sci-pitch> -> <A-G><#|b|<space>
|
|
1484
|
+
|
|
1485
|
+See imag_themes/scores/dyn.txt for an example.
|
1317
|
1486
|
*/
|
1318
|
1487
|
|
1319
|
1488
|
typedef struct cmXsDyn_str
|
|
@@ -1877,10 +2046,22 @@ void cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
|
1877
|
2046
|
{
|
1878
|
2047
|
|
1879
|
2048
|
const cmXsNote_t* note = meas->noteL;
|
|
2049
|
+ unsigned t0 = 0;
|
|
2050
|
+ unsigned t1 = 0;
|
1880
|
2051
|
for(; note!=NULL; note=note->slink)
|
1881
|
2052
|
{
|
1882
|
2053
|
_cmXScoreReportNote(rpt,note);
|
1883
|
|
-
|
|
2054
|
+
|
|
2055
|
+ t1 = note->slink==NULL ? note->tick : note->slink->tick;
|
|
2056
|
+
|
|
2057
|
+ if( !(t0 <= note->tick && note->tick <= t1) )
|
|
2058
|
+ {
|
|
2059
|
+ cmRptPrintf(rpt," +");
|
|
2060
|
+ }
|
|
2061
|
+
|
|
2062
|
+ t0 = note->tick;
|
|
2063
|
+
|
|
2064
|
+
|
1884
|
2065
|
if( note->slink!=NULL || note->voice->id==0)
|
1885
|
2066
|
cmRptPrintf(rpt,"\n");
|
1886
|
2067
|
else
|
|
@@ -1944,8 +2125,11 @@ cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* midi
|
1944
|
2125
|
if((rc = cmXScoreInitialize( ctx, &h, xmlFn, midiFn)) != kOkXsRC )
|
1945
|
2126
|
return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
|
1946
|
2127
|
|
|
2128
|
+ //if( dynFn != NULL )
|
|
2129
|
+ // cmXScoreInsertDynamics(h, dynFn );
|
|
2130
|
+
|
1947
|
2131
|
if( dynFn != NULL )
|
1948
|
|
- cmXScoreInsertDynamics(h, dynFn );
|
|
2132
|
+ cmXScoreReorder(h,dynFn);
|
1949
|
2133
|
|
1950
|
2134
|
if( outFn != NULL )
|
1951
|
2135
|
cmXScoreWriteCsv(h,outFn);
|