|
@@ -894,7 +894,7 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
|
894
|
894
|
|
895
|
895
|
case kMidiChMdId:
|
896
|
896
|
if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.bVal))) == kOkMfRC )
|
897
|
|
- rc = _cmMidiFileWrite8(mfp,tmp->u.bVal);
|
|
897
|
+ rc = _cmMidiFileWrite8(mfp,tmp->u.bVal);
|
898
|
898
|
break;
|
899
|
899
|
|
900
|
900
|
case kEndOfTrkMdId:
|
|
@@ -1304,182 +1304,13 @@ typedef struct _cmMidiVoice_str
|
1304
|
1304
|
} _cmMidiVoice_t;
|
1305
|
1305
|
|
1306
|
1306
|
|
1307
|
|
-void _cmMidFileCalcNoteDurationReleaseNote( _cmMidiVoice_t** listPtrPtr, _cmMidiVoice_t* pp, _cmMidiVoice_t* vp )
|
1308
|
|
-{
|
1309
|
|
- assert( (pp==NULL && vp==*listPtrPtr) || pp->link==vp);
|
1310
|
|
-
|
1311
|
|
- // store the duration of the note into the track msg
|
1312
|
|
- // assoc'd with the note-on msg
|
1313
|
|
- cmMidiChMsg_t* cmp = (cmMidiChMsg_t*)vp->mp->u.chMsgPtr; // cast away const
|
1314
|
|
- cmp->durMicros = vp->durMicros;
|
1315
|
|
-
|
1316
|
|
- _cmMidiVoice_t* np = vp->link;
|
1317
|
|
-
|
1318
|
|
- // release the voice msg
|
1319
|
|
- cmMemFree(vp);
|
1320
|
|
-
|
1321
|
|
- // unlink the active voice msg
|
1322
|
|
- if( pp == NULL )
|
1323
|
|
- *listPtrPtr = np;
|
1324
|
|
- else
|
1325
|
|
- pp->link = np;
|
1326
|
|
-
|
1327
|
|
-}
|
1328
|
|
-
|
1329
|
|
-void _cmMidiFileCalcNoteDurationsAllocVoice( _cmMidiVoice_t** listPtrPtr, cmMidiTrackMsg_t* mp, bool sustainFl )
|
1330
|
|
-{
|
1331
|
|
- _cmMidiVoice_t* vp = cmMemAllocZ(_cmMidiVoice_t,1);
|
1332
|
|
- vp->mp = mp;
|
1333
|
|
- vp->sustainFl = sustainFl;
|
1334
|
|
- vp->link = *listPtrPtr;
|
1335
|
|
- *listPtrPtr = vp;
|
1336
|
|
-}
|
1337
|
|
-
|
1338
|
|
-void cmMidiFileCalcNoteDurations2( cmMidiFileH_t h )
|
1339
|
|
-{
|
1340
|
|
- _cmMidiFile_t* p;
|
1341
|
|
-
|
1342
|
|
- if((p = _cmMidiFileHandleToPtr(h)) == NULL )
|
1343
|
|
- return;
|
1344
|
|
-
|
1345
|
|
- if( p->msgN == 0 )
|
1346
|
|
- return;
|
1347
|
|
-
|
1348
|
|
- unsigned mi = cmInvalidId;
|
1349
|
|
- _cmMidiVoice_t* list = NULL; // list of active voices
|
1350
|
|
- _cmMidiVoice_t* vp = NULL;
|
1351
|
|
- cmMidiTrackMsg_t* sustainPedalDownMsg = NULL;
|
1352
|
|
- bool sustainFlagV[ kMidiChCnt ];
|
1353
|
|
-
|
1354
|
|
- // clear the sustain pedal flag
|
1355
|
|
- for(mi=0; mi<kMidiChCnt; ++mi)
|
1356
|
|
- sustainFlagV[mi]=false;
|
1357
|
|
-
|
1358
|
|
- for(mi=0; mi<p->msgN; ++mi)
|
1359
|
|
- {
|
1360
|
|
- cmMidiTrackMsg_t* mp = p->msgV[mi];
|
1361
|
|
-
|
1362
|
|
- unsigned d_amicro = 0;
|
1363
|
|
- if( mi > 0 )
|
1364
|
|
- {
|
1365
|
|
- assert( mp->amicro >= p->msgV[mi-1]->amicro );
|
1366
|
|
- d_amicro = mp->amicro - p->msgV[mi-1]->amicro;
|
1367
|
|
- }
|
1368
|
|
-
|
1369
|
|
- // update the duration of the sounding notes
|
1370
|
|
- for(vp = list; vp!=NULL; vp=vp->link)
|
1371
|
|
- vp->durMicros += d_amicro;
|
1372
|
|
-
|
1373
|
|
- // update the sustain pedal duration
|
1374
|
|
- if( sustainPedalDownMsg != NULL )
|
1375
|
|
- ((cmMidiChMsg_t*)(sustainPedalDownMsg->u.chMsgPtr))->durMicros += d_amicro; // cast away const
|
1376
|
|
-
|
1377
|
|
- //
|
1378
|
|
- // If this is sustain pedal msg
|
1379
|
|
- //
|
1380
|
|
- if( mp->status==kCtlMdId && mp->u.chMsgPtr->d0 == kSustainCtlMdId )
|
1381
|
|
- {
|
1382
|
|
- unsigned chIdx = mp->u.chMsgPtr->ch;
|
1383
|
|
- assert( chIdx < kMidiChCnt );
|
1384
|
|
-
|
1385
|
|
- // set the state of the sustain pedal flags
|
1386
|
|
- sustainFlagV[chIdx] = mp->u.chMsgPtr->d1 >= 64;
|
1387
|
|
-
|
1388
|
|
- // if the pedal went down ...
|
1389
|
|
- if( sustainFlagV[chIdx] )
|
1390
|
|
- {
|
1391
|
|
-
|
1392
|
|
- if( sustainPedalDownMsg != NULL )
|
1393
|
|
- {
|
1394
|
|
- // TODO: the correct way to handle this is to maintain multiple sustain pedals
|
1395
|
|
- //cmErrMsg(&p->err,kSustainPedalMfRC,"Sustain pedal down with no intervening sustain pedal up.");
|
1396
|
|
- }
|
1397
|
|
- else
|
1398
|
|
- {
|
1399
|
|
- sustainPedalDownMsg = mp;
|
1400
|
|
- ((cmMidiChMsg_t*)(sustainPedalDownMsg->u.chMsgPtr))->durMicros = 0; // cast away const
|
1401
|
|
- }
|
1402
|
|
-
|
1403
|
|
- _cmMidiFileCalcNoteDurationsAllocVoice( &list, mp, true );
|
1404
|
|
- }
|
1405
|
|
- else // ... if the pedal went up
|
1406
|
|
- {
|
1407
|
|
-
|
1408
|
|
- sustainPedalDownMsg = NULL;
|
1409
|
|
-
|
1410
|
|
- // ... then release sustaining notes
|
1411
|
|
- _cmMidiVoice_t* pp = NULL;
|
1412
|
|
- for(vp=list; vp != NULL; )
|
1413
|
|
- {
|
1414
|
|
- _cmMidiVoice_t* np = vp->link;
|
1415
|
|
- if( vp->sustainFl && (vp->mp->u.chMsgPtr->ch == chIdx) )
|
1416
|
|
- _cmMidFileCalcNoteDurationReleaseNote(&list,pp,vp);
|
1417
|
|
- else
|
1418
|
|
- pp = vp;
|
1419
|
|
-
|
1420
|
|
- vp = np;
|
1421
|
|
- }
|
1422
|
|
- }
|
1423
|
|
- }
|
1424
|
|
-
|
1425
|
|
- //
|
1426
|
|
- // if this is a note-on msg
|
1427
|
|
- //
|
1428
|
|
- if( mp->status==kNoteOnMdId && mp->u.chMsgPtr->d1>0 )
|
1429
|
|
- {
|
1430
|
|
- _cmMidiFileCalcNoteDurationsAllocVoice( &list, mp, false );
|
1431
|
|
- }
|
1432
|
|
- else
|
1433
|
|
- //
|
1434
|
|
- // if this is a note-off msg
|
1435
|
|
- //
|
1436
|
|
- if( (mp->status==kNoteOnMdId && mp->u.chMsgPtr->d1==0) || (mp->status==kNoteOffMdId) )
|
1437
|
|
- {
|
1438
|
|
- _cmMidiVoice_t* pp = NULL;
|
1439
|
|
- unsigned chIdx = mp->u.chMsgPtr->ch;
|
1440
|
|
- assert( chIdx < kMidiChCnt );
|
1441
|
|
-
|
1442
|
|
-
|
1443
|
|
- // for each active voice
|
1444
|
|
- for(vp=list; vp!=NULL; vp=vp->link )
|
1445
|
|
- {
|
1446
|
|
- // if this active voice ch/pitch matches the note-off msg ch pitch
|
1447
|
|
- if( (vp->mp->u.chMsgPtr->d0==mp->u.chMsgPtr->d0) && (vp->mp->u.chMsgPtr->ch==chIdx) )
|
1448
|
|
- {
|
1449
|
|
- // if the sustain pedal is down for this channel - then defer turning the note off
|
1450
|
|
- if( sustainFlagV[chIdx] )
|
1451
|
|
- vp->sustainFl = true;
|
1452
|
|
- else
|
1453
|
|
- _cmMidFileCalcNoteDurationReleaseNote(&list,pp,vp);
|
1454
|
|
- break;
|
1455
|
|
- }
|
1456
|
|
-
|
1457
|
|
- pp = vp;
|
1458
|
|
- } // end for
|
1459
|
|
- } // end if
|
1460
|
|
-
|
1461
|
|
- } // end-for
|
1462
|
|
-
|
1463
|
|
-
|
1464
|
|
- // check for hung notes
|
1465
|
|
- _cmMidiVoice_t* np = NULL;
|
1466
|
|
- vp = list;
|
1467
|
|
- while( vp != NULL )
|
1468
|
|
- {
|
1469
|
|
- np = vp->link;
|
1470
|
|
-
|
1471
|
|
- if( cmMidiIsNoteOn(vp->mp->status) == false )
|
1472
|
|
- cmErrMsg(&p->err,kMissingNoteOffMfRC,"Missing note-off for note-on:%s",cmMidiToSciPitch(vp->mp->u.chMsgPtr->d0,NULL,0));
|
1473
|
|
-
|
1474
|
|
- cmMemFree(vp);
|
1475
|
|
- vp = np;
|
1476
|
|
- }
|
1477
|
|
-}
|
1478
|
|
-
|
1479
|
1307
|
void _cmMidiFileSetDur( cmMidiTrackMsg_t* m0, cmMidiTrackMsg_t* m1 )
|
1480
|
1308
|
{
|
1481
|
1309
|
// calculate the duration of the sounding note
|
1482
|
1310
|
((cmMidiChMsg_t*)m0->u.chMsgPtr)->durMicros = m1->amicro - m0->amicro;
|
|
1311
|
+
|
|
1312
|
+ // set the note-off msg pointer
|
|
1313
|
+ ((cmMidiChMsg_t*)m0->u.chMsgPtr)->end = m1;
|
1483
|
1314
|
}
|
1484
|
1315
|
|
1485
|
1316
|
bool _cmMidiFileCalcNoteDur( cmMidiTrackMsg_t* m0, cmMidiTrackMsg_t* m1, int noteGateFl, int sustainGateFl, bool sostGateFl )
|
|
@@ -1628,6 +1459,7 @@ void cmMidiFileCalcNoteDurations( cmMidiFileH_t h )
|
1628
|
1459
|
if( sustV[ch] != NULL )
|
1629
|
1460
|
{
|
1630
|
1461
|
_cmMidiFileSetDur(sustV[ch],m);
|
|
1462
|
+ ((cmMidiChMsg_t*)sustV[ch]->u.chMsgPtr)->end = m; // set the pedal-up msg ptr. in the pedal-down msg.
|
1631
|
1463
|
sustV[ch] = NULL;
|
1632
|
1464
|
}
|
1633
|
1465
|
}
|
|
@@ -1635,7 +1467,7 @@ void cmMidiFileCalcNoteDurations( cmMidiFileH_t h )
|
1635
|
1467
|
}
|
1636
|
1468
|
else
|
1637
|
1469
|
|
1638
|
|
- // This is a sostenuto-pedal down msg
|
|
1470
|
+ // This is a sostenuto pedal-down msg
|
1639
|
1471
|
if( cmMidiFileIsSostenutoPedalDown(m) )
|
1640
|
1472
|
{
|
1641
|
1473
|
// if the sustain channel is already down
|
|
@@ -1651,7 +1483,7 @@ void cmMidiFileCalcNoteDurations( cmMidiFileH_t h )
|
1651
|
1483
|
}
|
1652
|
1484
|
else
|
1653
|
1485
|
|
1654
|
|
- // This is a sostenuto-pedal up msg
|
|
1486
|
+ // This is a sostenuto pedal-up msg
|
1655
|
1487
|
if( cmMidiFileIsSostenutoPedalUp(m) )
|
1656
|
1488
|
{
|
1657
|
1489
|
// if the sustain channel is already up
|
|
@@ -1677,7 +1509,8 @@ void cmMidiFileCalcNoteDurations( cmMidiFileH_t h )
|
1677
|
1509
|
|
1678
|
1510
|
if( sostV[ch] != NULL )
|
1679
|
1511
|
{
|
1680
|
|
- _cmMidiFileSetDur(sostV[ch],m);
|
|
1512
|
+ _cmMidiFileSetDur(sostV[ch],m);
|
|
1513
|
+ ((cmMidiChMsg_t*)sostV[ch]->u.chMsgPtr)->end = m; // set the pedal-up msg ptr. in the pedal-down msg.
|
1681
|
1514
|
sostV[ch] = NULL;
|
1682
|
1515
|
}
|
1683
|
1516
|
|