00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "XMidiEvent.h"
00021 #include "XMidiEventList.h"
00022
00023 #ifdef PENTAGRAM_IN_EXULT
00024 #include "databuf.h"
00025 #else
00026 #include "ODataSource.h"
00027 #endif
00028
00029 #ifndef UNDER_CE
00030 using std::atof;
00031 using std::atoi;
00032 using std::memcmp;
00033 using std::memcpy;
00034 using std::memset;
00035 using std::size_t;
00036 #endif
00037 using std::string;
00038 using std::endl;
00039
00040
00041
00042
00043
00044
00045
00046 int XMidiEventList::write (ODataSource *dest)
00047 {
00048 int len = 0;
00049
00050 if (!events)
00051 {
00052 perr << "No midi data loaded." << endl;
00053 return 0;
00054 }
00055
00056
00057 if (!dest)
00058 {
00059
00060 len = convertListToMTrk (NULL);
00061 return 14 + len;
00062 }
00063
00064 dest->write1 ('M');
00065 dest->write1 ('T');
00066 dest->write1 ('h');
00067 dest->write1 ('d');
00068
00069 dest->write4high (6);
00070
00071 dest->write2high (0);
00072 dest->write2high (1);
00073 dest->write2high (60);
00074
00075 len = convertListToMTrk (dest);
00076
00077 return len + 14;
00078 }
00079
00080
00081
00082
00083
00084
00085 int XMidiEventList::putVLQ(ODataSource *dest, uint32 value)
00086 {
00087 int buffer;
00088 int i = 1;
00089 buffer = value & 0x7F;
00090 while (value >>= 7)
00091 {
00092 buffer <<= 8;
00093 buffer |= ((value & 0x7F) | 0x80);
00094 i++;
00095 }
00096 if (!dest) return i;
00097 for (int j = 0; j < i; j++)
00098 {
00099 dest->write1(buffer & 0xFF);
00100 buffer >>= 8;
00101 }
00102
00103 return i;
00104 }
00105
00106
00107
00108
00109 uint32 XMidiEventList::convertListToMTrk (ODataSource *dest)
00110 {
00111 int time = 0;
00112 int lasttime = 0;
00113 XMidiEvent *event;
00114 uint32 delta;
00115 unsigned char last_status = 0;
00116 uint32 i = 8;
00117 uint32 j;
00118 uint32 size_pos=0;
00119
00120 if (dest)
00121 {
00122 dest->write1('M');
00123 dest->write1('T');
00124 dest->write1('r');
00125 dest->write1('k');
00126
00127 size_pos = dest->getPos();
00128 dest->skip(4);
00129 }
00130
00131 for (event = events; event; event=event->next)
00132 {
00133
00134 if (event->status == 0xFF && event->data[0] == 0x2f) {
00135 lasttime = event->time;
00136 continue;
00137 }
00138
00139 delta = (event->time - time);
00140 time = event->time;
00141
00142 i += putVLQ (dest, delta);
00143
00144 if ((event->status != last_status) || (event->status >= 0xF0))
00145 {
00146 if (dest) dest->write1(event->status);
00147 i++;
00148 }
00149
00150 last_status = event->status;
00151
00152 switch (event->status >> 4)
00153 {
00154
00155
00156 case 0x8: case 0x9: case 0xA: case 0xB: case 0xE:
00157 if (dest)
00158 {
00159 dest->write1(event->data[0]);
00160 dest->write1(event->data[1]);
00161 }
00162 i += 2;
00163 break;
00164
00165
00166
00167
00168 case 0xC: case 0xD:
00169 if (dest) dest->write1(event->data[0]);
00170 i++;
00171 break;
00172
00173
00174
00175
00176 case 0xF:
00177 if (event->status == 0xFF)
00178 {
00179 if (dest) dest->write1(event->data[0]);
00180 i++;
00181 }
00182
00183 i += putVLQ (dest, event->ex.sysex_data.len);
00184
00185 if (event->ex.sysex_data.len)
00186 {
00187 for (j = 0; j < event->ex.sysex_data.len; j++)
00188 {
00189 if (dest) dest->write1(event->ex.sysex_data.buffer[j]);
00190 i++;
00191 }
00192 }
00193
00194 break;
00195
00196
00197
00198 default:
00199 perr << "Not supposed to see this" << endl;
00200 break;
00201 }
00202 }
00203
00204
00205 if (lasttime > time) i += putVLQ (dest, lasttime-time);
00206 else i += putVLQ (dest, 0);
00207 if (dest) {
00208 dest->write1(0xFF);
00209 dest->write1(0x2F);
00210 }
00211 i += 2+putVLQ (dest, 0);
00212
00213 if (dest)
00214 {
00215 int cur_pos = dest->getPos();
00216 dest->seek (size_pos);
00217 dest->write4high (i-8);
00218 dest->seek (cur_pos);
00219 }
00220 return i;
00221 }
00222
00223 void XMidiEventList::decerementCounter()
00224 {
00225 if (--counter < 0) {
00226 deleteEventList(events);
00227 XMidiEvent::Free(this);
00228 }
00229 }
00230
00231 void XMidiEventList::deleteEventList (XMidiEvent *mlist)
00232 {
00233 XMidiEvent *event;
00234 XMidiEvent *next;
00235
00236 next = mlist;
00237 event = mlist;
00238
00239 while ((event = next))
00240 {
00241 next = event->next;
00242
00243 if ((event->status>>4) == 0xF && event->ex.sysex_data.buffer) XMidiEvent::Free (event->ex.sysex_data.buffer);
00244 XMidiEvent::Free (event);
00245 }
00246 }