read_a_midifile.c
上传用户:qqqqgs84aa
上传日期:2008-08-12
资源大小:47k
文件大小:10k
- /*
read_a_midifile.c version 0.10, march 18, 2004.
Example program that reads a midi file.
RDMID, a portable, thread-safe MIDI file parser.
Latest version available at: http://www.hku.nl/~pieter/EDU/c/rdmid/
Copyright (c) 2004 Pieter Suurmond
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Any person wishing to distribute modifications to the Software is
requested to send the modifications to the original developer so that
they can be incorporated into the canonical version.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The following program counts all C's, in all octaves, but only in the
first 3 tracks of the file, meanwhile reporting note-on events and
'start of track' events. After having read the first 3 tracks, it
stops, ignoring any subsequent tracks.
We accomplish this by installing two event handlers: One to print
and count note-on's, and another one to terminate the parser
(by returning non-zero) after having read enough tracks.
*/
#include <stdlib.h>
#include <stdio.h> /* Header rdmid.h needs FILE* and we also printf here. */
#include "rdmid.h" /* API documentation, prototypes and return codes. */
#include "rdmid.c"
typedef struct /* We use this structure to pass information between */
{ /* main() and our event handlers (via void* userdata). */
FILE* dest; /* Written by main(), read by event handlers. */
long count; /* Reset and read by main(), incremented by handler. */
} MY_DATA;
- struct Note
- {
- // char * MusicFileName;
- long Ontime;
- long Offtime;
- int note;
- int channel;
- int velocity;
- }pNote[5000],pMainNote[5000];
- int i;
-
int my_trackstart(void* userdata, int track) /* Event handler that will be */
{ /* invoked by the parser as */
MY_DATA* data = (MY_DATA*)userdata; /* soon as it encounters the */
/* start of a new track. */
fprintf(data->dest, "Track #%d start.n", track); /* First track# = 0. */
if (track > 15)
{
fprintf(data->dest, "Had 15 tracks now, let's stop.n");
return 1; /* Returning non-zero terminates the parser. */
}
return 0; /* Returning zero lets the parser continue. */
}
int my_note_on(void* userdata, long time, int channel, int note, int velocity)
{
MY_DATA* data = (MY_DATA*)userdata; /* Event handler that will be called */
/* after a note-on messages is read. */
if (velocity && time <5000) /* Don't print alternative note-off events. */
{
fprintf(data->dest, "%8ld: NOTE ON: ch=%d, note=%d, vel=%d",
time, channel, note, velocity);
- pNote[i].Ontime=time;
- pNote[i].channel=channel;
- pNote[i].note=note;
- pNote[i].velocity=velocity;
- i++;
- // fprintf(data->dest,"%8ld: NOTE ON: note=%d",pNote[i].Ontime,pNote[i].note);
if (!(note % 12))
{
data->count++; /* Count all C's, in all octaves. */
fprintf(data->dest, "<- c"); /* And mark them. */
}
fprintf(data->dest, ".n");
}
return 0; /* Don't stop parser, always return zero. */
}
/*
See the top of sourcefile rdmid.c for more event handler examples.
You may add more event handlers to this file.
*/
int main(void)
{
- int j,m,n,k;
int e;
FILE* fp;
- FILE* fpC;
char* filename="甘心.mid";
MY_DATA my_data;
/* Communicate without global variables. */
//my_data.dest = stdout; /* Where event handlers should fprintf() to. */
- my_data.dest=fopen("Note.txt","w");
- fpC=fopen("contour.txt","w");
my_data.count = 0L; /* Reset counter. Handler may increment. */
-
- for(i=0;i<5000;i++)
- {
- pNote[i].Ontime=0;
- pNote[i].Offtime=0;
- pNote[i].channel=0;
- pNote[i].note=0;
- pNote[i].velocity=0;
- pMainNote[i].Ontime=0;
- pMainNote[i].Offtime=0;
- pMainNote[i].channel=0;
- pMainNote[i].note=0;
- pMainNote[i].velocity=0;
- }
- i=0;
- j=0;
- m=0;
- n=0;
-
fp = fopen(filename, "rb");
if (fp) /* 24 arguments, it may seem a lot. */
{
e = rdmid((void*)&my_data, /* Userdata. */
fp, /* An open stream to read from. */
0, /* Merge broken sysex messages. */
/* Here follow 21 function pointers to your handlers. */
/* 3 evt handlers for header and tracks: */
NULL, /* eh_header() */
/* ----> */ my_trackstart, /* eh_trackstart() */
/* Only */ NULL, /* eh_trackend() */
/* these */ /* 7 channel events: */
/* two. */ NULL, /* eh_note_off() */
/* ----> */ my_note_on, /* eh_note_on() */
NULL, /* eh_poly_press() */
NULL, /* eh_controller() */
NULL, /* eh_program() */
NULL, /* eh_chan_press() */
NULL, /* eh_pitchbend() */
/* 1 sysex event: */
NULL, /* eh_sysex() */
/* 10 meta events: */
NULL, /* eh_seqnum() */
NULL, /* eh_text() */
NULL, /* eh_eot() */
NULL, /* eh_tempo() */
NULL, /* eh_smpte() */
NULL, /* eh_timesig() */
NULL, /* eh_keysig() */
NULL, /* eh_seq_spec() */
NULL, /* eh_metamisc() */
NULL ); /* eh_arbitrary() */
if (e == RDMID_OK)
{
fprintf(my_data.dest,"Ok, parsed standard MIDI file '%s'.n", filename);
- }
else if (e == RDMID_USER_TERM)
{
fprintf(my_data.dest,"User's event handler stopped parsing '%s'.n", filename);
e = 0; /* Not an error. */
}
else /* Some error. */
{
fprintf(my_data.dest,"Sorry, an error occured: rdmid() = %d.n", e);
e = 1;
}
fprintf(my_data.dest,"Counted %ld C's.n", my_data.count); /* Read sum from struct. */
if (fclose(fp)) /* Apart from the file we opened ourselves, there is */
e = 1; /* nothing to close or to free after calling rdmid(). */
}
else
{
fprintf(my_data.dest,"Sorry, could not open file '%s'.n", filename);
e = 1;
}
- fprintf(my_data.dest,"the num of all notes=%dn",i);
-
-
- /* pMainNote[0].Ontime=pNote[0].Ontime;
- pMainNote[0].channel=pNote[0].channel;
- pMainNote[0].note=pNote[0].note;
- pMainNote[0].velocity=pNote[0].velocity;*/
- n=0;
- for(m=0;m<i+1;m++)
- {
- j=0;
- while((j<n)&&(pNote[m].Ontime>pMainNote[j].Ontime))
- {
- j++;
- }
- if(j==n)
- {
- n++;
- pMainNote[n].Ontime=pNote[m].Ontime;
- pMainNote[n].channel=pNote[m].channel;
- pMainNote[n].note=pNote[m].note;
- pMainNote[n].velocity=pNote[m].velocity;
-
- }
- else if(pNote[m].Ontime==pMainNote[j].Ontime)
- {
- if(pNote[m].note>pMainNote[j].note)
- {
- pMainNote[j].note=pNote[m].note;
- pMainNote[j].channel=pNote[m].channel;
- pMainNote[j].velocity=pNote[m].velocity;
- }
-
- }
- else
- {
- n++;
- for(k=n;k>j;k--)
- {
- pMainNote[k].Ontime=pMainNote[k-1].Ontime;
- pMainNote[k].channel=pMainNote[k-1].channel;
- pMainNote[k].note=pMainNote[k-1].note;
- pMainNote[k].velocity=pMainNote[k-1].velocity;
-
- }
- pMainNote[j].Ontime=pNote[m].Ontime;
- pMainNote[j].channel=pNote[m].channel;
- pMainNote[j].note=pNote[m].note;
- pMainNote[j].velocity=pNote[m].velocity;
- }
- }
- fprintf(my_data.dest,"the num of all main notes=%dn",n);
- fprintf(fpC,"%sn",filename);
- fprintf(fpC,"*");
- for(j=1;j<n+1;j++)
- {
- fprintf(my_data.dest, "%8ld: NOTE ON: ch=%d, note=%d, vel=%dn",pMainNote[j].Ontime, pMainNote[j].channel, pMainNote[j].note, pMainNote[j].velocity);
- if(pMainNote[j].note<pMainNote[j-1].note)
- {
- fprintf(fpC,"D");
- }
- else if (pMainNote[j].note>pMainNote[j-1].note)
- {
- fprintf(fpC,"U");
- }
- else
- {
- fprintf(fpC,"R");
- }
-
- }
- fprintf(fpC,"n");
- fprintf(fpC,"the length of the strings is %dn",n);
- fclose(my_data.dest);
- fclose(fpC);
return e; /* Only return 0 or 1 to the OS. */
}