home *** CD-ROM | disk | FTP | other *** search
- // midiread v1.0 written by Günter Nagler 1995 (gnagler@ihm.tu-graz.ac.at)
- #include "midiread.hpp"
-
- unsigned long getlong(FILE* f)
- {
- unsigned char c[4];
- unsigned long n = 0;
-
- if (fread(c, 4, 1, f) != 1)
- return 0;
- n = c[0];
- n = (n << 8) + c[1];
- n = (n << 8) + c[2];
- n = (n << 8) + c[3];
- return n;
- }
-
- unsigned long gettri(FILE* f)
- {
- unsigned char c[3];
- unsigned long n = 0;
-
- if (fread(c, 3, 1, f) != 1)
- return 0;
- n = c[0];
- n = (n << 8) + c[1];
- n = (n << 8) + c[2];
- return n;
- }
-
- int getbyte(FILE*f)
- {
- return fgetc(f);
- }
-
- void putbyte(FILE* f, int n)
- {
- fputc(n, f);
- }
-
- unsigned short getword(FILE* f)
- {
- unsigned char c[2];
- unsigned short n = 0;
-
- if (fread(c, 2, 1, f) != 1)
- return 0;
- n = c[0];
- n = (n << 8) + c[1];
- return n;
- }
-
- void putword(FILE* f, unsigned short n)
- {
- unsigned char c[2];
-
- c[0] = ((n>>8) & 0xff);
- c[1] = n & 0xff;
- fwrite(c, 2, 1, f);
- }
-
- void putlong(FILE* f, unsigned long n)
- {
- unsigned char c[4];
-
- c[0] = ((n>>24) & 0xff);
- c[1] = ((n>>16) & 0xff);
- c[2] = ((n>>8) & 0xff);
- c[3] = n & 0xff;
- fwrite(c, 4, 1, f);
- }
-
- void puttri(FILE* f, unsigned long n)
- {
- unsigned char c[3];
-
- c[0] = ((n>>16) & 0xff);
- c[1] = ((n>>8) & 0xff);
- c[2] = n & 0xff;
- fwrite(c, 3, 1, f);
- }
-
- int get_midihead(FILE* f, MIDIHEAD* h)
- {
- long tag;
- long taglen;
- long tagend;
-
- fseek(f, 0L, SEEK_SET);
-
- tag = getlong(f);
- if (tag != MThd)
- return 0;
-
- taglen = getlong(f);
- tagend = ftell(f)+taglen;
-
- h->songs = getword(f);
- h->tracks = getword(f);
- h->unitsperbeat = getword(f);
- fseek(f, tagend, SEEK_SET);
-
- return 1;
- }
-
- void skip_tag(FILE* f)
- {
- getlong(f);
- fseek(f, getlong(f), SEEK_CUR);
- }
-
- void put_midihead(FILE* f, MIDIHEAD* h)
- {
- fseek(f, 0L, SEEK_SET);
-
- putlong(f, MThd);
- putlong(f, 6l);
-
- putword(f, h->songs);
- putword(f, h->tracks);
- putword(f, h->unitsperbeat);
- }
-
- unsigned long getdelta(FILE* f)
- {
- unsigned long n = 0;
- int i = 0, c;
-
- for (i = 0; i < 4; i++)
- {
- c = fgetc(f);
- if (c == -1)
- break;
- n = (n << 7) + (c & 0x7f);
- if ((c & 0x80) == 0)
- break;
- }
- return n;
- }
-
- void putdelta(FILE* f, unsigned long n)
- {
- unsigned char c[4], v;
- int i = 0;
-
- while (i < 4)
- {
- v = n & 0x7f;
- n >>= 7;
- c[i++] = v;
- if (n == 0)
- break;
- }
- while (i > 0)
- {
- int v;
-
- v = c[--i];
- if (i > 0)
- v |= 0x80;
- fputc(v, f);
- }
- }
-
- static long chunkpos;
-
- void open_chunk(FILE* f, char* s)
- {
- fwrite(s, 1, 4, f);
- putlong(f, 0L);
- chunkpos = ftell(f);
- }
-
- void close_chunk(FILE* f)
- {
- unsigned long p = ftell(f);
- unsigned long len = 0;
-
- len = p - chunkpos;
- fseek(f, chunkpos-4, SEEK_SET);
- putlong(f, len);
- fseek(f, p, SEEK_SET);
- }
-
- int scanevent(
- FILE* f,
- unsigned long* dtime,
- unsigned char* ev,
- unsigned char lastev,
- unsigned long* len)
- {
- int c;
-
- *dtime = getdelta(f);
- c = getbyte(f);
-
- if (c == EOF)
- return 0;
-
- if ((c & 0x80) == 0 && (lastev >= 0x80 && lastev <= 0xEF))
- {
- fseek(f, -1, SEEK_CUR); // event not given, use lastev
- c = lastev;
- }
- *ev = c;
- switch(c & 0xf0)
- {
- case 0xf0:
- {
- switch(c)
- {
- case 0xf0: // sysex event
- *len = getdelta(f);
- break;
- case 0xf2: // song position pointer event
- *len = 2;
- break;
- case 0xf3: // song select event
- *len = 1;
- break;
- case 0xf6: // tune request event
- case 0xf8: // timing clock event
- case 0xfa: // start event
- case 0xfb: // continue event
- case 0xfc: // stop event
- case 0xfe: // active sensing event
- *len = 0;
- break;
- case 0xff: // system reset event
- {
- long p = ftell(f);
-
- getbyte(f);
- *len = getdelta(f);
- *len += ftell(f)-p;
- fseek(f, p, SEEK_SET);
- }
- }
- }
- break;
- case 0x90: // notes
- case 0x80:
- *len = 2;
- break;
- case 0xC0:
- case 0xD0:
- *len = 1;
- break;
- case 0xA0:
- case 0xB0:
- case 0xE0:
- *len = 2;
- break;
- default:
- *len = 0;
- return 0;
- }
- return 1;
- }
-
- int seekchannel(FILE* f, unsigned long len)
- {
- unsigned char lastev = 0xff, ev;
- long oldpos = ftell(f);
- long endpos = oldpos + len;
- unsigned long delta, paramlen;
-
- while (ftell(f) < endpos && scanevent(f, &delta, &ev, lastev, ¶mlen) && !feof(f))
- {
- if (ev >= 0x80 && ev <= 0xEF)
- {
- fseek(f, oldpos, SEEK_SET);
- return ev & 15;
- }
- fseek(f, paramlen, SEEK_CUR);
- }
- fseek(f, oldpos, SEEK_SET);
- return -1;
- }
-
- static char* GMProg[128] =
- {
- "Piano", "BritePiano", "HammerPiano", "HonkeyTonk", "NewTines", "DigiPiano", "Harpsicord", "Clav",
- "Celesta", "Glocken", "MusicBox", "Vibes", "Marimba", "Xylophon", "Tubular", "Santur",
- "FullOrgan", "PercOrgan", "BX-3Organ", "ChurchPipe", "Positive", "Musette", "Harmonica", "Tango",
- "ClassicGtr", "A.Guitar", "JazzGuitar", "CleanGtr", "MuteGuitar", "OverDrive", "DistGuitar", "RockMonics",
- "JazzBass", "DeepBass", "PickBass", "FretLess", "SlapBass1", "SlapBass2", "SynthBass1", "SynthBass2",
- "Violin", "Viola", "Cello", "ContraBass", "TremoloStr", "Pizzicato", "Harp", "Timpani",
- "Marcato", "SlowString", "AnalogPad", "StringPad", "Choir", "DooVoice", "Voices", "OrchHit",
- "Trumpet", "Trombone", "Tuba", "MutedTrumpet", "FrenchHorn", "Brass", "SynBrass1", "SynBrass2",
- "SopranoSax", "AltoSax", "TenorSax", "BariSax", "SweetOboe", "EnglishHorn", "BasoonOboe", "Clarinet",
- "Piccolo", "Flute", "Recorder", "PanFlute", "Bottle", "Shakuhachi","Whistle", "Ocarina",
- "SquareWave", "SawWave", "SynCalinope", "SynChiff", "Charang", "AirChorus", "Rezzo4ths", "Bass&Lead",
- "Fantasia", "WarmPad", "PolyPad", "GhostPad", "BowedGlas", "MetalPad", "HaloPad", "Sweep",
- "IceRain", "SoundTrack", "Crystal", "Atmosphere", "Brightness", "Goblin", "EchoDrop", "StarTheme",
- "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba","Scotland","Fiddle", "Shanai",
- "MetalBell", "Agogo", "SteelDrums", "Woodblock", "Taiko", "Tom", "SynthTom", "RevCymbal",
- "FretNoise", "NoiseChiff", "Seashore", "Birds", "Telephone", "Helicopter", "Stadium!!", "GunShot"
- };
-
- const char* progname(int n, int channel)
- {
- static char defname[10] = "";
-
- if (channel == 9) // drum programs
- {
- switch(n)
- {
- case 0: return "Dr1";
- case 0x10: return "Dr2";
- case 0x19: return "Dr3";
- case 0x20: return "Dr4";
- case 0x28: return "Dr5";
- case 0x40: return "Dr6";
- case 0x18: return "Dr7";
- case 0x30: return "Dr8";
- }
- }
- else if (n >= 0 && n <= 127)
- return GMProg[n];
- def:
- sprintf(defname, "%d", n);
- return (const char*)defname;
- }
-