2024.02.11

This commit is contained in:
sshlien
2024-02-11 13:59:25 -05:00
parent eac28d9489
commit b9c48dc778
3 changed files with 66 additions and 112 deletions

View File

@@ -1,4 +1,4 @@
.TH MIDISTATS 1 "04 January 2024" .TH MIDISTATS 1 "11 February 2024"
.SH NAME .SH NAME
\fBmidistats\fP \- program to summarize the statistical properties of a midi file \fBmidistats\fP \- program to summarize the statistical properties of a midi file
.SH SYNOPSIS .SH SYNOPSIS
@@ -26,7 +26,7 @@ applies.
program is followed by the channel number and the General Midi Program program is followed by the channel number and the General Midi Program
number. number.
.PP .PP
trkinfo is an array of 8 numbers which indicates the statistical properties trkinfo is an array of 19 numbers which indicates the statistical properties
of the track of interest. The following data is given: of the track of interest. The following data is given:
the channel number, the channel number,
the first program assigned to this channel, the first program assigned to this channel,
@@ -44,6 +44,10 @@ the minimum note length in pulses
the maximum note length in pulses the maximum note length in pulses
the number of gaps in the channel the number of gaps in the channel
the entropy of the pitch class histogram for that channel the entropy of the pitch class histogram for that channel
the number of notes whose pitch were the same as the previous note
the number of notes whose pitch changed by less than 4 semitones
the number of notes whose pitch changed by 4 or more semitones
(In event of a chords the maximum pitches are compared.)
.PP .PP
After processing all the individual tracks, the following information After processing all the individual tracks, the following information
applies to the entire midi file. applies to the entire midi file.
@@ -108,6 +112,29 @@ collisions. Midistats counts the bar rhythm patterns using a hashing
function. Presently collisions are ignored so occasionally two function. Presently collisions are ignored so occasionally two
distinct rhythm patterns are counted as one. distinct rhythm patterns are counted as one.
.PP .PP
Midistats prints a number of arrays which may be useful in
determining where the music in the track is a melody line or
chordal rhythmic support. These arrays indicate the properties
for each of the 16 channels. (The percussion channel 9 contains
zeros.) In the case same channel occurs in several tracks, these
numbers are the totals for all track containing that channel.
Here is a description of these properties.
.PP
nnotes: the total number of notes in each channel
.br
nzeros: the number of notes whose previous note was the same pitch
.br
nsteps: the number of notes whose pitch difference with the previous
note was less than 4 semitones.
.br
njumps: the number of notes whose pitch difference with the previous
note was 4 or more semitones.
.br
rpats: the number of rhythmpatterns for each channels. This is a
duplication of data printed previously.
.br
pavg: the average pitch of all the notes for each channel.
.PP
In addition the midistats may return other codes that describe In addition the midistats may return other codes that describe
other characteristics. They include other characteristics. They include
@@ -250,6 +277,7 @@ splits the two 4-bit values with a period. Thus 33 = (2*16 + 1).
-pitchclass -pitchclass
.br .br
Returns the pitch class distribution for the entire midi file. Returns the pitch class distribution for the entire midi file.
.PP .PP
-nseqfor n -nseqfor n
.br .br
@@ -274,7 +302,16 @@ repeating patterns.
.br .br
Same as above except it is applied to all channels except the Same as above except it is applied to all channels except the
percussion channel. percussion channel.
.br
.PP
-nseqtokens
Returns the number of distinct sequence elements for each channel.
The channel number and number of distinct elements separated by
a comma is returned in a tab separated list for all active channels
except the percussion channel. Here is an example.
.br
2,3 3,4 4,11 5,6 6,3 7,3 8,6 9,3 11,2 12,1
.br
-ver (version number) -ver (version number)

View File

@@ -6,7 +6,7 @@ abc2abc version 2.20 February 07 2023
yaps version 1.92 January 06 2023 yaps version 1.92 January 06 2023
abcmatch version 1.82 June 14 2022 abcmatch version 1.82 June 14 2022
midicopy version 1.39 November 08 2022 midicopy version 1.39 November 08 2022
midistats version 0.85 January 04 2024 midistats version 0.87 February 11 2024
24th January 2002 24th January 2002
Copyright James Allwright Copyright James Allwright

View File

@@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#define VERSION "0.87 February 09 2024 midistats" #define VERSION "0.87 February 11 2024 midistats"
/* midistrats.c is a descendent of midi2abc.c which was becoming to /* midistrats.c is a descendent of midi2abc.c which was becoming to
large. The object of the program is to extract statistical characterisitic large. The object of the program is to extract statistical characterisitic
@@ -68,7 +68,7 @@ float histogram_perplexity (int *histogram, int size);
void stats_noteoff(int chan,int pitch,int vol); void stats_noteoff(int chan,int pitch,int vol);
void stats_eot (); void stats_eot ();
void keymatch(); void keymatch();
void outputNoteMemory(); void outputChannelSummary();
void clearTrackNm (); void clearTrackNm ();
#define max(a,b) (( a > b ? a : b)) #define max(a,b) (( a > b ? a : b))
@@ -102,7 +102,6 @@ int percpatternfor;
int percpatternhist; int percpatternhist;
int pitchclassanalysis; int pitchclassanalysis;
int nseqfor; int nseqfor;
int pmove;
int corestats; int corestats;
int chordthreshold; /* number of maximum number of pulses separating note */ int chordthreshold; /* number of maximum number of pulses separating note */
int beatsPerBar = 4; /* 4/4 time */ int beatsPerBar = 4; /* 4/4 time */
@@ -149,7 +148,6 @@ int channel_used_in_track[17]; /* for dealing with quietTime [SS] 2023-09-06 */
int histogram[256]; int histogram[256];
unsigned char drumpat[8000]; unsigned char drumpat[8000];
unsigned char pseq[8000]; unsigned char pseq[8000];
unsigned char maxpitch[8000];
int pseqhist[128]; int pseqhist[128];
int percnum; int percnum;
int nseqchn; int nseqchn;
@@ -204,6 +202,8 @@ struct notememory {int eighthUnit;
int zeroCount; int zeroCount;
int stepCount; int stepCount;
int jumpCount; int jumpCount;
int totalNotes;
int totalPitches;
} nm[17]; } nm[17];
struct notememory tracknm; struct notememory tracknm;
@@ -562,12 +562,6 @@ tripletsCriterion8 = (float) pulseDistribution[8]/ (float) ncounts;
tripletsCriterion4 = (float) pulseDistribution[4]/ (float) ncounts; tripletsCriterion4 = (float) pulseDistribution[4]/ (float) ncounts;
if (tripletsCriterion8 > 0.10 || tripletsCriterion4 > 0.10) printf("triplets\n"); if (tripletsCriterion8 > 0.10 || tripletsCriterion4 > 0.10) printf("triplets\n");
if (pulseDistribution[0]/(float) ncounts > 0.95) printf("qnotes"); if (pulseDistribution[0]/(float) ncounts > 0.95) printf("qnotes");
/*
printf("pulseDistribution:");
for (i=0;i<resolution;i++) printf("%6.3f",(float) pulseDistribution[i]/(float) ncounts);
printf("\n");
printf("nzeros = %d npeaks = %d \n",nzeros,npeaks);
*/
} }
void stats_finish() void stats_finish()
@@ -645,7 +639,7 @@ printf("collisions = %d\n",ncollisions);
if (hasLyrics) printf("Lyrics\n"); if (hasLyrics) printf("Lyrics\n");
stats_interpret_pulseCounter (); stats_interpret_pulseCounter ();
printf("\n"); printf("\n");
outputNoteMemory(); outputChannelSummary();
} }
@@ -717,10 +711,12 @@ for (i=1;i<17;i++) {
printf("-1 0"); printf("-1 0");
trkdata.quietTime[i] = 0; /* in case channel i is used in another track */ trkdata.quietTime[i] = 0; /* in case channel i is used in another track */
trkdata.numberOfGaps[i] = 0; trkdata.numberOfGaps[i] = 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);
printf("\n"); printf("\n");
channel2nnotes[i] += trkdata.notecount[i] + trkdata.chordcount[i]; channel2nnotes[i] += trkdata.notecount[i] + trkdata.chordcount[i];
if (lasttrack > 1) printf("nzeros = %d nsteps = %d njumps = %d\n",tracknm.zeroCount,tracknm.stepCount,tracknm.jumpCount);
} }
} }
@@ -778,6 +774,8 @@ void clearNotememory () {
nm[i].zeroCount = 0; nm[i].zeroCount = 0;
nm[i].stepCount = 0; nm[i].stepCount = 0;
nm[i].jumpCount = 0; nm[i].jumpCount = 0;
nm[i].totalNotes =0;
nm[i].totalPitches =0;
} }
} }
@@ -789,6 +787,8 @@ void clearTrackNm () {
tracknm.zeroCount = 0; tracknm.zeroCount = 0;
tracknm.stepCount = 0; tracknm.stepCount = 0;
tracknm.jumpCount = 0; tracknm.jumpCount = 0;
tracknm.totalNotes = 0;
tracknm.totalPitches = 0;
} }
void updateNotememory (int unit, int chn, int pitch) { void updateNotememory (int unit, int chn, int pitch) {
@@ -811,10 +811,8 @@ if (nm[chn].previousPitch > 0)
} }
if (nm[chn].beforePitch != 0) nm[chn].previousPitch = nm[chn].beforePitch; if (nm[chn].beforePitch != 0) nm[chn].previousPitch = nm[chn].beforePitch;
nm[chn].eighthUnit = unit; nm[chn].eighthUnit = unit;
/*printf("%d, %d, %d, %d, %d, %d %d\n",unit,nm[chn].beforePitch,nm[chn].previousPitch,\ nm[chn].totalNotes++;
deltaPitch,nm[chn].zeroCount,nm[chn].stepCount,nm[chn].jumpCount); nm[chn].totalPitches = nm[chn].totalPitches + pitch;
*/
} }
void updateTrackNotememory (int unit, int chn, int pitch) { void updateTrackNotememory (int unit, int chn, int pitch) {
@@ -1341,99 +1339,28 @@ printf("\n");
} }
void maxpitchInInterval(int chn) {
int i;
int half;
int channel;
int pitch;
int onset;
int index;
int remainder;
int noteNum;
int part;
half = division/2;
for (i = 0; i<8000; i++) maxpitch[i] = 0;
for (i = 0; i <lastEvent; i++) {
channel = midievents[i].channel;
if (channel == 9) continue; /* ignore percussion channel */
if (channel == chn || chn == -1) {
pitch = midievents[i].pitch;
onset = midievents[i].onsetTime;
index = onset/half;
if (index >= 8000) {printf("index too large in drumpattern\n");
break;
}
if (pitch > maxpitch[index]) maxpitch[index] = pitch;
}
/*printf("pitchclass = %d noteNum =%d index = %d pseq[index] %d \n",pitchclass, noteNum, index, pseq[index]); */
}
/*printf("maxpitch = \n");
for (i=0;i<100;i++) printf(" %d,",maxpitch[i]);
printf("\n");
*/
}
void pitchDifference (int chn) {
int i;
int nzeros;
int nsteps;
int njumps;
int lastmax;
int pmax;
int pdif;
nzeros = 0;
nsteps = 0;
njumps = 0;
lastmax = 0;
pdif = 0;
maxpitchInInterval(chn);
for (i = 0; i <lastEvent; i++) {
if (maxpitch[i] > 0) {
pmax = maxpitch[i];
if (lastmax > 0) {
pdif = pmax - lastmax;
if (pdif == 0) nzeros++;
else if (abs(pdif) <4) nsteps++;
else njumps++;
}
lastmax = pmax;
/*if(i<40) printf("%d %d %d %d %d %d\n",pmax,lastmax,pdif,nzeros,nsteps,njumps);
*/
}
}
printf("%d %d %d %d\n",chn+1,nzeros,nsteps,njumps);
}
void allPitchDifference() {
int i;
int nonzeros;
for (i=0;i<17;i++) {
/*printf("\n%d,%d",i,channel_active[i+1]);*/
if (i == 9) continue;
if (channel_active[i+1] == 0) continue;
pitchDifference(i);
}
printf("\n");
}
void outputNoteMemory() { void outputChannelSummary() {
int i; int i;
for (i=0;i<17;i++) { for (i=0;i<17;i++) {
if (i == 9) continue; printf("nnotes: ");
if ((nm[i].zeroCount + nm[i].stepCount+nm[i].jumpCount) == 0) continue; for(i=0;i<16;i++) printf(" %d",nm[i].totalNotes);
printf("nzeros: "); printf("\nnzeros: ");
for(i=0;i<16;i++) printf(" %d",nm[i].zeroCount); for(i=0;i<16;i++) printf(" %d",nm[i].zeroCount);
printf("\nnsteps: "); printf("\nnsteps: ");
for(i=0;i<16;i++) printf(" %d",nm[i].stepCount); for(i=0;i<16;i++) printf(" %d",nm[i].stepCount);
printf("\nnjumps: "); printf("\nnjumps: ");
for(i=0;i<16;i++) printf(" %d",nm[i].jumpCount); for(i=0;i<16;i++) printf(" %d",nm[i].jumpCount);
printf("\n"); printf("\nrpats: ");
for(i=1;i<17;i++) printf(" %d",trkdata.rhythmpatterns[i]);
printf("\npavg: ");
/* avoid dividing by 0 */
for(i=0;i<16;i++) printf(" %d",nm[i].totalPitches/(1+nm[i].totalNotes));
printf("\n");
} }
/* printf("pmove: %d %d %d %d\n",i+1,nm[i].zeroCount,nm[i].stepCount,nm[i].jumpCount);
}*/
} }
void dualDrumPattern (int perc1, int perc2) { void dualDrumPattern (int perc1, int perc2) {
@@ -1835,11 +1762,6 @@ int argc;
nseqchn = -1; nseqchn = -1;
} }
arg = getarg("-pmove",argc,argv);
if (arg != -1) {
pmove = 1;
stats = 0;
}
arg = getarg("-nseqtokens",argc,argv); arg = getarg("-nseqtokens",argc,argv);
if (arg != -1) { if (arg != -1) {
@@ -1891,7 +1813,6 @@ int argc;
printf(" -nseq\n"); printf(" -nseq\n");
printf(" -nseqfor channel\n"); printf(" -nseqfor channel\n");
printf(" -nseqtokens\n"); printf(" -nseqtokens\n");
printf(" -pmove\n");
printf(" -ver version number\n"); printf(" -ver version number\n");
printf(" -d <number> debug parameter\n"); printf(" -d <number> debug parameter\n");
printf(" The input filename is assumed to be any string not\n"); printf(" The input filename is assumed to be any string not\n");
@@ -1950,9 +1871,6 @@ if (nseqfor) {
if (nseqdistinct) { if (nseqdistinct) {
allDistinctNoteSeq(); allDistinctNoteSeq();
} }
if (pmove) {
allPitchDifference();
}
if (corestats) corestatsOutput(); if (corestats) corestatsOutput();
if (pitchclassanalysis) { if (pitchclassanalysis) {
pitchClassAnalysis(); pitchClassAnalysis();
@@ -1973,7 +1891,6 @@ int argc;
if(stats == 1) midistats(argc,argv); if(stats == 1) midistats(argc,argv);
if(pulseanalysis || corestats || percanalysis ||\ if(pulseanalysis || corestats || percanalysis ||\
percpatternfor || percpattern || percpatternhist ||\ percpatternfor || percpattern || percpatternhist ||\
pitchclassanalysis || nseqfor || nseqdistinct ||\ pitchclassanalysis || nseqfor || nseqdistinct) loadEvents();
pmove) loadEvents();
return 0; return 0;
} }