mirror of
https://github.com/sshlien/abcmidi.git
synced 2025-12-06 06:55:06 +00:00
2024.02.11
This commit is contained in:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
133
midistats.c
133
midistats.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user