mirror of
https://github.com/sshlien/abcmidi.git
synced 2025-12-06 06:55:06 +00:00
2022.12.09
This commit is contained in:
@@ -14865,3 +14865,7 @@ separate applications. Midistats is a new application that will replace
|
|||||||
the midi2abc -midistats option.
|
the midi2abc -midistats option.
|
||||||
|
|
||||||
|
|
||||||
|
December 9 2022
|
||||||
|
|
||||||
|
Cleaning out -stats code in midi2abc.
|
||||||
|
|
||||||
|
|||||||
@@ -172,23 +172,6 @@ the given string.
|
|||||||
.B -origin \fistring\fP
|
.B -origin \fistring\fP
|
||||||
Adds an O: field with the given string.
|
Adds an O: field with the given string.
|
||||||
.TP
|
.TP
|
||||||
.B -stats
|
|
||||||
Extracts the characteristics of the given midi file. They include
|
|
||||||
ntrks - the number of tracks, ppqn - pulses per quarter note,
|
|
||||||
timesig - time signature, keysig - key signature, program - mapping
|
|
||||||
between channel number and midi program, npulses - length of the
|
|
||||||
midi file in pulses, tempocmd - number of times the tempo has
|
|
||||||
been specified, pitchbends - number of pitchbends, pitchbendin -
|
|
||||||
number of pitchbends in each of the channels, programcmd - number of
|
|
||||||
times the midi program has been revised, progs and progsact - the
|
|
||||||
programs used and the number of pulses these programs used, drums -
|
|
||||||
the drum numbers that were used, drumhits - the number of times
|
|
||||||
each of those drums were hit, pitches - the number of times the
|
|
||||||
11 pitch classes (C C# etc...) were activated and a few other
|
|
||||||
complex variables. These characteristics are used in other
|
|
||||||
applications such as midiexplorer. More details are available
|
|
||||||
in the file midi2abc-stats.txt included in the doc/ folder
|
|
||||||
of the abcmidi distribution package.
|
|
||||||
|
|
||||||
|
|
||||||
.SS FEATURES
|
.SS FEATURES
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH MIDISTATS 1 "3 December 2022"
|
.TH MIDISTATS 1 "9 December 2022"
|
||||||
.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
|
||||||
@@ -35,17 +35,12 @@ the total number of notes for this for this channel,
|
|||||||
the sum of the MIDI pitches for all the notes,
|
the sum of the MIDI pitches for all the notes,
|
||||||
the sum of the note durations in MIDI pulse units,
|
the sum of the note durations in MIDI pulse units,
|
||||||
the number of control parameter messages,
|
the number of control parameter messages,
|
||||||
and the number of pressure messages.
|
the number of pressure messages.
|
||||||
|
and the number of distinct rhythm patterns for each channel
|
||||||
.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.
|
||||||
.PP
|
.PP
|
||||||
rhythmPatterns indicates the number of distinct rhythm patterns for each
|
|
||||||
channel. A large number likely implies that the melody line occurs in
|
|
||||||
this channel, while a small number indicates that this channel probably
|
|
||||||
is used for chordal support.
|
|
||||||
.PP
|
|
||||||
npulses is the length of the longest midi track in midi pulse units
|
npulses is the length of the longest midi track in midi pulse units
|
||||||
.PP
|
.PP
|
||||||
tempocmds specifies the number of times the tempo is changed in this
|
tempocmds specifies the number of times the tempo is changed in this
|
||||||
@@ -74,7 +69,17 @@ that occur in the midi file.
|
|||||||
.PP
|
.PP
|
||||||
pitchact is a similar histogram but is weighted by the length of
|
pitchact is a similar histogram but is weighted by the length of
|
||||||
the notes.
|
the notes.
|
||||||
|
.PP
|
||||||
|
quietTime is used to compute the track/channel spread in midiexplorer.
|
||||||
|
It is computed by summing up all the midi pulses which occur
|
||||||
|
in gaps greater than 8 beats.
|
||||||
|
.PP
|
||||||
|
totalrhythmpatterns is the total number of bar rhythm patterns for
|
||||||
|
all channels except the percussion channel.
|
||||||
|
.PP
|
||||||
|
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.
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Seymour Shlien <fy733@ncf.ca>
|
Seymour Shlien <fy733@ncf.ca>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
/abc2midi.txt/1.1.1.1/Thu Sep 28 18:17:04 2006//
|
|
||||||
/coding.txt/1.1.1.1/Thu Sep 28 18:17:04 2006//
|
|
||||||
/midi2abc.txt/1.1.1.1/Thu Sep 28 18:17:04 2006//
|
|
||||||
/split.abc/1.1.1.1/Thu Sep 28 18:17:04 2006//
|
|
||||||
/yaps.txt/1.1.1.1/Thu Sep 28 18:17:04 2006//
|
|
||||||
D
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
abcmidi/doc/programming
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/home/seymour/CVSREPOS
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
abcMIDI : abc <-> MIDI conversion utilities
|
abcMIDI : abc <-> MIDI conversion utilities
|
||||||
|
|
||||||
midi2abc version 3.57 September 01 2022
|
midi2abc version 3.58 December 09 2022
|
||||||
abc2midi version 4.76 August 01 2022
|
abc2midi version 4.76 August 01 2022
|
||||||
abc2abc version 2.18 June 14 2022
|
abc2abc version 2.18 June 14 2022
|
||||||
yaps version 1.90 June 14 2022
|
yaps version 1.90 June 14 2022
|
||||||
abcmatch version 1.82 June 14 2022
|
abcmatch version 1.82 June 14 2022
|
||||||
midicopy version 1.38 May 06 2022
|
midicopy version 1.38 May 06 2022
|
||||||
midistats version 0.56 December 07 2022
|
midistats version 0.58 December 09 2022
|
||||||
|
|
||||||
24th January 2002
|
24th January 2002
|
||||||
|
|
||||||
|
|||||||
457
midi2abc.c
457
midi2abc.c
@@ -45,7 +45,7 @@
|
|||||||
* based on public domain 'midifilelib' package.
|
* based on public domain 'midifilelib' package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERSION "3.57 September 01 2022 midi2abc"
|
#define VERSION "3.58 December 09 2022 midi2abc"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
/* Microsoft Visual C++ Version 6.0 or higher */
|
/* Microsoft Visual C++ Version 6.0 or higher */
|
||||||
@@ -79,12 +79,9 @@ extern char* strchr();
|
|||||||
#define MIDDLE 72
|
#define MIDDLE 72
|
||||||
void initfuncs();
|
void initfuncs();
|
||||||
void setupkey(int);
|
void setupkey(int);
|
||||||
void stats_finish();
|
|
||||||
int testtrack(int trackno, int barbeats, int anacrusis);
|
int testtrack(int trackno, int barbeats, int anacrusis);
|
||||||
int open_note(int chan, int pitch, int vol);
|
int open_note(int chan, int pitch, int vol);
|
||||||
int close_note(int chan, int pitch, int *initvol);
|
int close_note(int chan, int pitch, int *initvol);
|
||||||
float histogram_entropy (int *histogram, int size);
|
|
||||||
void stats_noteoff(int chan,int pitch,int vol);
|
|
||||||
void reset_back_array (); /* [SS] 2019-05-08 */
|
void reset_back_array (); /* [SS] 2019-05-08 */
|
||||||
|
|
||||||
|
|
||||||
@@ -251,67 +248,7 @@ void txt_trackstart_type0();
|
|||||||
void txt_noteon_type0(int,int,int);
|
void txt_noteon_type0(int,int,int);
|
||||||
void txt_program_type0(int,int);
|
void txt_program_type0(int,int);
|
||||||
|
|
||||||
/* The following variables are used by the -stats option
|
|
||||||
* which is used by a separate application called midiexplorer.tcl.
|
|
||||||
* The channel numbers go from 1 to 16 instead of 0 to 15
|
|
||||||
*/
|
|
||||||
struct trkstat {
|
|
||||||
int notecount[17];
|
|
||||||
int chordcount[17];
|
|
||||||
int notemeanpitch[17];
|
|
||||||
int notelength[17];
|
|
||||||
int pitchbend[17];
|
|
||||||
int pressure[17];
|
|
||||||
int cntlparam[17];
|
|
||||||
int program[17];
|
|
||||||
int tempo[17];
|
|
||||||
int npulses[17];
|
|
||||||
int lastNoteOff[17];
|
|
||||||
int quietTime[17];
|
|
||||||
} trkdata;
|
|
||||||
|
|
||||||
/* The trkstat references the individual channels in the midi file.
|
|
||||||
* notecount is the number of notes or bass notes in the chord.
|
|
||||||
* chordcount is the number of notes not counting the bass notes.
|
|
||||||
* notemeanpitch is the average pitch for the channel.
|
|
||||||
* notelength is the average note length.
|
|
||||||
* pitchbend is the number of pitch bends for the channel.
|
|
||||||
* pressure is the number of control pressure commands.
|
|
||||||
* cntlparam is the number of control parameter commands.
|
|
||||||
* program is number of times there is a program command for the channel.
|
|
||||||
* tempo is the number of times there is a tempo command.
|
|
||||||
* npulses is the number of pulses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int progcolor[17]; /* used by stats_program */
|
|
||||||
int drumhistogram[82]; /* counts drum noteons */
|
|
||||||
int pitchhistogram[12]; /* pitch distribution for non drum notes */
|
|
||||||
int channel2prog[17]; /* maps channel to program */
|
|
||||||
int channel2nnotes[17]; /*maps channel to note count */
|
|
||||||
int chnactivity[17]; /* [SS] 2018-02-02 */
|
|
||||||
int progactivity[128]; /* [SS] 2018-02-02 */
|
|
||||||
int pitchclass_activity[12]; /* [SS] 2018-02-02 */
|
|
||||||
|
|
||||||
|
|
||||||
/* [SS] 2017-11-01 */
|
|
||||||
static int progmapper[] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 1, 1, 1, 1, 1, 1, 2,
|
|
||||||
3, 3, 3, 3, 3, 3, 3, 3,
|
|
||||||
2, 2, 4, 4, 4, 4, 4, 2,
|
|
||||||
5, 5, 5, 5, 5, 5, 5, 5,
|
|
||||||
6, 6, 6, 6, 6, 2, 7, 10,
|
|
||||||
7, 7, 7, 7, 8, 8, 8, 8,
|
|
||||||
9, 9, 9, 9, 9, 9, 9, 9,
|
|
||||||
11, 11, 11, 11, 11, 11, 11, 11,
|
|
||||||
12, 12, 12, 12, 12, 12, 12, 12,
|
|
||||||
13, 13, 13, 13, 13, 13, 13, 13,
|
|
||||||
14, 14, 14, 14, 14, 14, 14, 14,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
2, 2, 2, 2, 2, 12, 6, 12,
|
|
||||||
1, 1, 10, 10, 10, 10, 10, 1,
|
|
||||||
16, 16, 16, 16, 16, 16, 16, 16
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Stage 1. Parsing MIDI file */
|
/* Stage 1. Parsing MIDI file */
|
||||||
|
|
||||||
@@ -609,15 +546,6 @@ char *s;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* [SS] 2017-11-19 */
|
|
||||||
void stats_error(s)
|
|
||||||
char *s;
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Error: %s\n",s);
|
|
||||||
fprintf(stderr,"activetrack %d\n",tracknum);
|
|
||||||
stats_finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void txt_header(xformat,ntrks,ldivision)
|
void txt_header(xformat,ntrks,ldivision)
|
||||||
@@ -731,12 +659,6 @@ int chan, pitch, press;
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void stats_pressure(chan,press)
|
|
||||||
int chan, press;
|
|
||||||
{
|
|
||||||
trkdata.pressure[0]++;
|
|
||||||
trkdata.pressure[chan+1]++; /* [SS] 2022.04.28 */
|
|
||||||
}
|
|
||||||
|
|
||||||
void txt_parameter(chan,control,value)
|
void txt_parameter(chan,control,value)
|
||||||
int chan, control, value;
|
int chan, control, value;
|
||||||
@@ -1140,145 +1062,7 @@ void mftxt_header (int format, int ntrks, int ldivision)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stats_header (int format, int ntrks, int ldivision)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
division = ldivision;
|
|
||||||
quietLimit = ldivision*8;
|
|
||||||
printf("ntrks %d\n",ntrks);
|
|
||||||
printf("ppqn %d\n",ldivision);
|
|
||||||
chordthreshold = ldivision/16; /* [SS] 2018-01-21 */
|
|
||||||
trkdata.tempo[0] = 0;
|
|
||||||
trkdata.pressure[0] = 0;
|
|
||||||
trkdata.program[0] = 0;
|
|
||||||
for (i=0;i<17;i++) {
|
|
||||||
trkdata.npulses[i] = 0;
|
|
||||||
trkdata.pitchbend[i] = 0;
|
|
||||||
trkdata.cntlparam[i] = 0; /* [SS] 2022-03-04 */
|
|
||||||
trkdata.pressure[i] = 0; /* [SS] 2022-03-04 */
|
|
||||||
trkdata.quietTime[i] = 0; /* [SS] 2022-08-22 */
|
|
||||||
progcolor[i] = 0;
|
|
||||||
channel2prog[i] = -1;
|
|
||||||
channel2nnotes[i] = 0;
|
|
||||||
chnactivity[i] = 0; /* [SS] 2018-02-02 */
|
|
||||||
}
|
|
||||||
for (i=0;i<82;i++) drumhistogram[i] = 0;
|
|
||||||
for (i=0;i<12;i++) pitchhistogram[i] = 0; /* [SS] 2017-11-01 */
|
|
||||||
for (i=0;i<12;i++) pitchclass_activity[i] = 0; /* [SS] 2018-02-02 */
|
|
||||||
for (i=0;i<128;i++) progactivity[i] = 0; /* [SS] 2018-02-02 */
|
|
||||||
}
|
|
||||||
|
|
||||||
void determine_progcolor ()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0;i<17;i++) progcolor[i] =0;
|
|
||||||
for (i=0;i<128;i++) {
|
|
||||||
progcolor[progmapper[i]] += progactivity[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* [SS] 2018-04-24 */
|
|
||||||
void output_progs_data () {
|
|
||||||
int i;
|
|
||||||
/* check that there is valid progactivity */
|
|
||||||
|
|
||||||
printf("progs ");
|
|
||||||
for (i=0;i<128;i++)
|
|
||||||
if(progactivity[i] > 0) printf(" %d",i);
|
|
||||||
printf("\nprogsact ");
|
|
||||||
for (i=0;i<128;i++)
|
|
||||||
if(progactivity[i] > 0) printf(" %d",progactivity[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void stats_finish()
|
|
||||||
{
|
|
||||||
int i; /* [SDG] 2020-06-03 */
|
|
||||||
int npulses;
|
|
||||||
int nprogs;
|
|
||||||
double delta;
|
|
||||||
|
|
||||||
npulses = trkdata.npulses[0];
|
|
||||||
printf("npulses %d\n",trkdata.npulses[0]);
|
|
||||||
printf("tempocmds %d\n",trkdata.tempo[0]);
|
|
||||||
printf("pitchbends %d\n",trkdata.pitchbend[0]);
|
|
||||||
for (i=1;i<17;i++) {
|
|
||||||
if (trkdata.pitchbend[i] > 0) {
|
|
||||||
printf("pitchbendin %d %d\n",i,trkdata.pitchbend[i]); }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trkdata.pressure[0] > 0)
|
|
||||||
printf("pressure %d\n",trkdata.pressure[0]);
|
|
||||||
printf("programcmd %d\n",trkdata.program[0]);
|
|
||||||
|
|
||||||
nprogs = 0; /* [SS] 2018-04-24 */
|
|
||||||
for (i=1;i<128;i++)
|
|
||||||
if(progactivity[i] >0) nprogs++;
|
|
||||||
if (nprogs > 0) output_progs_data();
|
|
||||||
else {
|
|
||||||
for (i=0;i<17;i++)
|
|
||||||
if(chnactivity[i] > 0)
|
|
||||||
progactivity[channel2prog[i]] = chnactivity[i];
|
|
||||||
output_progs_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
determine_progcolor();
|
|
||||||
printf("\nprogcolor ");
|
|
||||||
if (npulses > 0)
|
|
||||||
for (i=0;i<17;i++) printf("%5.2f ",progcolor[i]/(double) npulses);
|
|
||||||
else
|
|
||||||
for (i=0;i<17;i++) printf("%5.2f ",(double) progcolor[i]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
printf("drums ");
|
|
||||||
for (i=35;i<82;i++) {
|
|
||||||
if (drumhistogram[i] > 0) printf("%d ",i);
|
|
||||||
}
|
|
||||||
printf("\ndrumhits ");
|
|
||||||
for (i=35;i<82;i++) {
|
|
||||||
if (drumhistogram[i] > 0) printf("%d ",drumhistogram[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\npitches "); /* [SS] 2017-11-01 */
|
|
||||||
for (i=0;i<12;i++) printf("%d ",pitchhistogram[i]);
|
|
||||||
printf("\npitchact "); /* [SS] 2018-02-02 */
|
|
||||||
if (npulses > 0)
|
|
||||||
for (i=0;i<12;i++) printf("%5.2f ",pitchclass_activity[i]/(double) npulses);
|
|
||||||
else
|
|
||||||
for (i=0;i<12;i++) printf("%5.2f ",(double) pitchclass_activity[i]);
|
|
||||||
printf("\nchnact "); /* [SS] 2018-02-08 */
|
|
||||||
if (npulses > 0)
|
|
||||||
for (i=1;i<17;i++) printf("%5.2f ",chnactivity[i]/(double) trkdata.npulses[0]);
|
|
||||||
else
|
|
||||||
for (i=0;i<17;i++) printf("%5.2f ",(double) chnactivity[i]);
|
|
||||||
|
|
||||||
printf("\npitchentropy %f\n",histogram_entropy(pitchclass_activity,12));
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float histogram_entropy (int *histogram, int size)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int total;
|
|
||||||
float entropy;
|
|
||||||
float e,p;
|
|
||||||
total = 0;
|
|
||||||
entropy = 0.0;
|
|
||||||
for (i=0;i<size;i++) {
|
|
||||||
total += histogram[i];
|
|
||||||
}
|
|
||||||
for (i=0;i<size;i++) {
|
|
||||||
if (histogram[i] < 1) continue;
|
|
||||||
p = (float) histogram[i]/total;
|
|
||||||
e = p*log(p);
|
|
||||||
entropy = entropy + e;
|
|
||||||
}
|
|
||||||
return -entropy/log(2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1291,70 +1075,9 @@ void mftxt_trackstart()
|
|||||||
printf("Track %d contains %d bytes\n",tracknum,numbytes);
|
printf("Track %d contains %d bytes\n",tracknum,numbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_count_trkdata(data_array,name)
|
|
||||||
int data_array[];
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
int i,sum;
|
|
||||||
sum = 0;
|
|
||||||
for (i=1;i<17;i++) sum += data_array[i];
|
|
||||||
if (sum != 0) {
|
|
||||||
for (i=0;i<17;i++)
|
|
||||||
if(data_array[i]>0) {
|
|
||||||
printf("%s ",name);
|
|
||||||
printf("%d %d ",i,data_array[i]);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void output_track_summary () {
|
|
||||||
int i;
|
|
||||||
/* find first channel containing data */
|
|
||||||
for (i=0;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*/
|
|
||||||
printf("%d %d ",trkdata.notecount[i],trkdata.chordcount[i]);
|
|
||||||
printf("%d %d ",trkdata.notemeanpitch[i], trkdata.notelength[i]);
|
|
||||||
printf("%d %d ",trkdata.cntlparam[i],trkdata.pressure[i]); /* [SS] 2022-03-04 */
|
|
||||||
printf("%d ",trkdata.quietTime[i]); /* [SS] 2022.09.01 */
|
|
||||||
trkdata.quietTime[i] = 0;
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
channel2nnotes[i] += trkdata.notecount[i] + trkdata.chordcount[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void stats_trackstart()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
tracknum++;
|
|
||||||
for (i=0;i<17;i++) {
|
|
||||||
trkdata.notecount[i] = 0;
|
|
||||||
trkdata.notemeanpitch[i] = 0;
|
|
||||||
trkdata.notelength[i] = 0;
|
|
||||||
trkdata.chordcount[i] = 0;
|
|
||||||
trkdata.cntlparam[i] = 0;
|
|
||||||
last_tick[i] = -1;
|
|
||||||
last_on_tick[i] = -1;
|
|
||||||
}
|
|
||||||
printf("trk %d \n",tracknum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stats_trackend()
|
|
||||||
{
|
|
||||||
trkdata.npulses[tracknum] = Mf_currtime;
|
|
||||||
if (trkdata.npulses[0] < Mf_currtime) trkdata.npulses[0] = Mf_currtime;
|
|
||||||
output_track_summary();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mftxt_noteon(chan,pitch,vol)
|
void mftxt_noteon(chan,pitch,vol)
|
||||||
int chan, pitch, vol;
|
int chan, pitch, vol;
|
||||||
{
|
{
|
||||||
@@ -1369,38 +1092,6 @@ int chan, pitch, vol;
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void stats_noteon(chan,pitch,vol)
|
|
||||||
int chan, pitch, vol;
|
|
||||||
{
|
|
||||||
int delta;
|
|
||||||
if (vol == 0) {
|
|
||||||
/* treat as noteoff */
|
|
||||||
stats_noteoff(chan,pitch,vol);
|
|
||||||
trkdata.lastNoteOff[chan+1] = Mf_currtime; /* [SS] 2022.08.22 */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
trkdata.notemeanpitch[chan+1] += pitch;
|
|
||||||
if (trkdata.lastNoteOff[chan+1] >= 0) {
|
|
||||||
delta = Mf_currtime - trkdata.lastNoteOff[chan+1];
|
|
||||||
trkdata.lastNoteOff[chan+1] = -1; /* in case of chord */
|
|
||||||
if (delta > quietLimit) {
|
|
||||||
trkdata.quietTime[chan+1] += delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abs(Mf_currtime - last_on_tick[chan+1]) < chordthreshold) trkdata.chordcount[chan+1]++;
|
|
||||||
else trkdata.notecount[chan+1]++; /* [SS] 2019-08-02 */
|
|
||||||
last_tick[chan+1] = Mf_currtime;
|
|
||||||
last_on_tick[chan+1] = Mf_currtime; /* [SS] 2019-08-02 */
|
|
||||||
/* last_on_tick not updated by stats_noteoff */
|
|
||||||
if (chan == 9) {
|
|
||||||
if (pitch < 0 || pitch > 81)
|
|
||||||
printf("****illegal drum value %d\n",pitch);
|
|
||||||
else drumhistogram[pitch]++;
|
|
||||||
}
|
|
||||||
else pitchhistogram[pitch % 12]++; /* [SS] 2017-11-01 */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mftxt_noteoff(chan,pitch,vol)
|
void mftxt_noteoff(chan,pitch,vol)
|
||||||
int chan, pitch, vol;
|
int chan, pitch, vol;
|
||||||
@@ -1415,28 +1106,6 @@ int chan, pitch, vol;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stats_noteoff(int chan,int pitch,int vol)
|
|
||||||
{
|
|
||||||
int length;
|
|
||||||
int program;
|
|
||||||
/* ignore if there was no noteon */
|
|
||||||
if (last_tick[chan+1] == -1) return;
|
|
||||||
length = Mf_currtime - last_tick[chan+1];
|
|
||||||
trkdata.notelength[chan+1] += length;
|
|
||||||
trkdata.lastNoteOff[chan+1] = Mf_currtime; /* [SS] 2022.08.22 */
|
|
||||||
chnactivity[chan+1] += length;
|
|
||||||
if (chan == 9) return; /* drum channel */
|
|
||||||
pitchclass_activity[pitch % 12] += length;
|
|
||||||
program = trkdata.program[chan+1];
|
|
||||||
progactivity[program] += length;
|
|
||||||
/* [SS] 2018-04-18 */
|
|
||||||
if(Mf_currtime > last_tick[chan+1]) last_tick[chan+1] = Mf_currtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stats_eot () {
|
|
||||||
trkdata.lastNoteOff[0] = Mf_currtime; /* [SS] 2022.08.24 */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void mftxt_polypressure(chan,pitch,press)
|
void mftxt_polypressure(chan,pitch,press)
|
||||||
@@ -1474,12 +1143,6 @@ int chan, lsb, msb;
|
|||||||
printf("Pitchbend %2d %d cents = %6.3f (cents)\n",chan+1,pitchbend,cents);
|
printf("Pitchbend %2d %d cents = %6.3f (cents)\n",chan+1,pitchbend,cents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stats_pitchbend(chan,lsb,msb)
|
|
||||||
int chan, lsb, msb;
|
|
||||||
{
|
|
||||||
trkdata.pitchbend[0]++;
|
|
||||||
trkdata.pitchbend[chan+1]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mftxt_program(chan,program)
|
void mftxt_program(chan,program)
|
||||||
int chan, program;
|
int chan, program;
|
||||||
@@ -1536,23 +1199,6 @@ static char *patches[] = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stats_program(chan,program)
|
|
||||||
int chan, program;
|
|
||||||
{
|
|
||||||
int beatnumber;
|
|
||||||
if (program <0 || program > 127) return; /* [SS] 2018-03-06 */
|
|
||||||
if (trkdata.program[chan+1] != 0) {
|
|
||||||
beatnumber = Mf_currtime/division;
|
|
||||||
printf("cprogram %d %d %d\n",chan+1,program,beatnumber);
|
|
||||||
/* count number of times the program was modified for a channel */
|
|
||||||
trkdata.program[0] = trkdata.program[0]+1;
|
|
||||||
} else {
|
|
||||||
printf("program %d %d\n",chan+1,program);
|
|
||||||
trkdata.program[chan+1] = program;
|
|
||||||
}
|
|
||||||
if (channel2prog[chan+1]== -1) channel2prog[chan+1] = program;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mftxt_parameter(chan,control,value)
|
void mftxt_parameter(chan,control,value)
|
||||||
int chan, control, value;
|
int chan, control, value;
|
||||||
@@ -1631,15 +1277,6 @@ int chan, control, value;
|
|||||||
printf("CntlParm %2d %s = %d\n",chan+1, ctype[control],value);
|
printf("CntlParm %2d %s = %d\n",chan+1, ctype[control],value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stats_parameter(chan,control,value)
|
|
||||||
int chan, control, value;
|
|
||||||
{
|
|
||||||
/*if (control == 7) {
|
|
||||||
printf("cntrlvolume %d %d \n",chan+1,value);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
trkdata.cntlparam[chan+1]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mftxt_metatext(type,leng,mess)
|
void mftxt_metatext(type,leng,mess)
|
||||||
int type, leng;
|
int type, leng;
|
||||||
@@ -1677,17 +1314,6 @@ char *mess;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stats_metatext(type,leng,mess)
|
|
||||||
int type, leng;
|
|
||||||
char *mess;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (type != 3) return;
|
|
||||||
printf("metatext %d ",type);
|
|
||||||
for (i=0;i<leng;i++) printf("%c",mess[i]);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mftxt_keysig(sf,mi)
|
void mftxt_keysig(sf,mi)
|
||||||
int sf, mi;
|
int sf, mi;
|
||||||
@@ -1706,25 +1332,6 @@ int sf, mi;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* [SS] 2018-01-02 */
|
|
||||||
void stats_keysig(sf,mi)
|
|
||||||
int sf, mi;
|
|
||||||
{
|
|
||||||
float beatnumber;
|
|
||||||
static char *major[] = {"Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F",
|
|
||||||
"C", "G", "D", "A", "E", "B", "F#", "C#"};
|
|
||||||
static char *minor[] = {"Abmin", "Ebmin", "Bbmin", "Fmin", "Cmin",
|
|
||||||
"Gmin", "Dmin", "Amin", "Emin", "Bmin", "F#min", "C#min", "G#min"};
|
|
||||||
int index;
|
|
||||||
beatnumber = Mf_currtime/division;
|
|
||||||
index = sf + 7;
|
|
||||||
if (index < 0 || index >12) return;
|
|
||||||
if (mi)
|
|
||||||
printf("keysig %s %d %d %6.2f\n",minor[index],sf,mi,beatnumber);
|
|
||||||
else
|
|
||||||
printf("keysig %s %d %d %6.2f\n",major[index],sf,mi,beatnumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mftxt_tempo(ltempo)
|
void mftxt_tempo(ltempo)
|
||||||
long ltempo;
|
long ltempo;
|
||||||
@@ -1734,17 +1341,6 @@ long ltempo;
|
|||||||
printf("Metatext tempo = %6.2f bpm\n",60000000.0/tempo);
|
printf("Metatext tempo = %6.2f bpm\n",60000000.0/tempo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [SS] 2018-01-02 */
|
|
||||||
void stats_tempo(ltempo)
|
|
||||||
long ltempo;
|
|
||||||
{
|
|
||||||
float beatnumber;
|
|
||||||
tempo = ltempo;
|
|
||||||
beatnumber = Mf_currtime/division;
|
|
||||||
if (trkdata.tempo[0] == 0) printf("tempo %6.2f bpm\n",60000000.0/tempo);
|
|
||||||
else if (trkdata.tempo[0] < 10) printf("ctempo %6.2f %6.2f\n",60000000.0/tempo,beatnumber);
|
|
||||||
trkdata.tempo[0]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mftxt_timesig(nn,dd,cc,bb)
|
void mftxt_timesig(nn,dd,cc,bb)
|
||||||
int nn, dd, cc, bb;
|
int nn, dd, cc, bb;
|
||||||
@@ -1758,16 +1354,6 @@ int nn, dd, cc, bb;
|
|||||||
32nd-notes/24-MIDI-clocks=%d\n", nn,denom,cc,bb); */
|
32nd-notes/24-MIDI-clocks=%d\n", nn,denom,cc,bb); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void stats_timesig(nn,dd,cc,bb)
|
|
||||||
int nn, dd, cc, bb;
|
|
||||||
{
|
|
||||||
float beatnumber;
|
|
||||||
int denom = 1;
|
|
||||||
beatnumber = Mf_currtime/division;
|
|
||||||
while ( dd-- > 0 )
|
|
||||||
denom *= 2;
|
|
||||||
printf("timesig %d/%d %6.2f\n",nn,denom,beatnumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mftxt_smpte(hr,mn,se,fr,ff)
|
void mftxt_smpte(hr,mn,se,fr,ff)
|
||||||
int hr, mn, se, fr, ff;
|
int hr, mn, se, fr, ff;
|
||||||
@@ -1836,31 +1422,6 @@ void initfunc_for_mftext()
|
|||||||
Mf_arbitrary = no_op2;
|
Mf_arbitrary = no_op2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initfunc_for_stats()
|
|
||||||
{
|
|
||||||
Mf_error = stats_error; /* [SS] 2017-11-19 */
|
|
||||||
Mf_header = stats_header;
|
|
||||||
Mf_trackstart = stats_trackstart;
|
|
||||||
Mf_trackend = stats_trackend;
|
|
||||||
Mf_noteon = stats_noteon;
|
|
||||||
Mf_noteoff = stats_noteoff;
|
|
||||||
Mf_pressure = no_op3;
|
|
||||||
Mf_parameter = stats_parameter;
|
|
||||||
Mf_pitchbend = stats_pitchbend;
|
|
||||||
Mf_program = stats_program;
|
|
||||||
Mf_chanpressure = stats_pressure;
|
|
||||||
Mf_sysex = no_op2;
|
|
||||||
Mf_metamisc = no_op3;
|
|
||||||
Mf_seqnum = no_op1;
|
|
||||||
Mf_eot = stats_eot;
|
|
||||||
Mf_timesig = stats_timesig;
|
|
||||||
Mf_smpte = no_op5;
|
|
||||||
Mf_tempo = stats_tempo;
|
|
||||||
Mf_keysig = stats_keysig;
|
|
||||||
Mf_seqspecific = no_op3;
|
|
||||||
Mf_text = stats_metatext;
|
|
||||||
Mf_arbitrary = no_op2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3662,7 +3223,8 @@ int argc;
|
|||||||
arg = getarg("-stats",argc,argv);
|
arg = getarg("-stats",argc,argv);
|
||||||
if (arg != -1)
|
if (arg != -1)
|
||||||
{
|
{
|
||||||
stats = 1;
|
printf("\nuse the new application midistats\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
arg = getarg("-d",argc,argv);
|
arg = getarg("-d",argc,argv);
|
||||||
@@ -3875,7 +3437,6 @@ int argc;
|
|||||||
printf(" -mftext mftext output in beats\n");
|
printf(" -mftext mftext output in beats\n");
|
||||||
printf(" -mftextpulses mftext output in midi pulses\n");
|
printf(" -mftextpulses mftext output in midi pulses\n");
|
||||||
printf(" -mftext mftext output in seconds\n");
|
printf(" -mftext mftext output in seconds\n");
|
||||||
printf(" -stats summary and statistics output\n");
|
|
||||||
printf(" -ver version number\n");
|
printf(" -ver version number\n");
|
||||||
printf(" -d <number> debug parameter\n");
|
printf(" -d <number> debug parameter\n");
|
||||||
printf(" None or only one of the options -aul -gu, -b, -Q -u should\n");
|
printf(" None or only one of the options -aul -gu, -b, -Q -u should\n");
|
||||||
@@ -4124,17 +3685,6 @@ mfread();
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void midistats(argc,argv)
|
|
||||||
char *argv[];
|
|
||||||
int argc;
|
|
||||||
{
|
|
||||||
initfunc_for_stats();
|
|
||||||
Mf_getc = filegetc;
|
|
||||||
mfread();
|
|
||||||
stats_finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(argc,argv)
|
int main(argc,argv)
|
||||||
char *argv[];
|
char *argv[];
|
||||||
@@ -4146,7 +3696,6 @@ int argc;
|
|||||||
arg = process_command_line_arguments(argc,argv);
|
arg = process_command_line_arguments(argc,argv);
|
||||||
if(midiprint ==1) { midigram(argc,argv);
|
if(midiprint ==1) { midigram(argc,argv);
|
||||||
} else if(midiprint ==2) { mftext(argc,argv);
|
} else if(midiprint ==2) { mftext(argc,argv);
|
||||||
} else if(stats == 1) { midistats(argc,argv);
|
|
||||||
} else midi2abc(argc,argv);
|
} else midi2abc(argc,argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
30
midistats.c
30
midistats.c
@@ -18,7 +18,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.56 December 07 2022 midistats"
|
#define VERSION "0.58 December 08 2022 midistats"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
/* Microsoft Visual C++ Version 6.0 or higher */
|
/* Microsoft Visual C++ Version 6.0 or higher */
|
||||||
@@ -166,29 +166,35 @@ struct barPattern {
|
|||||||
} barChn[17];
|
} barChn[17];
|
||||||
|
|
||||||
|
|
||||||
#define HashSize 255
|
#define HashSize 257
|
||||||
struct hashStruct {
|
struct hashStruct {
|
||||||
int pattern[HashSize];
|
int pattern[HashSize];
|
||||||
int count[HashSize];
|
int count[HashSize];
|
||||||
} hasher[17] = {0};
|
} hasher[17] = {0};
|
||||||
|
|
||||||
int ncollisions = 0;
|
int ncollisions = 0;
|
||||||
|
int nrpatterns = 0;
|
||||||
|
|
||||||
|
void handle_collision () {
|
||||||
|
ncollisions++;
|
||||||
|
}
|
||||||
|
|
||||||
void put_pattern (int chan, int pattern) {
|
void put_pattern (int chan, int pattern) {
|
||||||
int hashindex;
|
int hashindex;
|
||||||
hashindex = pattern % HashSize;
|
hashindex = pattern % HashSize;
|
||||||
if (hasher[chan].pattern[hashindex] == 0) {
|
if (hasher[chan].pattern[hashindex] == 0) {
|
||||||
hasher[chan].pattern[hashindex] = pattern;
|
hasher[chan].pattern[hashindex] = pattern;
|
||||||
|
nrpatterns++;
|
||||||
/*printf ("hasher[%d].pattern[%d] = %d\n",chan,hashindex,pattern);*/
|
/*printf ("hasher[%d].pattern[%d] = %d\n",chan,hashindex,pattern);*/
|
||||||
} else {
|
} else if (hasher[chan].pattern[hashindex] != pattern) {
|
||||||
if (hasher[chan].pattern[hashindex] != pattern) {
|
|
||||||
/* printf("collision\n"); */
|
/* printf("collision\n"); */
|
||||||
ncollisions++;
|
handle_collision ();
|
||||||
}
|
} else {
|
||||||
|
hasher[chan].count[hashindex]++;
|
||||||
}
|
}
|
||||||
hasher[chan].count[hashindex]++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int count_patterns_for (int chan) {
|
int count_patterns_for (int chan) {
|
||||||
int i;
|
int i;
|
||||||
int sum;
|
int sum;
|
||||||
@@ -204,14 +210,12 @@ return sum;
|
|||||||
|
|
||||||
void output_hasher_results () {
|
void output_hasher_results () {
|
||||||
int i;
|
int i;
|
||||||
printf("rhythmPatterns ");
|
/* printf("rhythmPatterns ");*/
|
||||||
for (i = 0; i<16; i++) {
|
for (i = 0; i<17; i++) {
|
||||||
trkdata.rhythmpatterns[i] = count_patterns_for(i);
|
trkdata.rhythmpatterns[i] = count_patterns_for(i);
|
||||||
printf("%d ",count_patterns_for (i));
|
/* printf("%d ",count_patterns_for (i)); */
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("collisions %d\n",ncollisions);
|
|
||||||
ncollisions = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -493,6 +497,8 @@ for (i=1;i<17;i++) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("\npitchentropy %f\n",histogram_entropy(pitchclass_activity,12));
|
printf("\npitchentropy %f\n",histogram_entropy(pitchclass_activity,12));
|
||||||
|
printf("totalrhythmpatterns =%d\n",nrpatterns);
|
||||||
|
printf("collisions = %d\n",ncollisions);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user