diff --git a/doc/midistats.1 b/doc/midistats.1 index ae2f59f..6b9c5d4 100644 --- a/doc/midistats.1 +++ b/doc/midistats.1 @@ -1,4 +1,4 @@ -.TH MIDISTATS 1 "04 January 2024" +.TH MIDISTATS 1 "11 February 2024" .SH NAME \fBmidistats\fP \- program to summarize the statistical properties of a midi file .SH SYNOPSIS @@ -26,7 +26,7 @@ applies. program is followed by the channel number and the General Midi Program number. .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: the channel number, the first program assigned to this channel, @@ -44,6 +44,10 @@ the minimum note length in pulses the maximum note length in pulses the number of gaps in the 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 After processing all the individual tracks, the following information 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 distinct rhythm patterns are counted as one. .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 other characteristics. They include @@ -250,6 +277,7 @@ splits the two 4-bit values with a period. Thus 33 = (2*16 + 1). -pitchclass .br Returns the pitch class distribution for the entire midi file. + .PP -nseqfor n .br @@ -274,7 +302,16 @@ repeating patterns. .br Same as above except it is applied to all channels except the 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) diff --git a/doc/readme.txt b/doc/readme.txt index ec25211..0b30969 100644 --- a/doc/readme.txt +++ b/doc/readme.txt @@ -6,7 +6,7 @@ abc2abc version 2.20 February 07 2023 yaps version 1.92 January 06 2023 abcmatch version 1.82 June 14 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 Copyright James Allwright diff --git a/midistats.c b/midistats.c index 6c3765b..9fb7a09 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 "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 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_eot (); void keymatch(); -void outputNoteMemory(); +void outputChannelSummary(); void clearTrackNm (); #define max(a,b) (( a > b ? a : b)) @@ -102,7 +102,6 @@ int percpatternfor; int percpatternhist; int pitchclassanalysis; int nseqfor; -int pmove; int corestats; int chordthreshold; /* number of maximum number of pulses separating note */ 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]; unsigned char drumpat[8000]; unsigned char pseq[8000]; -unsigned char maxpitch[8000]; int pseqhist[128]; int percnum; int nseqchn; @@ -204,6 +202,8 @@ struct notememory {int eighthUnit; int zeroCount; int stepCount; int jumpCount; + int totalNotes; + int totalPitches; } nm[17]; struct notememory tracknm; @@ -562,12 +562,6 @@ tripletsCriterion8 = (float) pulseDistribution[8]/ (float) ncounts; tripletsCriterion4 = (float) pulseDistribution[4]/ (float) ncounts; if (tripletsCriterion8 > 0.10 || tripletsCriterion4 > 0.10) printf("triplets\n"); if (pulseDistribution[0]/(float) ncounts > 0.95) printf("qnotes"); -/* -printf("pulseDistribution:"); -for (i=0;i 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"); 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].stepCount = 0; nm[i].jumpCount = 0; + nm[i].totalNotes =0; + nm[i].totalPitches =0; } } @@ -789,6 +787,8 @@ void clearTrackNm () { tracknm.zeroCount = 0; tracknm.stepCount = 0; tracknm.jumpCount = 0; + tracknm.totalNotes = 0; + tracknm.totalPitches = 0; } 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; nm[chn].eighthUnit = unit; -/*printf("%d, %d, %d, %d, %d, %d %d\n",unit,nm[chn].beforePitch,nm[chn].previousPitch,\ - deltaPitch,nm[chn].zeroCount,nm[chn].stepCount,nm[chn].jumpCount); -*/ - +nm[chn].totalNotes++; +nm[chn].totalPitches = nm[chn].totalPitches + 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 = 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 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; for (i=0;i<17;i++) { - if (i == 9) continue; - if ((nm[i].zeroCount + nm[i].stepCount+nm[i].jumpCount) == 0) continue; - printf("nzeros: "); + printf("nnotes: "); + for(i=0;i<16;i++) printf(" %d",nm[i].totalNotes); + printf("\nnzeros: "); for(i=0;i<16;i++) printf(" %d",nm[i].zeroCount); printf("\nnsteps: "); for(i=0;i<16;i++) printf(" %d",nm[i].stepCount); printf("\nnjumps: "); 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) { @@ -1835,11 +1762,6 @@ int argc; nseqchn = -1; } - arg = getarg("-pmove",argc,argv); - if (arg != -1) { - pmove = 1; - stats = 0; - } arg = getarg("-nseqtokens",argc,argv); if (arg != -1) { @@ -1891,7 +1813,6 @@ int argc; printf(" -nseq\n"); printf(" -nseqfor channel\n"); printf(" -nseqtokens\n"); - printf(" -pmove\n"); printf(" -ver version number\n"); printf(" -d debug parameter\n"); printf(" The input filename is assumed to be any string not\n"); @@ -1950,9 +1871,6 @@ if (nseqfor) { if (nseqdistinct) { allDistinctNoteSeq(); } -if (pmove) { - allPitchDifference(); - } if (corestats) corestatsOutput(); if (pitchclassanalysis) { pitchClassAnalysis(); @@ -1973,7 +1891,6 @@ int argc; if(stats == 1) midistats(argc,argv); if(pulseanalysis || corestats || percanalysis ||\ percpatternfor || percpattern || percpatternhist ||\ - pitchclassanalysis || nseqfor || nseqdistinct ||\ - pmove) loadEvents(); + pitchclassanalysis || nseqfor || nseqdistinct) loadEvents(); return 0; }