002
18.11.2005, 15:45 Uhr
FloSoft
Medialer Over-Flow (Administrator)
|
hatte da mal ne klasse geschrieben, weiß nicht ob die mit "normalen" midi files klarkommt, mit dem xmidi von glaub yamaha schon:
loadMID.cpp
C++: |
#include "main.h" #include "load/loadMID.h"
int loadMID(MID_Data *data, const char *file) { // ist file ein gültiger Pointer? if(!file) { printf("loadMID: ERROR: file is null\n"); return -1; }
// ist data ein gültiger Pointer? if(!data) { printf("loadMID: ERROR: data is null\n"); return -1; }
#ifndef USE_MIXER printf("loadMID: skipped\n"); return 0; #else
// DAT zum Lesen öffnen FILE *mid_data = fopen(file,"rb");
// Öffnen fehlgeschlagen if(!mid_data) { printf("loadMID: ERROR: %s\n", strerror(errno) ); return -1; }
unsigned long value, bobtype, type;
// Group-Identifier einlesen bobtype = fget32(mid_data);
// Überprüfen if(bobtype != 0x464F524D) // != "FORM" { printf("loadMID: ERROR: Group Identifier (FORM) not found: No valid XMIDI-File!!!\n" ); return -1; }
// Blocklänge lesen unsigned long form_length; form_length = fget32(mid_data);
type = fget32(mid_data);
if(type == 0x584D4944) // != "XMID" { printf("loadMID: WARNING: XMIDI does not have XDIR!!!\n" ); data->track_count = 1; } else if(type != 0x58444952) // != "XDIR" { printf("loadMID: ERROR: Type Identifier (XDIR/XMID) not found: No valid XMIDI-File!!!\n" ); return -1; } else { unsigned long x = 4; while(x < form_length) { value = fget32(mid_data);
switch(value) { case 0x494E464F: // "INFO" { // Blocklänge einlesen unsigned long length; length = fget32(mid_data);
// bei ungerader zahl "aufrunden" if (length%2) length++; x += length;
if(length != 2) { printf("loadMID: ERROR: Invalid chunk length for INFO block: %ld < 2!!!\n", length ); return -1; }
fread(&data->track_count, 2, 1, mid_data); length -= 2;
// Unvollständig gelesen?!? if (length != 0) { printf("loadMID: WARNING: INFO-Block abgeschnitten: %ld Bytes zu wenig/zuviel!\n", length ); } } break; case 0x43415420: // "CAT " { // Blocklänge einlesen unsigned long length; length = fget32(mid_data);
// bei ungerader zahl "aufrunden" if (length%2) length++;
x += length;
type = fget32(mid_data); if(type != 0x584D4944) { printf("loadMID: ERROR: Type Identifier (XMID) not found: No valid XMIDI-File!!!\n" ); return -1; } } break; } }
if(data->track_count == 0) { printf("loadMID: ERROR: XMIDI-File does not contain any tracks!!!\n" ); return -1; }
if(data->track_count > 256) { printf("loadMID: ERROR: XMIDI-File does contain too many tracks (%d > 256)!!!\n", data->track_count); return -1; }
unsigned short track_nr = 0; while(track_nr < data->track_count) { // Block-Identifier einlesen value = fget32(mid_data);
switch(value) { case 0x464F524D: // "FORM" { // Unbekannte Daten einlesen unsigned char unknown[4]; fread(unknown, 1, 4, mid_data); } break; case 0x584D4944: // "XMID" { } break; case 0x54494D42: // "TIMB" { // Blocklänge einlesen unsigned long length; length = fget32(mid_data);
// bei ungerader zahl "aufrunden" if (length%2) length++;
// Rest des Blocks einlesen (unbekannte Daten) unsigned char *unknown2 = new unsigned char[length+1]; size_t read = fread(unknown2, 1, length, mid_data); if(read <= length) length -= (unsigned long)read;
// Unvollständig gelesen?!? if (length != 0) { printf("loadMID: WARNING: TIMB-Block abgeschnitten: %ld Bytes zu wenig/zuviel!\n", length ); }
delete[] unknown2; } break; case 0x45564E54: // "EVNT" { // Blocklänge einlesen unsigned long length; length = fget32(mid_data);
// bei ungerader zahl "aufrunden" if (length%2) length++;
// Rest des Blocks einlesen (Track Daten) data->tracks[track_nr].data = new unsigned char[length+1]; size_t read = fread(data->tracks[track_nr].data, 1, length, mid_data); if(read <= length) length -= (unsigned long)read;
data->tracks[track_nr].data_length = (unsigned int)read;
// Unvollständig gelesen?!? if (length != 0) { printf("loadMID: WARNING: EVNT-Block abgeschnitten: %ld Bytes zu wenig/zuviel!\n", length ); }
track_nr++; } break; } } }
data->file = new CXMIDIFile(data); data->file->Convert();
fclose(mid_data);
#endif // !USE_MIXER
return 0; }
void freeMID(MID_Data *data) { #ifdef USE_MIXER for(unsigned int x = 0; x < 256; x++) { delete[] data->tracks[x].data; data->tracks[x].data = NULL;
delete[] data->tracks[x].converted; data->tracks[x].converted = NULL; }
delete data->file; data->file = NULL; #endif // USE_MIXER
data->track_count = 0;
memset(data, 0, sizeof(MID_Data)); }
|
loadMID.h
C++: |
class CXMIDIFile;
typedef struct MID_Data { unsigned short track_count; MID_Track tracks[256];
CXMIDIFile *file; } MID_Data;
typedef struct MID_Event { int time; unsigned char status;
unsigned char data[2];
unsigned int len; unsigned char *buffer; int duration; MID_Event *next_note; unsigned int note_time; MID_Event *next; } MID_Event;
typedef struct MID_Track { unsigned char *data; unsigned int data_length;
unsigned char *converted; unsigned int converted_length;
MID_Event *events; unsigned int event_count; } MID_Track;
|
XMIDIFile.cpp
C++: |
#include "main.h" #include "midi/XMIDIFile.h"
CXMIDIFile::CXMIDIFile(MID_Data *data) { MIDData = data; position = 0; current = NULL;
memset(bank127, 0, sizeof(bank127)); }
CXMIDIFile::~CXMIDIFile() { for(unsigned int track_nr = 0; track_nr < MIDData->track_count; track_nr++) { if(MIDData->tracks[track_nr].event_count > 0) { MID_Event *event, *next; event = MIDData->tracks[track_nr].events; next = MIDData->tracks[track_nr].events; while ((event = next)) { next = event->next; if ((event->status>>4) == 0xF && event->buffer) delete[] (event->buffer); delete event; } } } }
#define PATCH_VOL_PAN_BIAS 5
GammaTable<unsigned char> CXMIDIFile::VolumeCurve(128);
const char CXMIDIFile::mt32asgm[128] = { 0, // 0 Piano 1 1, // 1 Piano 2 2, // 2 Piano 3 (synth) 4, // 3 EPiano 1 4, // 4 EPiano 2 5, // 5 EPiano 3 5, // 6 EPiano 4 3, // 7 Honkytonk 16, // 8 Organ 1 17, // 9 Organ 2 18, // 10 Organ 3 16, // 11 Organ 4 19, // 12 Pipe Organ 1 19, // 13 Pipe Organ 2 19, // 14 Pipe Organ 3 21, // 15 Accordion 6, // 16 Harpsichord 1 6, // 17 Harpsichord 2 6, // 18 Harpsichord 3 7, // 19 Clavinet 1 7, // 20 Clavinet 2 7, // 21 Clavinet 3 8, // 22 Celesta 1 8, // 23 Celesta 2 62, // 24 Synthbrass 1 (62) 63, // 25 Synthbrass 2 (63) 62, // 26 Synthbrass 3 Bank 8 63, // 27 Synthbrass 4 Bank 8 38, // 28 Synthbass 1 39, // 29 Synthbass 2 38, // 30 Synthbass 3 Bank 8 39, // 31 Synthbass 4 Bank 8 88, // 32 Fantasy 90, // 33 Harmonic Pan - No equiv closest is polysynth(90) :( 52, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)??? 92, // 35 Glass 97, // 36 Soundtrack 99, // 37 Atmosphere 14, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is! 54, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111) 98, // 40 EchoBell, no real equiv, sounds like Crystal(98) 96, // 41 IceRain 68, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68) 95, // 43 EchoPans, no equiv, setting to SweepPad 81, // 44 DoctorSolo Bank 8 87, // 45 SchoolDaze, no real equiv 112, // 46 Bell Singer 80, // 47 SquareWave 48, // 48 Strings 1 48, // 49 Strings 2 - should be 49 44, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50 45, // 51 Pizzicato Strings 40, // 52 Violin 1 40, // 53 Violin 2 ? Viola 42, // 54 Cello 1 42, // 55 Cello 2 43, // 56 Contrabass 46, // 57 Harp 1 46, // 58 Harp 2 24, // 59 Guitar 1 (Nylon) 25, // 60 Guitar 2 (Steel) 26, // 61 Elec Guitar 1 27, // 62 Elec Guitar 2 104, // 63 Sitar 32, // 64 Acou Bass 1 32, // 65 Acou Bass 2 33, // 66 Elec Bass 1 34, // 67 Elec Bass 2 36, // 68 Slap Bass 1 37, // 69 Slap Bass 2 35, // 70 Fretless Bass 1 35, // 71 Fretless Bass 2 73, // 72 Flute 1 73, // 73 Flute 2 72, // 74 Piccolo 1 72, // 75 Piccolo 2 74, // 76 Recorder 75, // 77 Pan Pipes 64, // 78 Sax 1 65, // 79 Sax 2 66, // 80 Sax 3 67, // 81 Sax 4 71, // 82 Clarinet 1 71, // 83 Clarinet 2 68, // 84 Oboe 69, // 85 English Horn (Cor Anglais) 70, // 86 Bassoon 22, // 87 Harmonica 56, // 88 Trumpet 1 56, // 89 Trumpet 2 57, // 90 Trombone 1 57, // 91 Trombone 2 60, // 92 French Horn 1 60, // 93 French Horn 2 58, // 94 Tuba 61, // 95 Brass Section 1 61, // 96 Brass Section 2 11, // 97 Vibes 1 11, // 98 Vibes 2 99, // 99 Syn Mallet Bank 1 112, // 100 WindBell no real equiv Set to TinkleBell(112) 9, // 101 Glockenspiel 14, // 102 Tubular Bells 13, // 103 Xylophone 12, // 104 Marimba 107, // 105 Koto 111, // 106 Sho?? set to Shanai(111) 77, // 107 Shakauhachi 78, // 108 Whistle 1 78, // 109 Whistle 2 76, // 110 Bottle Blow 76, // 111 Breathpipe no real equiv set to bottle blow(76) 47, // 112 Timpani 117, // 113 Melodic Tom 116, // 114 Deap Snare no equiv, set to Taiko(116) 118, // 115 Electric Perc 1 118, // 116 Electric Perc 2 116, // 117 Taiko 115, // 118 Taiko Rim, no real equiv, set to Woodblock(115) 119, // 119 Cymbal, no real equiv, set to reverse cymbal(119) 115, // 120 Castanets, no real equiv, in GM set to Woodblock(115) 112, // 121 Triangle, no real equiv, set to TinkleBell(112) 55, // 122 Orchestral Hit 124, // 123 Telephone 123, // 124 BirdTweet 94, // 125 Big Notes Pad no equiv, set to halo pad (94) 98, // 126 Water Bell set to Crystal Pad(98) 121 // 127 Jungle Tune set to Breath Noise };
int CXMIDIFile::Convert(void) { for(unsigned int track_nr = 0; track_nr < MIDData->track_count; track_nr++) { ConvertTrackToList(&MIDData->tracks[track_nr]); ConvertListToMTrk(&MIDData->tracks[track_nr]); } return 0; }
int CXMIDIFile::ConvertTrackToList(MID_Track *track) { int time = 0; // 120th of a second unsigned int data; int end = 0; unsigned int status = 0; int play_size = 3; int retval = 0;
position = 0;
first_state fs; memset(&fs, 0, sizeof(first_state));
while (!end && position < track->data_length) { GetVLQ2(track, data); time += data; status = (unsigned int)track->data[position++];
switch (status >> 4) { case MIDI_STATUS_NOTE_ON: retval |= 1 << (status & 0xF); ConvertNote(track, time, status, play_size); break;
case MIDI_STATUS_NOTE_OFF: ConvertNote(track, time, status, 2); break;
// 2 byte data case MIDI_STATUS_AFTERTOUCH: case MIDI_STATUS_CONTROLLER: case MIDI_STATUS_PITCH_WHEEL: ConvertEvent(track, time, status, 2, fs); break;
// 1 byte data case MIDI_STATUS_PROG_CHANGE: case MIDI_STATUS_PRESSURE: ConvertEvent(track, time, status, 1, fs); break;
case MIDI_STATUS_SYSEX: if (status == 0xFF) { unsigned int pos = position; unsigned int data = track->data[position++];
if (data == 0x2F) end = 1; else if (data == 0x51) { GetVLQ(track, data); position += data; break; }
position = pos; } ConvertSystemMessage(track, time, status); break; }
} current = track->events;
position = 0; MID_Track test; test.events = track->events; test.data_length = 5; test.data = new unsigned char[5]; test.data[0] = 0x51; test.data[1] = 0x03; test.data[2] = 0x07; test.data[3] = 0xA1; test.data[4] = 0x20; ConvertSystemMessage(&test, 0, 0xFF);
delete[] test.data;
ApplyFirstState(track, fs, retval);
return retval; }
int CXMIDIFile::GetVLQ(MID_Track *track, unsigned int &quant) { int i; quant = 0; unsigned char data = 0;
for (i = 0; i < 4; i++) { data = track->data[position++]; quant <<= 7; quant |= data & 0x7F;
if (!(data & 0x80)) { i++; break; } } return i; }
int CXMIDIFile::GetVLQ2(MID_Track *track, unsigned int &quant) { int i; quant = 0; unsigned char data = 0;
for (i = 0; i < 4; i++) { data = track->data[position++]; if (data & 0x80) { position--; break; } quant += data; } return i; }
int CXMIDIFile::PutVLQ(MID_Track *track, unsigned int value, bool write, unsigned int pos /*= 0*/) { int buffer; int i = 1; buffer = value & 0x7F; while (value >>= 7) { buffer <<= 8; buffer |= ((value & 0x7F) | 0x80); i++; }
if (!write) return i;
for (int j = 0; j < i; j++) { track->converted[pos++] = buffer & 0xFF; buffer >>= 8; }
return i; }
int CXMIDIFile::ConvertNote(MID_Track *track, const int time, const unsigned char status, const int size) { unsigned int delta = 0; int data;
data = track->data[position++];
CreateNewEvent(track, time); current->status = status;
current->data[0] = data; current->data[1] = track->data[position++];
// Volume modify the note on's, only if converting if ((current->status >> 4) == MIDI_STATUS_NOTE_ON && current->data[1]) current->data[1] = VolumeCurve[current->data[1]];
if (size == 2) return 2;
// XMI Note On handling
int i = GetVLQ(track, delta); current->duration = delta;
// This is an optimization MID_Event *prev = current;
// Create a note off CreateNewEvent(track, time+delta);
current->status = status; current->data[0] = data; current->data[1] = 0;
// Optimization current = prev;
return i + 2; }
int CXMIDIFile::ConvertEvent(MID_Track *track, const int time, const unsigned char status, const int size, first_state &fs) { // Uint32 delta=0; int data;
data = track->data[position++];
// Bank changes are handled here if ((status >> 4) == 0xB && data == 0) { data = track->data[position++];
bank127[status&0xF] = false;
return 2; }
// Handling for patch change mt32 conversion, probably should go elsewhere if ((status >> 4) == 0xC && (status&0xF) != 9) { data = mt32asgm[data]; }
// Disable patch changes on Track 10 is doing a conversion else if ((status >> 4) == 0xC && (status&0xF) == 9) { return size; }
CreateNewEvent(track, time); current->status = status;
current->data[0] = data;
// Check for patch change, and update fs if req if ((status >> 4) == 0xC) { if (!fs.patch[status&0xF] || fs.patch[status&0xF]->time > time) fs.patch[status&0xF] = current; }
// Controllers else if ((status >> 4) == 0xB) { // Volume if (current->data[0] == 7) { if (!fs.vol[status&0xF] || fs.vol[status&0xF]->time > time) fs.vol[status&0xF] = current; } // Pan else if (current->data[0] == 10) { if (!fs.pan[status&0xF] || fs.pan[status&0xF]->time > time) fs.pan[status&0xF] = current; } }
if (size == 1) return 1;
current->data[1] = track->data[position++];
// Volume modify the volume controller, only if converting if ((current->status >> 4) == MIDI_STATUS_CONTROLLER && current->data[0] == 7) current->data[1] = VolumeCurve[current->data[1]];
return 2; }
int CXMIDIFile::ConvertSystemMessage(MID_Track *track, const int time, const unsigned char status) { int i = 0;
CreateNewEvent(track, time); current->status = status;
// Handling of Meta events if (status == 0xFF) { current->data[0] = track->data[position++]; i++; }
i += GetVLQ(track, current->len);
if (!current->len) { current->buffer = NULL; return i; }
current->buffer = new unsigned char[current->len]; memset(current->buffer, 0, current->len);
memcpy(current->buffer, &track->data[position], current->len); position += current->len;
return i + current->len; }
void CXMIDIFile::CreateNewEvent(MID_Track *track, int time) { if (!track->events) { track->events = current = new MID_Event; memset(track->events, 0, sizeof(MID_Event)); if (time > 0) current->time = time; track->event_count++; return; }
if (time < 0 || track->events->time > time) { MID_Event *event = new MID_Event; memset(event, 0, sizeof(MID_Event)); event->next = track->events; track->events = current = event; track->event_count++; return; }
if (!current || current->time > time) current = track->events;
while (current->next) { if (current->next->time > time) { MID_Event *event = new MID_Event; memset(event, 0, sizeof(MID_Event));
event->next = current->next; current->next = event; current = event; current->time = time; track->event_count++; return; }
current = current->next; }
current->next = new MID_Event; memset(current->next, 0, sizeof(MID_Event)); current = current->next; current->time = time;
track->event_count++; }
unsigned int CXMIDIFile::ConvertListToMTrk(MID_Track *track) { int time = 0; int lasttime = 0; MID_Event *event; unsigned int delta; unsigned char last_status = 0; unsigned int j;
// Größe des Tracks ermitteln
delete[] track->converted; track->converted_length = 8;
for (event = track->events; event; event = event->next) { if (event->status == 0xFF && event->data[0] == 0x2f) { lasttime = event->time; continue; }
delta = (event->time - time); time = event->time;
track->converted_length += PutVLQ(track, delta, false);
if ((event->status != last_status) || (event->status >= 0xF0)) track->converted_length++;
last_status = event->status;
switch (event->status >> 4) { // 2 bytes data // Note off, Note on, Aftertouch, Controller and Pitch Wheel case 0x8: case 0x9: case 0xA: case 0xB: case 0xE: track->converted_length += 2; break;
// 1 bytes data // Program Change and Channel Pressure case 0xC: case 0xD: track->converted_length++; break;
// Variable length // SysEx case 0xF: if (event->status == 0xFF) track->converted_length++;
track->converted_length += PutVLQ(track, event->len, false);
if (event->len) { for (j = 0; j < event->len; j++) track->converted_length++; } break; } }
// Write out end of stream marker if (lasttime > time) track->converted_length += PutVLQ(track, lasttime-time, false); else track->converted_length += PutVLQ(track, 0, false);
track->converted_length += 2;
track->converted_length += PutVLQ(track, 0, false);
// Speicher anlegen track->converted = new unsigned char[track->converted_length]; memset(track->converted, 0, track->converted_length);
// nun Stream in die das Array schreiben unsigned int i = 0; time = 0; lasttime = 0; delta = 0; last_status = 0;
// Header schreiben memcpy(&track->converted[i],"MTrk",4); i += 4;
unsigned int length = Endian_Int(track->converted_length); memcpy(&track->converted[i], (unsigned char *)&length, 4); i += 4;
for (event = track->events; event; event = event->next) { if (event->status == 0xFF && event->data[0] == 0x2f) { lasttime = event->time; continue; }
delta = (event->time - time); time = event->time;
i += PutVLQ(track, delta, true, i);
if ((event->status != last_status) || (event->status >= 0xF0)) track->converted[i++] = event->status;
last_status = event->status;
switch (event->status >> 4) { // 2 bytes data // Note off, Note on, Aftertouch, Controller and Pitch Wheel case 0x8: case 0x9: case 0xA: case 0xB: case 0xE: track->converted[i++] = event->data[0]; track->converted[i++] = event->data[1]; break;
// 1 bytes data // Program Change and Channel Pressure case 0xC: case 0xD: track->converted[i++] = event->data[0]; break;
// Variable length // SysEx case 0xF: if (event->status == 0xFF) track->converted[i++] = event->data[0];
i += PutVLQ(track, event->len, true, i);
if (event->len) { for (j = 0; j < event->len; j++) track->converted[i++] = event->buffer[j]; } break; } }
// Write out end of stream marker if (lasttime > time) i += PutVLQ(track, lasttime-time, true, i); else i += PutVLQ(track, 0, true, i);
track->converted[i++] = 0xFF; track->converted[i++] = 0x2F;
i += PutVLQ(track, 0, true, i);
if( i != track->converted_length ) { printf("ConvertListToMTrk: WARNING: I've written only %d Bytes instead of %d!",i, track->converted_length); }
return track->converted_length; }
void CXMIDIFile::ApplyFirstState(MID_Track *track, first_state &fs, int chan_mask) { for (unsigned char channel = 0; channel < 16; channel++) { MID_Event *patch = fs.patch[channel]; MID_Event *vol = fs.vol[channel]; MID_Event *pan = fs.pan[channel]; MID_Event *bank = fs.bank[channel]; MID_Event *temp;
if (!patch || !(chan_mask & 1 << channel)) continue;
/*#ifdef _DEBUG printf("Channel: %d\n", channel+1); printf("Patch: %d @ %d\n", patch->data[0], patch->time);
if(bank) printf(" Bank: %d @ %d\n", patch->data[0], patch->time); if(vol) printf(" Vol: %d @ %d\n", patch->data[0], patch->time); if(pan) printf(" Pan: %d @ %d\n", patch->data[0], patch->time); #endif*/
// Copy Patch Change Event temp = patch; patch = new MID_Event; memset(patch, 0, sizeof(MID_Event)); patch->time = temp->time; patch->status = (unsigned char)(channel|(MIDI_STATUS_PROG_CHANGE << 4)); patch->data[0] = temp->data[0];
// Copy Volume if (vol && (vol->time > patch->time+PATCH_VOL_PAN_BIAS || vol->time < patch->time-PATCH_VOL_PAN_BIAS)) vol = NULL;
temp = vol; vol = new MID_Event; memset(vol, 0, sizeof(MID_Event)); vol->status = (unsigned char)(channel|(MIDI_STATUS_CONTROLLER << 4)); vol->data[0] = 7;
if (!temp) vol->data[1] = VolumeCurve[90]; else vol->data[1] = temp->data[1];
// Copy Bank if (bank && (bank->time > patch->time+PATCH_VOL_PAN_BIAS || bank->time < patch->time-PATCH_VOL_PAN_BIAS)) bank = NULL;
temp = bank;
bank = new MID_Event; memset(bank, 0, sizeof(MID_Event)); bank->status = (unsigned char)(channel|(MIDI_STATUS_CONTROLLER << 4));
if (!temp) bank->data[1] = 0; else bank->data[1] = temp->data[1];
// Copy Pan if (pan && (pan->time > patch->time+PATCH_VOL_PAN_BIAS || pan->time < patch->time-PATCH_VOL_PAN_BIAS)) pan = NULL;
temp = pan; pan = new MID_Event; memset(pan, 0, sizeof(MID_Event)); pan->status = (unsigned char)(channel|(MIDI_STATUS_CONTROLLER << 4)); pan->data[0] = 10;
if (!temp) pan->data[1] = 64; else pan->data[1] = temp->data[1];
vol->time = 0; pan->time = 0; patch->time = 0; bank->time = 0;
bank->next = vol; vol->next = pan; pan->next = patch;
patch->next = track->events;
track->events = bank; } }
|
XMIDIFile.h
C++: |
#ifndef XMIDIFILE_H_ #define XMIDIFILE_H_
#include "helper/endian.h" #include "midi/GammaTable.h"
#include "structs/structMID_Data.h" #include "structs/structMID_Track.h"
struct first_state { // Status, Data[0] MID_Event *patch[16]; // 0xC MID_Event *bank[16]; // 0xB, 0 MID_Event *pan[16]; // 0xB, 7 MID_Event *vol[16]; // 0xB, 10 };
class CXMIDIFile { public: CXMIDIFile(MID_Data *data); ~CXMIDIFile(void);
int Convert();
private: int ConvertTrackToList(MID_Track *track); unsigned int ConvertListToMTrk(MID_Track *track);
void ApplyFirstState(MID_Track *track, first_state &fs, int chan_mask);
int ConvertNote(MID_Track *track, const int time, const unsigned char status, const int size); int ConvertEvent(MID_Track *track, const int time, const unsigned char status, const int size, first_state &fs); int ConvertSystemMessage(MID_Track *track, const int time, const unsigned char status);
int GetVLQ(MID_Track *track, unsigned int &quant); int GetVLQ2(MID_Track *track, unsigned int &quant); int PutVLQ(MID_Track *track, unsigned int value, bool write, unsigned int pos = 0);
void CreateNewEvent(MID_Track *track, int time);
private: MID_Data *MIDData; MID_Event *current; unsigned int position;
enum { MIDI_STATUS_NOTE_OFF = 0x8, MIDI_STATUS_NOTE_ON = 0x9, MIDI_STATUS_AFTERTOUCH = 0xA, MIDI_STATUS_CONTROLLER = 0xB, MIDI_STATUS_PROG_CHANGE = 0xC, MIDI_STATUS_PRESSURE = 0xD, MIDI_STATUS_PITCH_WHEEL = 0xE, MIDI_STATUS_SYSEX = 0xF };
bool bank127[16];
const static char mt32asgm[128]; static GammaTable<unsigned char> VolumeCurve; };
#endif // XMIDIFILE_H_
|
GammaTable.h
C++: |
#ifndef GAMMATABLE_H_ #define GAMMATABLE_H_
#include <math.h>
template <class T> class GammaTable { private: unsigned int size; float sizef; T *table; float gamma;
// ctor GammaTable(){ }
public: inline const float & get_gamma () { return gamma; }
inline void set_gamma (float g) { if (g < 0.001f) g = 0.001f; if (g == gamma) return; gamma = g;
for (unsigned int i = 0; i < size; i++) table[i] = (T) (pow (i / sizef, 1 / gamma) * sizef); }
GammaTable (unsigned int s, float g = 1) : sizef(-1), gamma(-1) { sizef += size = s>2?s:2; table = new T [size]; set_gamma(g); }
~GammaTable () { delete [] table; }
inline const T & operator [] (const T &i) const { return table[i]; } };
#endif // GAMMATABLE_H_
|
Endian.cpp
C++: |
unsigned short Endian_Short(unsigned short x) { // bytes swappen return (((x)&0x00ff)<<8) | (((x)&0xff00)>>8); }
unsigned int Endian_Int(unsigned int x) { // bytes swappen return Endian_Short(((x)&0xffff0000)>>16) | Endian_Short((x)&0x0000ffff)<<16; }
|
-- class God : public ChuckNorris { }; |