1 /*
2 * MUS2MIDI: MUS to MIDI Library
3 *
4 * Copyright (C) 2014 Bret Curtis
5 * Copyright (C) WildMIDI Developers 2015-2016
6 * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28
29 #ifdef __DJGPP__
30 typedef signed char int8_t;
31 typedef unsigned char uint8_t;
32 typedef signed short int16_t;
33 typedef unsigned short uint16_t;
34 typedef signed long int32_t;
35 typedef unsigned long uint32_t;
36 #endif
37
38 #define MUS_FREQUENCY 140 /* default Hz or BPM */
39
40 #if 0 /* older units: */
41 #define MUS_TEMPO 0x001aa309 /* MPQN: 60000000 / 34.37Hz = 1745673 */
42 #define MUS_DIVISION 0x0059 /* 89 -- used by many mus2midi converters */
43 #endif
44
45 #define MUS_TEMPO 0x00068A1B /* MPQN: 60000000 / 140BPM (140Hz) = 428571 */
46 /* 0x000D1436 -> MPQN: 60000000 / 70BPM (70Hz) = 857142 */
47
48 #define MUS_DIVISION 0x0101 /* 257 for 140Hz files with a 140MPQN */
49 /* 0x0088 -> 136 for 70Hz files with a 140MPQN */
50 /* 0x010B -> 267 for 70hz files with a 70MPQN */
51 /* 0x01F9 -> 505 for 140hz files with a 70MPQN */
52
53 /* New
54 * QLS: MPQN/1000000 = 0.428571
55 * TDPS: QLS/PPQN = 0.428571/136 = 0.003151257
56 * PPQN: 136
57 *
58 * QLS: MPQN/1000000 = 0.428571
59 * TDPS: QLS/PPQN = 0.428571/257 = 0.001667591
60 * PPQN: 257
61 *
62 * QLS: MPQN/1000000 = 0.857142
63 * TDPS: QLS/PPQN = 0.857142/267 = 0.00321027
64 * PPQN: 267
65 *
66 * QLS: MPQN/1000000 = 0.857142
67 * TDPS: QLS/PPQN = 0.857142/505 = 0.001697311
68 * PPQN: 505
69 *
70 * Old
71 * QLS: MPQN/1000000 = 1.745673
72 * TDPS: QLS/PPQN = 1.745673 / 89 = 0.019614303 (seconds per tick)
73 * PPQN: (TDPS = QLS/PPQN) (0.019614303 = 1.745673/PPQN) (0.019614303*PPQN = 1.745673) (PPQN = 89.000001682)
74 *
75 */
76
77 #define MUSEVENT_KEYOFF 0
78 #define MUSEVENT_KEYON 1
79 #define MUSEVENT_PITCHWHEEL 2
80 #define MUSEVENT_CHANNELMODE 3
81 #define MUSEVENT_CONTROLLERCHANGE 4
82 #define MUSEVENT_END 6
83
84 #define MUS_MIDI_MAXCHANNELS 16
85
86 static char MUS_ID[] = { 'M', 'U', 'S', 0x1A };
87
88 static uint8_t mus_midimap[] =
89 {/* MIDI Number Description */
90 0, /* 0 program change */
91 0, /* 1 bank selection */
92 0x01, /* 2 Modulation pot (frequency vibrato depth) */
93 0x07, /* 3 Volume: 0-silent, ~100-normal, 127-loud */
94 0x0A, /* 4 Pan (balance) pot: 0-left, 64-center (default), 127-right */
95 0x0B, /* 5 Expression pot */
96 0x5B, /* 6 Reverb depth */
97 0x5D, /* 7 Chorus depth */
98 0x40, /* 8 Sustain pedal */
99 0x43, /* 9 Soft pedal */
100 0x78, /* 10 All sounds off */
101 0x7B, /* 11 All notes off */
102 0x7E, /* 12 Mono (use numchannels + 1) */
103 0x7F, /* 13 Poly */
104 0x79, /* 14 reset all controllers */
105 };
106
107 typedef struct MUSHeader {
108 char ID[4]; /* identifier: "MUS" 0x1A */
109 uint16_t scoreLen;
110 uint16_t scoreStart;
111 uint16_t channels; /* count of primary channels */
112 uint16_t sec_channels; /* count of secondary channels */
113 uint16_t instrCnt;
114 } MUSHeader ;
115 #define MUS_HEADERSIZE 14
116
117 typedef struct MidiHeaderChunk {
118 char name[4];
119 int32_t length;
120 int16_t format; /* make 0 */
121 int16_t ntracks;/* make 1 */
122 int16_t division; /* 0xe250 ?? */
123 } MidiHeaderChunk;
124 #define MIDI_HEADERSIZE 14
125
126 typedef struct MidiTrackChunk {
127 char name[4];
128 int32_t length;
129 } MidiTrackChunk;
130 #define TRK_CHUNKSIZE 8
131
132 struct mus_ctx {
133 uint8_t *src, *src_ptr;
134 uint32_t srcsize;
135 uint32_t datastart;
136 uint8_t *dst, *dst_ptr;
137 uint32_t dstsize, dstrem;
138 };
139
140 #define DST_CHUNK 8192
mus2mid_resize_dst(struct mus_ctx * ctx)141 static void mus2mid_resize_dst(struct mus_ctx *ctx) {
142 uint32_t pos = (uint32_t)(ctx->dst_ptr - ctx->dst);
143 ctx->dst = (uint8_t *)realloc(ctx->dst, ctx->dstsize + DST_CHUNK);
144 ctx->dstsize += DST_CHUNK;
145 ctx->dstrem += DST_CHUNK;
146 ctx->dst_ptr = ctx->dst + pos;
147 }
148
mus2mid_write1(struct mus_ctx * ctx,uint32_t val)149 static void mus2mid_write1(struct mus_ctx *ctx, uint32_t val)
150 {
151 if (ctx->dstrem < 1)
152 mus2mid_resize_dst(ctx);
153 *ctx->dst_ptr++ = val & 0xff;
154 ctx->dstrem--;
155 }
156
mus2mid_write2(struct mus_ctx * ctx,uint32_t val)157 static void mus2mid_write2(struct mus_ctx *ctx, uint32_t val)
158 {
159 if (ctx->dstrem < 2)
160 mus2mid_resize_dst(ctx);
161 *ctx->dst_ptr++ = (val>>8) & 0xff;
162 *ctx->dst_ptr++ = val & 0xff;
163 ctx->dstrem -= 2;
164 }
165
mus2mid_write4(struct mus_ctx * ctx,uint32_t val)166 static void mus2mid_write4(struct mus_ctx *ctx, uint32_t val)
167 {
168 if (ctx->dstrem < 4)
169 mus2mid_resize_dst(ctx);
170 *ctx->dst_ptr++ = (uint8_t)((val>>24)&0xff);
171 *ctx->dst_ptr++ = (uint8_t)((val>>16)&0xff);
172 *ctx->dst_ptr++ = (uint8_t)((val>>8) & 0xff);
173 *ctx->dst_ptr++ = (uint8_t)((val & 0xff));
174 ctx->dstrem -= 4;
175 }
176
mus2mid_seekdst(struct mus_ctx * ctx,uint32_t pos)177 static void mus2mid_seekdst(struct mus_ctx *ctx, uint32_t pos) {
178 ctx->dst_ptr = ctx->dst + pos;
179 while (ctx->dstsize < pos)
180 mus2mid_resize_dst(ctx);
181 ctx->dstrem = ctx->dstsize - pos;
182 }
183
mus2mid_skipdst(struct mus_ctx * ctx,int32_t pos)184 static void mus2mid_skipdst(struct mus_ctx *ctx, int32_t pos) {
185 size_t newpos;
186 ctx->dst_ptr += pos;
187 newpos = ctx->dst_ptr - ctx->dst;
188 while (ctx->dstsize < newpos)
189 mus2mid_resize_dst(ctx);
190 ctx->dstrem = (uint32_t)(ctx->dstsize - newpos);
191 }
192
mus2mid_getdstpos(struct mus_ctx * ctx)193 static uint32_t mus2mid_getdstpos(struct mus_ctx *ctx) {
194 return (uint32_t)(ctx->dst_ptr - ctx->dst);
195 }
196
197 /* writes a variable length integer to a buffer, and returns bytes written */
mus2mid_writevarlen(int32_t value,uint8_t * out)198 static int32_t mus2mid_writevarlen(int32_t value, uint8_t *out)
199 {
200 int32_t buffer, count = 0;
201
202 buffer = value & 0x7f;
203 while ((value >>= 7) > 0) {
204 buffer <<= 8;
205 buffer += 0x80;
206 buffer += (value & 0x7f);
207 }
208
209 while (1) {
210 ++count;
211 *out = (uint8_t)buffer;
212 ++out;
213 if (buffer & 0x80)
214 buffer >>= 8;
215 else
216 break;
217 }
218 return (count);
219 }
220
221 #define MUS_READ_INT16(b) ((b)[0] | ((b)[1] << 8))
222 #define MUS_READ_INT32(b) ((b)[0] | ((b)[1] << 8) | ((b)[2] << 16) | ((b)[3] << 24))
223
Convert_mus2midi(uint8_t * in,uint32_t insize,uint8_t ** out,uint32_t * outsize,uint16_t frequency)224 static int Convert_mus2midi(uint8_t *in, uint32_t insize,
225 uint8_t **out, uint32_t *outsize,
226 uint16_t frequency)
227 {
228 struct mus_ctx ctx;
229 MUSHeader header;
230 uint8_t *cur, *end;
231 uint32_t track_size_pos, begin_track_pos, current_pos;
232 int32_t delta_time;/* Delta time for midi event */
233 int temp, ret = -1;
234 int channel_volume[MUS_MIDI_MAXCHANNELS];
235 int channelMap[MUS_MIDI_MAXCHANNELS], currentChannel;
236
237 if (insize < MUS_HEADERSIZE) {
238 /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);*/
239 return (-1);
240 }
241
242 if (!frequency)
243 frequency = MUS_FREQUENCY;
244
245 /* read the MUS header and set our location */
246 memcpy(header.ID, in, 4);
247 header.scoreLen = MUS_READ_INT16(&in[4]);
248 header.scoreStart = MUS_READ_INT16(&in[6]);
249 header.channels = MUS_READ_INT16(&in[8]);
250 header.sec_channels = MUS_READ_INT16(&in[10]);
251 header.instrCnt = MUS_READ_INT16(&in[12]);
252
253 if (memcmp(header.ID, MUS_ID, 4)) {
254 /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_MUS, NULL, 0);*/
255 return (-1);
256 }
257 if (insize < (uint32_t)header.scoreLen + (uint32_t)header.scoreStart) {
258 /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);*/
259 return (-1);
260 }
261 /* channel #15 should be excluded in the numchannels field: */
262 if (header.channels > MUS_MIDI_MAXCHANNELS - 1) {
263 /*_WM_GLOBAL_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, NULL, 0);*/
264 return (-1);
265 }
266
267 memset(&ctx, 0, sizeof(struct mus_ctx));
268 ctx.src = ctx.src_ptr = in;
269 ctx.srcsize = insize;
270
271 ctx.dst = (uint8_t*)calloc(DST_CHUNK, sizeof(uint8_t));
272 ctx.dst_ptr = ctx.dst;
273 ctx.dstsize = DST_CHUNK;
274 ctx.dstrem = DST_CHUNK;
275
276 /* Map channel 15 to 9 (percussions) */
277 for (temp = 0; temp < MUS_MIDI_MAXCHANNELS; ++temp) {
278 channelMap[temp] = -1;
279 channel_volume[temp] = 0x40;
280 }
281 channelMap[15] = 9;
282
283 /* Header is 14 bytes long and add the rest as well */
284 mus2mid_write1(&ctx, 'M');
285 mus2mid_write1(&ctx, 'T');
286 mus2mid_write1(&ctx, 'h');
287 mus2mid_write1(&ctx, 'd');
288 mus2mid_write4(&ctx, 6); /* length of header */
289 mus2mid_write2(&ctx, 0); /* MIDI type (always 0) */
290 mus2mid_write2(&ctx, 1); /* MUS files only have 1 track */
291 mus2mid_write2(&ctx, MUS_DIVISION); /* division */
292
293 /* Write out track header and track length position for later */
294 begin_track_pos = mus2mid_getdstpos(&ctx);
295 mus2mid_write1(&ctx, 'M');
296 mus2mid_write1(&ctx, 'T');
297 mus2mid_write1(&ctx, 'r');
298 mus2mid_write1(&ctx, 'k');
299 track_size_pos = mus2mid_getdstpos(&ctx);
300 mus2mid_skipdst(&ctx, 4);
301
302 /* write tempo: microseconds per quarter note */
303 mus2mid_write1(&ctx, 0x00); /* delta time */
304 mus2mid_write1(&ctx, 0xff); /* sys command */
305 mus2mid_write2(&ctx, 0x5103); /* command - set tempo */
306 mus2mid_write1(&ctx, MUS_TEMPO & 0x000000ff);
307 mus2mid_write1(&ctx, (MUS_TEMPO & 0x0000ff00) >> 8);
308 mus2mid_write1(&ctx, (MUS_TEMPO & 0x00ff0000) >> 16);
309
310 /* Percussions channel starts out at full volume */
311 mus2mid_write1(&ctx, 0x00);
312 mus2mid_write1(&ctx, 0xB9);
313 mus2mid_write1(&ctx, 0x07);
314 mus2mid_write1(&ctx, 127);
315
316 /* get current position in source, and end of position */
317 cur = in + header.scoreStart;
318 end = cur + header.scoreLen;
319
320 currentChannel = 0;
321 delta_time = 0;
322
323 /* main loop */
324 while(cur < end){
325 /*printf("LOOP DEBUG: %d\r\n",iterator++);*/
326 uint8_t channel;
327 uint8_t event;
328 uint8_t temp_buffer[32]; /* temp buffer for current iterator */
329 uint8_t *out_local = temp_buffer;
330 uint8_t status, bit1, bit2, bitc = 2;
331
332 /* read in current bit */
333 event = *cur++;
334 channel = (event & 15); /* current channel */
335
336 /* write variable length delta time */
337 out_local += mus2mid_writevarlen(delta_time, out_local);
338
339 /* set all channels to 127 (max) volume */
340 if (channelMap[channel] < 0) {
341 *out_local++ = 0xB0 + currentChannel;
342 *out_local++ = 0x07;
343 *out_local++ = 127;
344 *out_local++ = 0x00;
345 channelMap[channel] = currentChannel++;
346 if (currentChannel == 9)
347 ++currentChannel;
348 }
349 status = channelMap[channel];
350
351 /* handle events */
352 switch ((event & 122) >> 4){
353 case MUSEVENT_KEYOFF:
354 status |= 0x80;
355 bit1 = *cur++;
356 bit2 = 0x40;
357 break;
358 case MUSEVENT_KEYON:
359 status |= 0x90;
360 bit1 = *cur & 127;
361 if (*cur++ & 128) /* volume bit? */
362 channel_volume[channelMap[channel]] = *cur++;
363 bit2 = channel_volume[channelMap[channel]];
364 break;
365 case MUSEVENT_PITCHWHEEL:
366 status |= 0xE0;
367 bit1 = (*cur & 1) >> 6;
368 bit2 = (*cur++ >> 1) & 127;
369 break;
370 case MUSEVENT_CHANNELMODE:
371 status |= 0xB0;
372 if (*cur >= sizeof(mus_midimap) / sizeof(mus_midimap[0])) {
373 /*_WM_ERROR_NEW("%s:%i: can't map %u to midi",
374 __FUNCTION__, __LINE__, *cur);*/
375 goto _end;
376 }
377 bit1 = mus_midimap[*cur++];
378 bit2 = (*cur++ == 12) ? header.channels + 1 : 0x00;
379 break;
380 case MUSEVENT_CONTROLLERCHANGE:
381 if (*cur == 0) {
382 cur++;
383 status |= 0xC0;
384 bit1 = *cur++;
385 bit2 = 0;/* silence bogus warnings */
386 bitc = 1;
387 } else {
388 status |= 0xB0;
389 if (*cur >= sizeof(mus_midimap) / sizeof(mus_midimap[0])) {
390 /*_WM_ERROR_NEW("%s:%i: can't map %u to midi",
391 __FUNCTION__, __LINE__, *cur);*/
392 goto _end;
393 }
394 bit1 = mus_midimap[*cur++];
395 bit2 = *cur++;
396 }
397 break;
398 case MUSEVENT_END: /* End */
399 status = 0xff;
400 bit1 = 0x2f;
401 bit2 = 0x00;
402 if (cur != end) { /* should we error here or report-only? */
403 /*_WM_DEBUG_MSG("%s:%i: MUS buffer off by %ld bytes",
404 __FUNCTION__, __LINE__, (long)(cur - end));*/
405 }
406 break;
407 case 5:/* Unknown */
408 case 7:/* Unknown */
409 default:/* shouldn't happen */
410 /*_WM_ERROR_NEW("%s:%i: unrecognized event (%u)",
411 __FUNCTION__, __LINE__, event);*/
412 goto _end;
413 }
414
415 /* write it out */
416 *out_local++ = status;
417 *out_local++ = bit1;
418 if (bitc == 2)
419 *out_local++ = bit2;
420
421 /* write out our temp buffer */
422 if (out_local != temp_buffer)
423 {
424 if (ctx.dstrem < sizeof(temp_buffer))
425 mus2mid_resize_dst(&ctx);
426
427 memcpy(ctx.dst_ptr, temp_buffer, out_local - temp_buffer);
428 ctx.dst_ptr += out_local - temp_buffer;
429 ctx.dstrem -= (uint32_t)(out_local - temp_buffer);
430 }
431
432 if (event & 128) {
433 delta_time = 0;
434 do {
435 delta_time = (int32_t)((delta_time * 128 + (*cur & 127)) * (140.0 / (double)frequency));
436 } while ((*cur++ & 128));
437 } else {
438 delta_time = 0;
439 }
440 }
441
442 /* write out track length */
443 current_pos = mus2mid_getdstpos(&ctx);
444 mus2mid_seekdst(&ctx, track_size_pos);
445 mus2mid_write4(&ctx, current_pos - begin_track_pos - TRK_CHUNKSIZE);
446 mus2mid_seekdst(&ctx, current_pos); /* reseek to end position */
447
448 *out = ctx.dst;
449 *outsize = ctx.dstsize - ctx.dstrem;
450 ret = 0;
451
452 _end: /* cleanup */
453 if (ret < 0) {
454 free(ctx.dst);
455 *out = NULL;
456 *outsize = 0;
457 }
458
459 return (ret);
460 }
461
462