Quellcode durchsuchen

cmMidiFile.h/c : Added cmMidiFileInsertMsg() Also rearranged code to isolate

cmMidiTrackMsg_t allocation.  These changes are not yet tested.
master
kevin vor 8 Jahren
Ursprung
Commit
5cde332add
2 geänderte Dateien mit 185 neuen und 72 gelöschten Zeilen
  1. 181
    72
      cmMidiFile.c
  2. 4
    0
      cmMidiFile.h

+ 181
- 72
cmMidiFile.c Datei anzeigen

19
 #define mfSwap32(v)  cmSwap32(v)
19
 #define mfSwap32(v)  cmSwap32(v)
20
 #endif
20
 #endif
21
 
21
 
22
-
23
-
24
 typedef struct
22
 typedef struct
25
 {
23
 {
26
   unsigned          cnt;   // count of track records
24
   unsigned          cnt;   // count of track records
160
   return kOkMfRC; 
158
   return kOkMfRC; 
161
 }
159
 }
162
 
160
 
163
-cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status, cmMidiTrackMsg_t** trkMsgPtrPtr )
161
+cmMidiTrackMsg_t* _cmMidiFileAllocMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status )
164
 {
162
 {
165
   cmMidiTrackMsg_t* tmp = (cmMidiTrackMsg_t*)_cmMidiFileMalloc(mfp, sizeof(cmMidiTrackMsg_t) );
163
   cmMidiTrackMsg_t* tmp = (cmMidiTrackMsg_t*)_cmMidiFileMalloc(mfp, sizeof(cmMidiTrackMsg_t) );
166
-  
164
+
165
+  // set the generic track record fields
166
+  tmp->dtick     = dtick;
167
+  tmp->status   = status;
168
+  tmp->metaId   = kInvalidMetaMdId;
169
+  tmp->trkIdx   = trkIdx;
170
+  tmp->byteCnt  = 0;
171
+  tmp->uid      = mfp->nextUid++;
172
+
173
+  return tmp;
174
+}
175
+
176
+cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status, cmMidiTrackMsg_t** trkMsgPtrPtr )
177
+{
178
+  cmMidiTrackMsg_t* tmp = _cmMidiFileAllocMsg( mfp, trkIdx, dtick, status );
179
+    
167
   // link new record onto track record chain
180
   // link new record onto track record chain
168
   if( mfp->trkV[trkIdx].base == NULL )
181
   if( mfp->trkV[trkIdx].base == NULL )
169
     mfp->trkV[trkIdx].base = tmp;
182
     mfp->trkV[trkIdx].base = tmp;
174
   mfp->trkV[trkIdx].cnt++;
187
   mfp->trkV[trkIdx].cnt++;
175
 
188
 
176
 
189
 
177
-  // set the generic track record fields
178
-  tmp->dtick     = dtick;
179
-  tmp->status   = status;
180
-  tmp->metaId   = kInvalidMetaMdId;
181
-  tmp->trkIdx   = trkIdx;
182
-  tmp->byteCnt  = 0;
183
   *trkMsgPtrPtr = tmp;
190
   *trkMsgPtrPtr = tmp;
184
 
191
 
185
   return kOkMfRC;
192
   return kOkMfRC;
521
   
528
   
522
 }
529
 }
523
 
530
 
531
+void _cmMidiFileLinearize( _cmMidiFile_t* mfp )
532
+{
533
+  unsigned trkIdx,i,j;
534
+  
535
+  // get the total trk msg count
536
+  mfp->msgN = 0;
537
+  for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
538
+    mfp->msgN += mfp->trkV[ trkIdx ].cnt;
539
+
540
+  // allocate the trk msg index vector: msgV[]
541
+  mfp->msgV = cmMemResizeZ(cmMidiTrackMsg_t*, mfp->msgV, mfp->msgN);
542
+
543
+  // store a pointer to every trk msg in msgV[]
544
+  for(i=0,j=0; i<mfp->trkN; ++i)
545
+  {
546
+    cmMidiTrackMsg_t* m = mfp->trkV[i].base;
547
+    
548
+    for(; m!=NULL; m=m->link)
549
+    {
550
+      assert( j < mfp->msgN );
551
+      
552
+      mfp->msgV[j++] = m;
553
+    }
554
+  }
555
+
556
+
557
+  // set the atick value in each msg
558
+  _cmMidiFileSetAccumulateTicks(mfp);
559
+    
560
+  // sort msgV[] in ascending order on atick
561
+  qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
562
+
563
+  // set the amicro value in each msg
564
+  _cmMidiFileSetAbsoluteTime(mfp);
565
+  
566
+}
567
+
524
 
568
 
525
 cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
569
 cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
526
 {
570
 {
528
   _cmMidiFile_t* mfp    = NULL;
572
   _cmMidiFile_t* mfp    = NULL;
529
   unsigned short trkIdx = 0;
573
   unsigned short trkIdx = 0;
530
   cmErr_t        err;
574
   cmErr_t        err;
531
-  unsigned i,j;
532
 
575
 
533
   if( cmMidiFileIsValid(*hPtr) )
576
   if( cmMidiFileIsValid(*hPtr) )
534
     if((rc = _cmMidiFileClose(_cmMidiFileHandleToPtr(*hPtr))) != kOkMfRC )
577
     if((rc = _cmMidiFileClose(_cmMidiFileHandleToPtr(*hPtr))) != kOkMfRC )
538
 
581
 
539
   // allocate the midi file object 
582
   // allocate the midi file object 
540
   if(( mfp = cmMemAllocZ( _cmMidiFile_t, 1)) == NULL )
583
   if(( mfp = cmMemAllocZ( _cmMidiFile_t, 1)) == NULL )
541
-    return rc = cmErrMsg(&err,kMemAllocFailMfRC,"MIDI file memory allocation failed.");
584
+    return rc                                 = cmErrMsg(&err,kMemAllocFailMfRC,"MIDI file memory allocation failed.");
542
 
585
 
543
   cmErrClone(&mfp->err,&err);
586
   cmErrClone(&mfp->err,&err);
544
 
587
 
562
   
605
   
563
   while( !cmFileEof(mfp->fh) && trkIdx < mfp->trkN )
606
   while( !cmFileEof(mfp->fh) && trkIdx < mfp->trkN )
564
   {
607
   {
565
-    unsigned chkId=0,chkN=0;
608
+    unsigned chkId = 0,chkN=0;
566
 
609
 
567
     // read the chunk id
610
     // read the chunk id
568
     if((rc = _cmMidiFileRead32(mfp,&chkId)) != kOkMfRC )
611
     if((rc = _cmMidiFileRead32(mfp,&chkId)) != kOkMfRC )
591
     }
634
     }
592
   }
635
   }
593
 
636
 
594
-  // get the total trk msg count
595
-  mfp->msgN = 0;
596
-  for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
597
-    mfp->msgN += mfp->trkV[ trkIdx ].cnt;
598
-
599
-  // allocate the trk msg index vector: msgV[]
600
-  mfp->msgV = cmMemAllocZ(cmMidiTrackMsg_t*, mfp->msgN);
601
-
602
-  mfp->nextUid = 0;
603
-
604
-  // store a pointer to every trk msg in msgV[]  and set 'uid'  
605
-  for(i=0,j=0; i<mfp->trkN; ++i)
606
-  {
607
-    cmMidiTrackMsg_t* m = mfp->trkV[i].base;
608
-    
609
-    for(; m!=NULL; m=m->link)
610
-    {
611
-      assert( j < mfp->msgN );
612
-      
613
-      mfp->msgV[j++] = m;
614
-      m->uid         = mfp->nextUid++;
615
-    }
616
-  }
617
-
618
-  mfp->fn = _cmMidiFileMalloc(mfp,strlen(fn)+1);
637
+  // store the file name
638
+  mfp->fn          = _cmMidiFileMalloc(mfp,strlen(fn)+1);
619
   assert( mfp->fn != NULL );
639
   assert( mfp->fn != NULL );
620
   strcpy(mfp->fn,fn);
640
   strcpy(mfp->fn,fn);
621
-
622
-
623
-  // set the atick value in each msg
624
-  _cmMidiFileSetAccumulateTicks(mfp);
625
-    
626
-  // sort msgV[] in ascending order on atick
627
-  qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
628
-
629
-  // set the amicro value in each msg
630
-  _cmMidiFileSetAbsoluteTime(mfp);
641
+  
642
+  _cmMidiFileLinearize(mfp);
631
   
643
   
632
   hPtr->h = mfp;
644
   hPtr->h = mfp;
633
 
645
 
682
 
694
 
683
 cmMfRC_t _cmMidiFileWrite24( _cmMidiFile_t* mfp, unsigned v )
695
 cmMfRC_t _cmMidiFileWrite24( _cmMidiFile_t* mfp, unsigned v )
684
 {
696
 {
685
-  cmMfRC_t rc   = kOkMfRC;
697
+  cmMfRC_t rc = kOkMfRC;
686
   unsigned mask = 0xff0000;
698
   unsigned mask = 0xff0000;
687
   int      i;
699
   int      i;
688
 
700
 
689
-  for(i=2; i>=0; --i)
701
+  for(i = 2; i>=0; --i)
690
   {
702
   {
691
     unsigned char c = (v & mask) >> (i*8);
703
     unsigned char c = (v & mask) >> (i*8);
692
     mask >>= 8;
704
     mask >>= 8;
727
 
739
 
728
 cmMfRC_t _cmMidiFileWriteVarLen( _cmMidiFile_t* mfp, unsigned v )
740
 cmMfRC_t _cmMidiFileWriteVarLen( _cmMidiFile_t* mfp, unsigned v )
729
 {
741
 {
730
-  cmMfRC_t rc = kOkMfRC;
742
+  cmMfRC_t rc  = kOkMfRC;
731
   unsigned buf = v & 0x7f;
743
   unsigned buf = v & 0x7f;
732
  
744
  
733
   while((v >>= 7) > 0 )
745
   while((v >>= 7) > 0 )
786
   else
798
   else
787
   {
799
   {
788
     // ... otherwise the division field was given in smpte
800
     // ... otherwise the division field was given in smpte
789
-    v  = mfp->smpteFmtId << 8;
801
+    v = mfp->smpteFmtId << 8;
790
     v += mfp->smpteTicksPerFrame;    
802
     v += mfp->smpteTicksPerFrame;    
791
   }
803
   }
792
 
804
 
800
 
812
 
801
 cmMfRC_t _cmMidiFileWriteSysEx( _cmMidiFile_t* mfp, cmMidiTrackMsg_t* tmp )
813
 cmMfRC_t _cmMidiFileWriteSysEx( _cmMidiFile_t* mfp, cmMidiTrackMsg_t* tmp )
802
 {
814
 {
803
-  cmMfRC_t     rc = kOkMfRC;
815
+  cmMfRC_t rc = kOkMfRC;
804
 
816
 
805
   if((rc = _cmMidiFileWrite8(mfp,kSysExMdId)) != kOkMfRC )
817
   if((rc = _cmMidiFileWrite8(mfp,kSysExMdId)) != kOkMfRC )
806
     goto errLabel;
818
     goto errLabel;
814
 
826
 
815
 cmMfRC_t _cmMidiFileWriteChannelMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp, cmMidiByte_t* runStatus )
827
 cmMfRC_t _cmMidiFileWriteChannelMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp, cmMidiByte_t* runStatus )
816
 {
828
 {
817
-  cmMfRC_t     rc     = kOkMfRC;
818
-  unsigned     byteN  = cmMidiStatusToByteCount(tmp->status);
829
+  cmMfRC_t     rc    = kOkMfRC;
830
+  unsigned     byteN = cmMidiStatusToByteCount(tmp->status);
819
   cmMidiByte_t status = tmp->status + tmp->u.chMsgPtr->ch;
831
   cmMidiByte_t status = tmp->status + tmp->u.chMsgPtr->ch;
820
 
832
 
821
   if( status != *runStatus )
833
   if( status != *runStatus )
839
 
851
 
840
 cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp )
852
 cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp )
841
 {
853
 {
842
-  cmMfRC_t     rc;
854
+  cmMfRC_t rc;
843
 
855
 
844
   if((rc = _cmMidiFileWrite8(mfp,kMetaStId)) != kOkMfRC )
856
   if((rc = _cmMidiFileWrite8(mfp,kMetaStId)) != kOkMfRC )
845
     return rc;
857
     return rc;
852
   {
864
   {
853
     case kSeqNumbMdId:
865
     case kSeqNumbMdId:
854
       if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.sVal))) == kOkMfRC )
866
       if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.sVal))) == kOkMfRC )
855
-        rc = _cmMidiFileWrite16(mfp,tmp->u.sVal);
867
+        rc                                                  = _cmMidiFileWrite16(mfp,tmp->u.sVal);
856
       break;
868
       break;
857
 
869
 
858
     case kTempoMdId:
870
     case kTempoMdId:
862
 
874
 
863
     case kSmpteMdId:
875
     case kSmpteMdId:
864
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiSmpte_t))) == kOkMfRC )
876
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiSmpte_t))) == kOkMfRC )
865
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.smptePtr,sizeof(cmMidiSmpte_t));
877
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.smptePtr,sizeof(cmMidiSmpte_t));
866
         break;
878
         break;
867
           
879
           
868
     case kTimeSigMdId:
880
     case kTimeSigMdId:
869
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiTimeSig_t))) == kOkMfRC )
881
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiTimeSig_t))) == kOkMfRC )
870
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.timeSigPtr,sizeof(cmMidiTimeSig_t));
882
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.timeSigPtr,sizeof(cmMidiTimeSig_t));
871
         break;
883
         break;
872
 
884
 
873
     case kKeySigMdId:
885
     case kKeySigMdId:
874
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiKeySig_t))) == kOkMfRC )
886
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiKeySig_t))) == kOkMfRC )
875
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.keySigPtr,sizeof(cmMidiKeySig_t));
887
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.keySigPtr,sizeof(cmMidiKeySig_t));
876
         break;
888
         break;
877
 
889
 
878
     case kSeqSpecMdId:
890
     case kSeqSpecMdId:
879
         if((rc = _cmMidiFileWriteVarLen(mfp,sizeof(tmp->byteCnt))) == kOkMfRC )
891
         if((rc = _cmMidiFileWriteVarLen(mfp,sizeof(tmp->byteCnt))) == kOkMfRC )
880
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.sysExPtr,tmp->byteCnt);
892
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.sysExPtr,tmp->byteCnt);
881
         break;
893
         break;
882
 
894
 
883
     case kMidiChMdId: 
895
     case kMidiChMdId: 
884
         if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.bVal))) == kOkMfRC )
896
         if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.bVal))) == kOkMfRC )
885
-          rc = _cmMidiFileWrite8(mfp,tmp->u.bVal);
897
+          rc                                                  = _cmMidiFileWrite8(mfp,tmp->u.bVal);
886
         break;
898
         break;
887
 
899
 
888
     case kEndOfTrkMdId:  
900
     case kEndOfTrkMdId:  
898
     case kCuePointMdId:  
910
     case kCuePointMdId:  
899
       {
911
       {
900
         unsigned n = tmp->u.text==NULL ? 0 : strlen(tmp->u.text);
912
         unsigned n = tmp->u.text==NULL ? 0 : strlen(tmp->u.text);
901
-        if((rc = _cmMidiFileWriteVarLen(mfp,n)) == kOkMfRC && n>0 )
902
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.text,n);
913
+        if((rc     = _cmMidiFileWriteVarLen(mfp,n)) == kOkMfRC && n>0 )
914
+          rc       = _cmMidiFileWriteRecd(mfp,tmp->u.text,n);
903
       }
915
       }
904
       break;
916
       break;
905
 
917
 
915
 
927
 
916
 cmMfRC_t _cmMidiFileWriteTrack( _cmMidiFile_t* mfp, unsigned trkIdx )
928
 cmMfRC_t _cmMidiFileWriteTrack( _cmMidiFile_t* mfp, unsigned trkIdx )
917
 {
929
 {
918
-  cmMfRC_t           rc        = kOkMfRC;
919
-  cmMidiTrackMsg_t*  tmp       = mfp->trkV[trkIdx].base;
920
-  cmMidiByte_t       runStatus = 0;
930
+  cmMfRC_t          rc        = kOkMfRC;
931
+  cmMidiTrackMsg_t* tmp       = mfp->trkV[trkIdx].base;
932
+  cmMidiByte_t      runStatus = 0;
921
 
933
 
922
-  for(; tmp!=NULL; tmp=tmp->link)
934
+  for(; tmp != NULL; tmp=tmp->link)
923
   {
935
   {
924
     // write the msg tick count
936
     // write the msg tick count
925
     if((rc = _cmMidiFileWriteVarLen(mfp,tmp->dtick)) != kOkMfRC )
937
     if((rc = _cmMidiFileWriteVarLen(mfp,tmp->dtick)) != kOkMfRC )
968
 
980
 
969
   for(i=0; i < mfp->trkN; ++i )
981
   for(i=0; i < mfp->trkN; ++i )
970
   {
982
   {
971
-    unsigned chkId='MTrk';
972
-    long offs0,offs1;
983
+    unsigned chkId = 'MTrk';
984
+    long     offs0,offs1;
973
 
985
 
974
     // write the track chunk id ('MTrk')
986
     // write the track chunk id ('MTrk')
975
     if((rc = _cmMidiFileWrite32(mfp,chkId)) != kOkMfRC )
987
     if((rc = _cmMidiFileWrite32(mfp,chkId)) != kOkMfRC )
1124
 cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel )
1136
 cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel )
1125
 {
1137
 {
1126
   cmMidiTrackMsg_t* r;
1138
   cmMidiTrackMsg_t* r;
1127
-  _cmMidiFile_t* mfp = _cmMidiFileHandleToPtr(h);
1139
+  _cmMidiFile_t*    mfp = _cmMidiFileHandleToPtr(h);
1128
 
1140
 
1129
   assert( mfp != NULL );
1141
   assert( mfp != NULL );
1130
 
1142
 
1131
   if((r = _cmMidiFileUidToMsg(mfp,uid)) == NULL )
1143
   if((r = _cmMidiFileUidToMsg(mfp,uid)) == NULL )
1132
     return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The MIDI file uid %i could not be found.",uid);
1144
     return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The MIDI file uid %i could not be found.",uid);
1133
 
1145
 
1134
-  if( cmMidiIsNoteOn(r->status)==false && cmMidiIsNoteOff(r->status,0)==false )
1146
+  if( cmMidiIsNoteOn(r->status) == false && cmMidiIsNoteOff(r->status,0)==false )
1135
     return cmErrMsg(&mfp->err,kUidNotANoteMsgMfRC,"Cannot set velocity on a non-Note-On/Off msg.");
1147
     return cmErrMsg(&mfp->err,kUidNotANoteMsgMfRC,"Cannot set velocity on a non-Note-On/Off msg.");
1136
   
1148
   
1137
   cmMidiChMsg_t* chm = (cmMidiChMsg_t*)r->u.chMsgPtr;
1149
   cmMidiChMsg_t* chm = (cmMidiChMsg_t*)r->u.chMsgPtr;
1141
   return kOkMfRC;
1153
   return kOkMfRC;
1142
 }
1154
 }
1143
 
1155
 
1156
+// Returns NULL if uid is not found or if it the first msg on the track.
1157
+cmMidiTrackMsg_t*  _cmMidiFileMsgBeforeUid( _cmMidiFile_t* p, unsigned uid )
1158
+{
1159
+  cmMidiTrackMsg_t* m;
1160
+  
1161
+  if((m = _cmMidiFileUidToMsg(p,uid)) == NULL )
1162
+    return NULL;
1163
+
1164
+  assert( m->trkIdx < p->trkN );
1165
+
1166
+  cmMidiTrackMsg_t* m0 = NULL;
1167
+  cmMidiTrackMsg_t* m1 = p->trkV[ m->trkIdx ].base;
1168
+  for(; m1!=NULL; m1 = m1->link)
1169
+  {
1170
+    if( m1->uid == uid )
1171
+      break;
1172
+    m0 = m1;
1173
+  }
1174
+
1175
+  return m0;
1176
+}
1177
+
1178
+unsigned _cmMidiFileIsMsgFirstOnTrack( _cmMidiFile_t* p, unsigned uid )
1179
+{
1180
+  unsigned i;
1181
+  for(i=0; i<p->trkN; ++i)
1182
+    if( p->trkV[i].base!=NULL && p->trkV[i].base->uid == uid )
1183
+      return i;
1184
+  
1185
+  return cmInvalidIdx;   
1186
+}
1187
+
1188
+
1189
+cmMfRC_t cmMidiFileInsertMsg( cmMidiFileH_t h, unsigned uid, int dtick, cmMidiByte_t ch, cmMidiByte_t status, cmMidiByte_t d0, cmMidiByte_t d1 )
1190
+{
1191
+  _cmMidiFile_t*    mfp    = _cmMidiFileHandleToPtr(h);
1192
+  assert( mfp != NULL );
1193
+  cmMidiTrackMsg_t* ref    = NULL;
1194
+  unsigned          trkIdx = cmInvalidIdx;
1195
+
1196
+  // if dtick is positive ...
1197
+  if( dtick >= 0 )
1198
+  {
1199
+    ref    = _cmMidiFileUidToMsg(mfp,uid); // ... then get the ref. msg.
1200
+    trkIdx = ref->trkIdx;
1201
+  }
1202
+  else // if dtick is negative ...
1203
+  {
1204
+    // ... get get the msg before the ref. msg.
1205
+    if((ref = _cmMidiFileMsgBeforeUid(mfp,uid)) == NULL )
1206
+    {
1207
+      // ... the ref. msg was first in the track so there is no msg before it
1208
+      trkIdx = _cmMidiFileIsMsgFirstOnTrack(mfp,uid);
1209
+    }
1210
+  }
1211
+
1212
+  // verify that the reference msg was found
1213
+  if( trkIdx == cmInvalidIdx )
1214
+    return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The UID (%i) reference note could not be located.",uid);
1215
+
1216
+  assert( trkIdx < mfp->trkN );
1217
+
1218
+  // complete the msg setup
1219
+  _cmMidiTrack_t* trk   = mfp->trkV + trkIdx;
1220
+  cmMidiTrackMsg_t* m   = _cmMidiFileAllocMsg(mfp, trkIdx, abs(dtick), status );
1221
+  cmMidiChMsg_t*    c   = (cmMidiChMsg_t*)m->u.chMsgPtr; // cast away const
1222
+  c->ch   = ch;
1223
+  c->d0   = d0;
1224
+  c->d1   = d1;
1225
+
1226
+  // if 'm' is prior to the first msg in the track
1227
+  if( ref == NULL )
1228
+  {
1229
+    // ... then make 'm' the first msg in the first msg
1230
+    m->link = trk->base;
1231
+    trk->base = m;
1232
+    // 'm' is before ref and the track cannot be empty (because ref is in it) 'm'
1233
+    // can never be the last msg in the list
1234
+  } 
1235
+  else // ref is the msg before 'm'
1236
+  {
1237
+    m->link   = ref->link;
1238
+    ref->link = m;
1239
+    
1240
+    // if ref was the last msg in the trk ...
1241
+    if( trk->last == ref )
1242
+      trk->last = m;  //... then 'm' is now the last msg in the trk
1243
+  }
1244
+
1245
+  trk->cnt += 1;
1246
+
1247
+  _cmMidiFileLinearize(mfp);
1248
+
1249
+  return kOkMfRC;
1250
+
1251
+}
1252
+
1144
 unsigned  cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned long long offsUSecs, unsigned* msgUsecsPtr, unsigned* microsPerTickPtr )
1253
 unsigned  cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned long long offsUSecs, unsigned* msgUsecsPtr, unsigned* microsPerTickPtr )
1145
 {
1254
 {
1146
   _cmMidiFile_t* p;
1255
   _cmMidiFile_t* p;

+ 4
- 0
cmMidiFile.h Datei anzeigen

161
   // Set the velocity of a note-on/off msg identified by 'uid'.
161
   // Set the velocity of a note-on/off msg identified by 'uid'.
162
   cmMfRC_t             cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel );
162
   cmMfRC_t             cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel );
163
 
163
 
164
+  // Insert a MIDI message relative to the reference msg identified by 'uid'.
165
+  // If dtick is positive/negative then the new msg is inserted after/before the reference msg.  
166
+  cmMfRC_t             cmMidiFileInsertMsg( cmMidiFileH_t h, unsigned uid, int dtick, cmMidiByte_t ch, cmMidiByte_t status, cmMidiByte_t d0, cmMidiByte_t d1 );
167
+  
164
   // Return a pointer to the first msg at or after 'usecsOffs' or kInvalidIdx if no
168
   // Return a pointer to the first msg at or after 'usecsOffs' or kInvalidIdx if no
165
   // msg exists after 'usecsOffs'.  Note that 'usecOffs' is an offset from the beginning
169
   // msg exists after 'usecsOffs'.  Note that 'usecOffs' is an offset from the beginning
166
   // of the file.
170
   // of the file.

Laden…
Abbrechen
Speichern