diff --git a/VERSION b/VERSION index dff1228..5f42962 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -June 27 2025 +November 26 2025 diff --git a/doc/midistats.1 b/doc/midistats.1 index 45830de..d9386f0 100644 --- a/doc/midistats.1 +++ b/doc/midistats.1 @@ -1,4 +1,4 @@ -.TH MIDISTATS 1 "18 March 2024" +.TH MIDISTATS 1 "26 November 2025" .SH NAME \fBmidistats\fP \- program to summarize the statistical properties of a midi file .SH SYNOPSIS @@ -36,26 +36,29 @@ number. .PP trkinfo is an array of 19 numbers which indicates the statistical properties of the track of interest. The following data is given: -0 the channel number, -1 the first program assigned to this channel, -2 the number of notes for this channel counting any chords as one note, -3 the total number of notes for this for this channel, -4 the sum of the MIDI pitches for all the notes, -5 the sum of the note durations in MIDI pulse units, -6 the number of pitchbend messages, -7 the number of control parameter messages, -8 the number of pressure messages. -9 the number of distinct rhythm patterns for each channel -10 the number of pulses the channel was inactive -11 the minimum pitch value -12 the maximum pitch value -13 the minimum note length in pulses -14 the maximum note length in pulses -15 the number of gaps in the channel -16 the entropy of the pitch class histogram for that channel -17 the number of notes whose pitch were the same as the previous note -18 the number of notes whose pitch changed by less than 4 semitones -19 the number of notes whose pitch changed by 4 or more semitones + 0 the channel number, + 1 the first program assigned to this channel, + 2 the number of notes for this channel counting any chords as one note, + 3 the number of chord notes excluding the bass note, + 4 the sum of the MIDI pitches for all the notes, + 5 the sum of the note durations in MIDI pulse units, + 6 the number of pitchbend messages, + 7 the number of control parameter messages, + 8 the number of pressure messages. + 9 the number of distinct rhythm patterns for each channel + 10 the number of pulses the channel was inactive + 11 the minimum pitch value + 12 the maximum pitch value + 13 the minimum note length in pulses + 14 the maximum note length in pulses + 15 the number of gaps in the channel + 16 the entropy of the pitch class histogram for that channel + 17 the number of notes whose pitch were the same as the previous note + 18 the number of notes whose pitch changed by less than 4 semitones + 19 the number of notes whose pitch changed by 4 or more semitones + 20 the average note velocity + 21 the standard deviation of the note velocity + (In event of a chords the maximum pitches are compared.) .PP After processing all the individual tracks, the following information diff --git a/midistats.c b/midistats.c index 06f7c56..6776450 100644 --- a/midistats.c +++ b/midistats.c @@ -17,7 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#define VERSION "1.00 June 27 2025 midistats" +#define VERSION "1.01 November 26 2025 midistats" /* midistrats.c is a descendent of midi2abc.c which was becoming to large. The object of the program is to extract statistical characterisitic @@ -182,6 +182,8 @@ struct trkstat { int rhythmpatterns[17]; int numberOfGaps[17]; int chanvol[17]; + int velocity[17]; /* 2025.11.26 */ + int velocity2[17]; /* 2025.11.26 */ float pitchEntropy[17]; } trkdata; @@ -729,28 +731,38 @@ if (sum != 0) { void output_track_summary () { int i; +int nnotes; /* 2025.11.26 */ +float avgvel, varvel; /* 2025.11.26 */ /* find first channel containing data */ output_hasher_results(); for (i=1;i<17;i++) { if(trkdata.notecount[i] == 0 && trkdata.chordcount[i] == 0) continue; printf("trkinfo "); printf("%d %d ",i,trkdata.program[i]); /* channel number and program*/ + nnotes = trkdata.notecount[i]+trkdata.chordcount[i]; /* 2025.11.26 */ printf("%d %d ",trkdata.notecount[i],trkdata.chordcount[i]); /* [SS] 2023-08-22 */ if (i != 10) printf("%d %d ",trkdata.notemeanpitch[i], trkdata.notelength[i]); else printf("-1 0 "); + printf("%d ",trkdata.pitchbend[i]); /* [SS] 2024-07-26 */ printf("%d %d ",trkdata.cntlparam[i],trkdata.pressure[i]); /* [SS] 2022-03-04 */ printf("%d %d ",trkdata.quietTime[i],trkdata.rhythmpatterns[i]); if (i != 10) {printf("%d %d %d %d %d",trkdata.notepitchmin[i], trkdata.notepitchmax[i] ,trkdata.notelengthmin[i], trkdata.notelengthmax[i], trkdata.numberOfGaps[i]); printf(" %f",trkdata.pitchEntropy[i]); - } else - printf("-1 0"); - if (lasttrack > 1) printf(" %d %d %d\n",tracknm.zeroCount,tracknm.stepCount,tracknm.jumpCount); - else - printf(" %d %d %d\n",nm[i-1].zeroCount,nm[i-1].stepCount,nm[i-1].jumpCount); + /* 2025.11.26 next 6 lines */ + printf(" %d %d %d",nm[i-1].zeroCount,nm[i-1].stepCount,nm[i-1].jumpCount); + avgvel = (float) trkdata.velocity[i]/(float) nnotes; + varvel = ((float) trkdata.velocity2[i] / (float) nnotes) - avgvel*avgvel; + if (varvel < 0.01) varvel = 0.01; + printf(" %d %d",(int) round(avgvel),(int) round(sqrt(varvel))); printf("\n"); + } else + printf("-1 0\n"); + if (lasttrack == 1) { /* 2025.11.26 */ + printf(" %d %d %d\n",tracknm.zeroCount,tracknm.stepCount,tracknm.jumpCount); + } channel2nnotes[i] += trkdata.notecount[i] + trkdata.chordcount[i]; } @@ -774,6 +786,8 @@ void stats_trackstart() trkdata.notelengthmax[i] = 0; trkdata.chordcount[i] = 0; trkdata.cntlparam[i] = 0; + trkdata.velocity[i] = 0; /* 2025.11.26 */ + trkdata.velocity2[i] = 0; last_on_tick[i] = -1; channel_active[i] = 0; } @@ -921,6 +935,8 @@ int chan, pitch, vol; trkdata.notemeanpitch[chan+1] += pitch; trkdata.notepitchmax[chan+1] = max(trkdata.notepitchmax[chan+1],pitch); trkdata.notepitchmin[chan+1] = min(trkdata.notepitchmin[chan+1],pitch); + trkdata.velocity[chan+1] += vol; /* 2025.11.26 */ + trkdata.velocity2[chan+1] += vol*vol; if (trkdata.lastNoteOff[chan+1] >= 0) { delta = Mf_currtime - trkdata.lastNoteOff[chan+1]; if (delta > quietLimit) {