|
@@ -41,7 +41,7 @@ typedef struct
|
41
|
41
|
char* fn; // file name or NULL if this object did not originate from a file
|
42
|
42
|
unsigned msgN; // count of msg's in msgV[]
|
43
|
43
|
cmMidiTrackMsg_t** msgV; // sorted msg list
|
44
|
|
-
|
|
44
|
+ unsigned nextUid; // next available msg uid
|
45
|
45
|
} _cmMidiFile_t;
|
46
|
46
|
|
47
|
47
|
|
|
@@ -524,6 +524,7 @@ cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx )
|
524
|
524
|
|
525
|
525
|
// store a pointer to every trk msg in msgV[]
|
526
|
526
|
// and convert tick to absolute tick
|
|
527
|
+ mfp->nextUid = 0;
|
527
|
528
|
unsigned i = 0;
|
528
|
529
|
for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
|
529
|
530
|
{
|
|
@@ -534,15 +535,16 @@ cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx )
|
534
|
535
|
{
|
535
|
536
|
assert( i < mfp->msgN);
|
536
|
537
|
|
537
|
|
- tick += tmp->dtick; // convert delta-ticks to absolute ticks
|
|
538
|
+ tick += tmp->dtick; // convert delta-ticks to absolute ticks
|
538
|
539
|
tmp->atick = tick;
|
|
540
|
+ tmp->uid = mfp->nextUid++; // assign the msg uid
|
539
|
541
|
mfp->msgV[i] = tmp;
|
540
|
542
|
tmp = tmp->link;
|
541
|
543
|
++i;
|
542
|
544
|
}
|
543
|
545
|
}
|
544
|
546
|
|
545
|
|
- // sort msgV[] in ascending order on dtick
|
|
547
|
+ // sort msgV[] in ascending order on atick
|
546
|
548
|
qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
|
547
|
549
|
|
548
|
550
|
//for(i=0; i<25; ++i)
|
|
@@ -552,24 +554,6 @@ cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx )
|
552
|
554
|
assert( mfp->fn != NULL );
|
553
|
555
|
strcpy(mfp->fn,fn);
|
554
|
556
|
|
555
|
|
- //
|
556
|
|
- // calculate the total duration of the MIDI file and convert absolute ticks back to delta ticks
|
557
|
|
- //
|
558
|
|
- /*
|
559
|
|
- unsigned mi;
|
560
|
|
- unsigned prvTick = 0;
|
561
|
|
-
|
562
|
|
-
|
563
|
|
- for(mi=0; mi<mfp->msgN; ++mi)
|
564
|
|
- {
|
565
|
|
- cmMidiTrackMsg_t* mp = mfp->msgV[mi];
|
566
|
|
-
|
567
|
|
- // convert absolute ticks back to delta ticks
|
568
|
|
- unsigned dtick = mp->dtick - prvTick;
|
569
|
|
- prvTick = mp->dtick;
|
570
|
|
- mp->dtick = dtick;
|
571
|
|
- }
|
572
|
|
- */
|
573
|
557
|
|
574
|
558
|
hPtr->h = mfp;
|
575
|
559
|
|
|
@@ -1062,9 +1046,9 @@ unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned offsUSecs, unsigned* ms
|
1062
|
1046
|
return cmInvalidIdx;
|
1063
|
1047
|
|
1064
|
1048
|
unsigned mi;
|
1065
|
|
- unsigned microsPerQN = 60000000/120;
|
1066
|
|
- unsigned microsPerTick = microsPerQN / p->ticksPerQN;
|
1067
|
|
- unsigned accUSecs = 0;
|
|
1049
|
+ double microsPerQN = 60000000.0/120.0;
|
|
1050
|
+ double microsPerTick = microsPerQN / p->ticksPerQN;
|
|
1051
|
+ double accUSecs = 0;
|
1068
|
1052
|
|
1069
|
1053
|
for(mi=0; mi<p->msgN; ++mi)
|
1070
|
1054
|
{
|
|
@@ -1084,10 +1068,10 @@ unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned offsUSecs, unsigned* ms
|
1084
|
1068
|
return cmInvalidIdx;
|
1085
|
1069
|
|
1086
|
1070
|
if( msgUsecsPtr != NULL )
|
1087
|
|
- *msgUsecsPtr = accUSecs - offsUSecs;
|
|
1071
|
+ *msgUsecsPtr = round(accUSecs - offsUSecs);
|
1088
|
1072
|
|
1089
|
1073
|
if( microsPerTickPtr != NULL )
|
1090
|
|
- *microsPerTickPtr = microsPerTick;
|
|
1074
|
+ *microsPerTickPtr = round(microsPerTick);
|
1091
|
1075
|
|
1092
|
1076
|
return mi;
|
1093
|
1077
|
}
|
|
@@ -1097,15 +1081,16 @@ double cmMidiFileDurSecs( cmMidiFileH_t h )
|
1097
|
1081
|
_cmMidiFile_t* mfp = _cmMidiFileHandleToPtr(h);
|
1098
|
1082
|
unsigned mi;
|
1099
|
1083
|
double durSecs = 0;
|
1100
|
|
- unsigned microsPerQN = 60000000/120;
|
1101
|
|
- unsigned microsPerTick = microsPerQN / mfp->ticksPerQN;
|
|
1084
|
+ double r = 1.0; //1000.0/(1000-.8);
|
|
1085
|
+ double microsPerQN = r*60000000.0/120.0;
|
|
1086
|
+ double microsPerTick = microsPerQN / mfp->ticksPerQN;
|
1102
|
1087
|
|
1103
|
1088
|
for(mi=0; mi<mfp->msgN; ++mi)
|
1104
|
1089
|
{
|
1105
|
1090
|
cmMidiTrackMsg_t* mp = mfp->msgV[mi];
|
1106
|
1091
|
|
1107
|
1092
|
if( mp->status == kMetaStId && mp->metaId == kTempoMdId )
|
1108
|
|
- microsPerTick = mp->u.iVal / mfp->ticksPerQN;
|
|
1093
|
+ microsPerTick = r*mp->u.iVal / mfp->ticksPerQN;
|
1109
|
1094
|
|
1110
|
1095
|
// update the accumulated seconds
|
1111
|
1096
|
durSecs += (mp->dtick * microsPerTick) / 1000000.0;
|
|
@@ -1126,17 +1111,18 @@ void cmMidiFileTickToMicros( cmMidiFileH_t h )
|
1126
|
1111
|
return;
|
1127
|
1112
|
|
1128
|
1113
|
unsigned mi;
|
1129
|
|
- unsigned microsPerQN = 60000000/120; // default tempo
|
1130
|
|
- unsigned microsPerTick = microsPerQN / p->ticksPerQN;
|
|
1114
|
+ double r = 1.0; //1000.0/(1000-.8);
|
|
1115
|
+ double microsPerQN = r*60000000/120; // default tempo
|
|
1116
|
+ double microsPerTick = microsPerQN / p->ticksPerQN;
|
1131
|
1117
|
|
1132
|
1118
|
for(mi=0; mi<p->msgN; ++mi)
|
1133
|
1119
|
{
|
1134
|
1120
|
cmMidiTrackMsg_t* mp = p->msgV[mi];
|
1135
|
1121
|
|
1136
|
1122
|
if( mp->status == kMetaStId && mp->metaId == kTempoMdId )
|
1137
|
|
- microsPerTick = mp->u.iVal / p->ticksPerQN;
|
|
1123
|
+ microsPerTick = r*mp->u.iVal / p->ticksPerQN;
|
1138
|
1124
|
|
1139
|
|
- mp->dtick *= microsPerTick;
|
|
1125
|
+ mp->dtick = round(microsPerTick*mp->dtick);
|
1140
|
1126
|
}
|
1141
|
1127
|
|
1142
|
1128
|
}
|
|
@@ -1144,28 +1130,37 @@ void cmMidiFileTickToMicros( cmMidiFileH_t h )
|
1144
|
1130
|
void cmMidiFileTickToSamples( cmMidiFileH_t h, double srate, bool absFl )
|
1145
|
1131
|
{
|
1146
|
1132
|
_cmMidiFile_t* p;
|
1147
|
|
- unsigned mi;
|
1148
|
|
- //bool fl = true;
|
1149
|
1133
|
|
1150
|
1134
|
if((p = _cmMidiFileHandleToPtr(h)) == NULL )
|
1151
|
1135
|
return;
|
1152
|
1136
|
|
1153
|
|
- cmMidiFileTickToMicros(h);
|
|
1137
|
+ if( p->msgN == 0 )
|
|
1138
|
+ return;
|
1154
|
1139
|
|
1155
|
|
- unsigned absSmp = 0;
|
|
1140
|
+ unsigned mi;
|
|
1141
|
+ double r = 1.0; //1000.0/(1000-.8);
|
|
1142
|
+ double microsPerQN = r*60000000/120; // default tempo
|
|
1143
|
+ double microsPerTick = microsPerQN / p->ticksPerQN;
|
|
1144
|
+ double absSmp = 0;
|
1156
|
1145
|
|
1157
|
1146
|
for(mi=0; mi<p->msgN; ++mi)
|
1158
|
1147
|
{
|
1159
|
|
- cmMidiTrackMsg_t* mp = p->msgV[mi];
|
1160
|
|
- unsigned delta = floor((mp->dtick*srate)/1000000.0);
|
|
1148
|
+ cmMidiTrackMsg_t* mp = p->msgV[mi];
|
1161
|
1149
|
|
1162
|
|
- absSmp += delta;
|
|
1150
|
+ if( mp->status == kMetaStId && mp->metaId == kTempoMdId )
|
|
1151
|
+ microsPerTick = r*mp->u.iVal / p->ticksPerQN;
|
|
1152
|
+
|
|
1153
|
+ double delta = microsPerTick*mp->dtick*srate/1000000.0;
|
|
1154
|
+
|
|
1155
|
+ absSmp += delta;
|
1163
|
1156
|
|
1164
|
|
- mp->dtick = absFl ? absSmp : delta;
|
|
1157
|
+ mp->dtick = round(absFl ? absSmp : delta);
|
1165
|
1158
|
|
1166
|
1159
|
}
|
|
1160
|
+
|
1167
|
1161
|
}
|
1168
|
1162
|
|
|
1163
|
+
|
1169
|
1164
|
typedef struct _cmMidiVoice_str
|
1170
|
1165
|
{
|
1171
|
1166
|
const cmMidiTrackMsg_t* mp;
|