mus2midi.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include <assert.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include "idlib/sys/sys_defines.h"
  26. // mus header
  27. // reads a variable length integer
  28. unsigned long ReadVarLen( char* buffer ) {
  29. unsigned long value;
  30. byte c;
  31. if ((value = *buffer++) & 0x80) {
  32. value &= 0x7f;
  33. do {
  34. value = (value << 7) + ((c = *buffer++) & 0x7f);
  35. } while (c & 0x80);
  36. }
  37. return value;
  38. }
  39. // Writes a variable length integer to a buffer, and returns bytes written
  40. int WriteVarLen( long value, byte* out )
  41. {
  42. long buffer, count = 0;
  43. buffer = value & 0x7f;
  44. while ((value >>= 7) > 0) {
  45. buffer <<= 8;
  46. buffer += 0x80;
  47. buffer += (value & 0x7f);
  48. }
  49. while (1) {
  50. ++count;
  51. *out = (byte)buffer;
  52. ++out;
  53. if (buffer & 0x80)
  54. buffer >>= 8;
  55. else
  56. break;
  57. }
  58. return count;
  59. }
  60. // writes a byte, and returns the buffer
  61. unsigned char* WriteByte(void* buf, byte b)
  62. {
  63. unsigned char* buffer = (unsigned char*)buf;
  64. *buffer++ = b;
  65. return buffer;
  66. }
  67. unsigned char* WriteShort(void* b, unsigned short s)
  68. {
  69. unsigned char* buffer = (unsigned char*)b;
  70. *buffer++ = (s >> 8);
  71. *buffer++ = (s & 0x00FF);
  72. return buffer;
  73. }
  74. unsigned char* WriteInt(void* b, unsigned int i)
  75. {
  76. unsigned char* buffer = (unsigned char*)b;
  77. *buffer++ = (i & 0xff000000) >> 24;
  78. *buffer++ = (i & 0x00ff0000) >> 16;
  79. *buffer++ = (i & 0x0000ff00) >> 8;
  80. *buffer++ = (i & 0x000000ff);
  81. return buffer;
  82. }
  83. // Format - 0(1 track only), 1(1 or more tracks, each play same time), 2(1 or more, each play seperatly)
  84. void Midi_CreateHeader(MidiHeaderChunk_t* header, short format, short track_count, short division)
  85. {
  86. WriteInt(header->name, 'MThd');
  87. WriteInt(&header->length, 6);
  88. WriteShort(&header->format, format);
  89. WriteShort(&header->ntracks, track_count);
  90. WriteShort(&header->division, division);
  91. }
  92. unsigned char* Midi_WriteTempo(unsigned char* buffer, int tempo)
  93. {
  94. buffer = WriteByte(buffer, 0x00); // delta time
  95. buffer = WriteByte(buffer, 0xff); // sys command
  96. buffer = WriteShort(buffer, 0x5103); // command - set tempo
  97. buffer = WriteByte(buffer, tempo & 0x000000ff);
  98. buffer = WriteByte(buffer, (tempo & 0x0000ff00) >> 8);
  99. buffer = WriteByte(buffer, (tempo & 0x00ff0000) >> 16);
  100. return buffer;
  101. }
  102. int Midi_UpdateBytesWritten(int* bytes_written, int to_add, int max)
  103. {
  104. *bytes_written += to_add;
  105. if (max && *bytes_written > max)
  106. {
  107. assert(0);
  108. return 0;
  109. }
  110. return 1;
  111. }
  112. unsigned char MidiMap[] =
  113. {
  114. 0, // prog change
  115. 0, // bank sel
  116. 1, //2 // mod pot
  117. 0x07, //3 // volume
  118. 0x0A, //4 // pan pot
  119. 0x0B, //5 // expression pot
  120. 0x5B, //6 // reverb depth
  121. 0x5D, //7 // chorus depth
  122. 0x40, //8 // sustain pedal
  123. 0x43, //9 // soft pedal
  124. 0x78, //10 // all sounds off
  125. 0x7B, //11 // all notes off
  126. 0x7E, //12 // mono(use numchannels + 1)
  127. 0x7F, //13 // poly
  128. 0x79, //14 // reset all controllers
  129. };
  130. // The MUS data is stored in little-endian.
  131. namespace {
  132. unsigned short LittleToNative( const unsigned short value ) {
  133. return value;
  134. }
  135. }
  136. int Mus2Midi(unsigned char* bytes, unsigned char* out, int* len)
  137. {
  138. // mus header and instruments
  139. MUSheader_t header;
  140. // current position in read buffer
  141. unsigned char* cur = bytes,* end;
  142. // Midi header(format 0)
  143. MidiHeaderChunk_t midiHeader;
  144. // Midi track header, only 1 needed(format 0)
  145. MidiTrackChunk_t midiTrackHeader;
  146. // Stores the position of the midi track header(to change the size)
  147. byte* midiTrackHeaderOut;
  148. // Delta time for midi event
  149. int delta_time = 0;
  150. int temp;
  151. int channel_volume[MIDI_MAXCHANNELS] = {0};
  152. int bytes_written = 0;
  153. int channelMap[MIDI_MAXCHANNELS], currentChannel = 0;
  154. byte last_status = 0;
  155. // read the mus header
  156. memcpy(&header, cur, sizeof(header));
  157. cur += sizeof(header);
  158. header.scoreLen = LittleToNative( header.scoreLen );
  159. header.scoreStart = LittleToNative( header.scoreStart );
  160. header.channels = LittleToNative( header.channels );
  161. header.sec_channels = LittleToNative( header.sec_channels );
  162. header.instrCnt = LittleToNative( header.instrCnt );
  163. header.dummy = LittleToNative( header.dummy );
  164. // only 15 supported
  165. if (header.channels > MIDI_MAXCHANNELS - 1)
  166. return 0;
  167. // Map channel 15 to 9(percussions)
  168. for (temp = 0; temp < MIDI_MAXCHANNELS; ++temp) {
  169. channelMap[temp] = -1;
  170. channel_volume[temp] = 0x40;
  171. }
  172. channelMap[15] = 9;
  173. // Get current position, and end of position
  174. cur = bytes + header.scoreStart;
  175. end = cur + header.scoreLen;
  176. // Write out midi header
  177. Midi_CreateHeader(&midiHeader, 0, 1, 0x0059);
  178. Midi_UpdateBytesWritten(&bytes_written, MIDIHEADERSIZE, *len);
  179. memcpy(out, &midiHeader, MIDIHEADERSIZE); // cannot use sizeof(packs it to 16 bytes)
  180. out += MIDIHEADERSIZE;
  181. // Store this position, for later filling in the midiTrackHeader
  182. Midi_UpdateBytesWritten(&bytes_written, sizeof(midiTrackHeader), *len);
  183. midiTrackHeaderOut = out;
  184. out += sizeof(midiTrackHeader);
  185. // microseconds per quarter note(yikes)
  186. Midi_UpdateBytesWritten(&bytes_written, 7, *len);
  187. out = Midi_WriteTempo(out, 0x001aa309);
  188. // Percussions channel starts out at full volume
  189. Midi_UpdateBytesWritten(&bytes_written, 4, *len);
  190. out = WriteByte(out, 0x00);
  191. out = WriteByte(out, 0xB9);
  192. out = WriteByte(out, 0x07);
  193. out = WriteByte(out, 127);
  194. // Main Loop
  195. while (cur < end) {
  196. byte channel;
  197. byte event;
  198. byte temp_buffer[32]; // temp buffer for current iterator
  199. byte *out_local = temp_buffer;
  200. byte status, bit1, bit2, bitc = 2;
  201. // Read in current bit
  202. event = *cur++;
  203. channel = (event & 15); // current channel
  204. // Write variable length delta time
  205. out_local += WriteVarLen(delta_time, out_local);
  206. if (channelMap[channel] < 0) {
  207. // Set all channels to 127 volume
  208. out_local = WriteByte(out_local, 0xB0 + currentChannel);
  209. out_local = WriteByte(out_local, 0x07);
  210. out_local = WriteByte(out_local, 127);
  211. out_local = WriteByte(out_local, 0x00);
  212. channelMap[channel] = currentChannel++;
  213. if (currentChannel == 9)
  214. ++currentChannel;
  215. }
  216. status = channelMap[channel];
  217. // Handle ::g->events
  218. switch ((event & 122) >> 4)
  219. {
  220. default:
  221. assert(0);
  222. break;
  223. case MUSEVENT_KEYOFF:
  224. status |= 0x80;
  225. bit1 = *cur++;
  226. bit2 = 0x40;
  227. break;
  228. case MUSEVENT_KEYON:
  229. status |= 0x90;
  230. bit1 = *cur & 127;
  231. if (*cur++ & 128) // volume bit?
  232. channel_volume[channelMap[channel]] = *cur++;
  233. bit2 = channel_volume[channelMap[channel]];
  234. break;
  235. case MUSEVENT_PITCHWHEEL:
  236. status |= 0xE0;
  237. bit1 = (*cur & 1) >> 6;
  238. bit2 = (*cur++ >> 1) & 127;
  239. break;
  240. case MUSEVENT_CHANNELMODE:
  241. status |= 0xB0;
  242. assert(*cur < sizeof(MidiMap) / sizeof(MidiMap[0]));
  243. bit1 = MidiMap[*cur++];
  244. bit2 = (*cur++ == 12) ? header.channels + 1 : 0x00;
  245. break;
  246. case MUSEVENT_CONTROLLERCHANGE:
  247. if (*cur == 0) {
  248. cur++;
  249. status |= 0xC0;
  250. bit1 = *cur++;
  251. bitc = 1;
  252. } else {
  253. status |= 0xB0;
  254. assert(*cur < sizeof(MidiMap) / sizeof(MidiMap[0]));
  255. bit1 = MidiMap[*cur++];
  256. bit2 = *cur++;
  257. }
  258. break;
  259. case 5: // Unknown
  260. assert(0);
  261. break;
  262. case MUSEVENT_END: // End
  263. status = 0xff;
  264. bit1 = 0x2f;
  265. bit2 = 0x00;
  266. assert(cur == end);
  267. break;
  268. case 7: // Unknown
  269. assert(0);
  270. break;
  271. }
  272. // Write it out
  273. out_local = WriteByte(out_local, status);
  274. out_local = WriteByte(out_local, bit1);
  275. if (bitc == 2)
  276. out_local = WriteByte(out_local, bit2);
  277. // Write out temp stuff
  278. if (out_local != temp_buffer)
  279. {
  280. Midi_UpdateBytesWritten(&bytes_written, out_local - temp_buffer, *len);
  281. memcpy(out, temp_buffer, out_local - temp_buffer);
  282. out += out_local - temp_buffer;
  283. }
  284. if (event & 128) {
  285. delta_time = 0;
  286. do {
  287. delta_time = delta_time * 128 + (*cur & 127);
  288. } while ((*cur++ & 128));
  289. } else {
  290. delta_time = 0;
  291. }
  292. }
  293. // Write out track header
  294. WriteInt(midiTrackHeader.name, 'MTrk');
  295. WriteInt(&midiTrackHeader.length, out - midiTrackHeaderOut - sizeof(midiTrackHeader));
  296. memcpy(midiTrackHeaderOut, &midiTrackHeader, sizeof(midiTrackHeader));
  297. // Store length written
  298. *len = bytes_written;
  299. /*{
  300. FILE* file = f o pen("d:\\test.midi", "wb");
  301. fwrite(midiTrackHeaderOut - sizeof(MidiHeaderChunk_t), bytes_written, 1, file);
  302. fclose(file);
  303. }*/
  304. return 1;
  305. }