CLAM-Development
1.1
|
00001 #include "MIDITrack.hxx" 00002 #include "MIDISong.hxx" 00003 #include "MIDIReader.hxx" 00004 #include "MIDITempo.hxx" 00005 #include "MIDIFileReader.hxx" 00006 00007 namespace CLAM 00008 { 00009 MIDIFileReader::MIDIFileReader() 00010 : mOutput("MIDISong Output",this) 00011 { 00012 MIDIFileIOConfig cfg; 00013 Configure(cfg); 00014 } 00015 00016 MIDIFileReader::MIDIFileReader(const MIDIFileIOConfig& cfg) 00017 : mOutput("MIDISong Output",this) 00018 { 00019 Configure(cfg); 00020 } 00021 00022 MIDIFileReader::~MIDIFileReader() 00023 { 00024 } 00025 00026 bool MIDIFileReader::Do() 00027 { 00028 bool result = Do(mOutput.GetData()); 00029 mOutput.Produce(); 00030 return result; 00031 } 00032 00033 bool MIDIFileReader::Do(MIDISong& out) 00034 { 00035 MIDI::Reader r(mConfig.GetFileName().c_str()); 00036 MIDI::Song s; 00037 r.Read(s); 00038 MIDI::Tempo t(&s); 00039 static int nbytesPerChnMsg[7] = { 3,3,3,3,2,3,3 }; 00040 bool onset=true; 00041 int nTracks = s.Tracks(); 00042 for(int i=0; i < nTracks; i++) 00043 { 00044 MIDI::Track* track = s.GetTrack(i); 00045 MIDI::Track::EventIterator it = track->Begin(); 00046 MIDITrack midiTrack; 00047 for(;it != track->End(); it++) 00048 { 00049 const MIDI::Event &ev = **it; 00050 int type = ((ev[0]&0xF0)>>4)-8; 00051 if(type==7) continue; 00052 if(((ev[0]&0xF0)==0x90) || ((ev[0]&0xF0)==0x80)) 00053 { 00054 onset = ((ev[0]&0xF0)==0x90) ? (ev[2] > 0) : false; // velocity > 0 -> onset 00055 if(onset) 00056 { 00057 midiTrack.GetChannels().AddElem((int)(ev[0]&0x0F)); 00058 MIDINote note; 00059 note.GetTime().SetBegin(TData(t.TicksToTime(ev.GetTicks())/1000.0)); 00060 note.GetTime().SetEnd(TData(-1.0)); 00061 note.SetKey((int)ev[1]); 00062 note.SetVelocity((int)ev[2]); 00063 midiTrack.GetTrackMelody().GetNoteArray().AddElem(note); 00064 midiTrack.GetTrackMelody().GetNumberOfNotes()++; 00065 } 00066 else 00067 { 00068 for(int n=0; n < midiTrack.GetTrackMelody().GetNumberOfNotes(); n++) 00069 { 00070 if((midiTrack.GetTrackMelody().GetNoteArray()[n].GetKey() == (int)(ev[1])) && 00071 (midiTrack.GetTrackMelody().GetNoteArray()[n].GetTime().GetEnd()==TData(-1.0))) 00072 { 00073 midiTrack.GetTrackMelody().GetNoteArray()[n].GetTime().SetEnd(TData(t.TicksToTime(ev.GetTicks())/1000.0)); 00074 break; 00075 } 00076 } 00077 } 00078 } 00079 else 00080 { 00081 MIDIEvent e; 00082 e.SetName(GetEventName((ev[0]&0xF0))); 00083 e.SetTime((TTime)(t.TicksToTime(ev.GetTicks())/1000.0)); 00084 int len = nbytesPerChnMsg[type]; 00085 for(int k=0; k < len; k++) 00086 { 00087 e.GetMessage().AddElem(ev[k]); 00088 } 00089 midiTrack.GetEventInfo().AddElem(e); 00090 } 00091 } 00092 if(midiTrack.GetTrackMelody().GetNumberOfNotes() > 0) 00093 { 00094 out.GetTracks().AddElem(midiTrack); 00095 out.GetNumberOfTracks()++; 00096 } 00097 } 00098 return true; 00099 } 00100 00101 bool MIDIFileReader::ConcreteConfigure(const ProcessingConfig& c) 00102 { 00103 CopyAsConcreteConfig(mConfig, c); 00104 return true; 00105 } 00106 00107 std::string MIDIFileReader::GetEventName(TMIDIByte b) 00108 { 00109 switch(b) 00110 { 00111 case 0xA0: 00112 return "PolyAftertouch"; 00113 break; 00114 case 0xB0: 00115 return "ControlChange"; 00116 break; 00117 case 0xC0: 00118 return "ProgramChange"; 00119 break; 00120 case 0xD0: 00121 return "ChnAftertouch"; 00122 case 0xE0: 00123 return "PitchBend"; 00124 break; 00125 default: 00126 return "Unknow"; 00127 } 00128 } 00129 00130 } 00131 00132 // END 00133