fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <stdint.h>
  5. #include <string.h>
  6.  
  7. //midi event types
  8. enum{
  9. NOTE_OFF = 0x8,
  10. NOTE_ON = 0x9,
  11. NOTE_AFTERTOUCH = 0xA,
  12. CONTROLLER = 0xB,
  13. PROGRAM_CHANGE = 0xC,
  14. PROGRAM_AFTERTOUCH = 0xD,
  15. PITCH_BEND = 0xE,
  16. };
  17.  
  18. //meta event types
  19. enum{
  20. SEQUENCE_NUMBER = 0x00,
  21. TEXT = 0x01,
  22. COPYRIGHT_NOTICE = 0x02,
  23. SEQUENCE_TRACK_NAME = 0x03,
  24. INSTRUMENT_NAME = 0x04,
  25. LYRICS = 0x05,
  26. MARKER = 0x06,
  27. CUE_POINT = 0x07,
  28. //UNKNOWN_TEXT = 0x09;
  29. MIDI_CHANNEL_PREFIX = 0x20,
  30. END_OF_TRACK = 0x2F,
  31. SET_TEMPO = 0x51,
  32. SMPTE_OFFSET = 0x54,
  33. TIME_SIGNATURE = 0x58,
  34. KEY_SIGNATURE = 0x59,
  35. SEQUENCE_SPECIFIC = 0x7F,
  36. };
  37.  
  38. //system exclusive events
  39. /*enum{
  40. NORMAL = 0xF0;
  41. DIVIDED = 0xF0;
  42. DIVIDED = 0xF7;
  43. };*/
  44.  
  45. typedef struct _MthdCD{
  46. uint16_t format;
  47. uint16_t tracks_count;
  48. uint16_t time_division;
  49. uint8_t time_divisionType;
  50. }_MthdCD;
  51.  
  52. typedef struct _metaEventStruct{
  53. uint8_t type;
  54. uint64_t length;
  55. uint8_t *data;
  56. }_metaEventStruct;
  57.  
  58. typedef struct _midiEventStruct{
  59. uint8_t type;
  60. uint8_t channel;
  61. uint8_t param1, param2;
  62. }_midiEventStruct;
  63.  
  64. typedef struct _sysExEventStruct{
  65. uint64_t length;
  66. uint8_t *data;
  67. }_sysExEventStruct;
  68.  
  69. typedef struct _MtrkCD{
  70. uint32_t byteCount;
  71. uint64_t elementCount;
  72. uint64_t *deltaTime;
  73. uint8_t *eventType;
  74. _metaEventStruct *metaEventValues;
  75. _midiEventStruct *midiEventValues;
  76. _sysExEventStruct *sysExEventValues;
  77. }_MtrkCD;
  78.  
  79. uint64_t _ReadVariableLength(FILE *file,int *l);
  80. uint8_t _ReadByte(FILE *file);
  81. uint16_t _ReadByte2(FILE *file);
  82. uint32_t _ReadByte4(FILE *file);
  83.  
  84. uint8_t _firstBits4(int byte);
  85. uint8_t _lastBits4(int byte);
  86. uint8_t _firstByte(int bytes);
  87. uint8_t _lastByte(int bytes);
  88.  
  89. int _ReadMthdChunk(FILE *file, _MthdCD *MthdChunkData, int print);
  90. int _ReadMtrkChunk(FILE *file, _MtrkCD *MtrkChunkData, int trackID, int print);
  91.  
  92. int _ParseMidi(char *fileName, int print, int save);
  93.  
  94. uint64_t _ReadVariableLength(FILE *file, int *l){
  95. *l=0;
  96. uint64_t totalVal = 0;
  97. uint8_t curVal=0, copyVal=0;
  98. do{
  99. copyVal = curVal = _ReadByte(file);
  100. copyVal &= ~(1 << 7);
  101. totalVal = (totalVal << 7) + copyVal;
  102. (*l)++;
  103. }while(curVal&(1<<7));
  104. return totalVal;
  105. }
  106.  
  107. uint8_t _ReadByte(FILE *file){
  108. return (fgetc(file));
  109. }
  110.  
  111. uint16_t _ReadByte2(FILE *file){
  112. uint16_t res = fgetc(file);
  113. res = (res<<8) + fgetc(file);
  114. return res;
  115. }
  116.  
  117. uint32_t _ReadByte4(FILE *file){
  118. uint32_t res = fgetc(file);
  119. res = (res<<8) + fgetc(file);
  120. res = (res<<8) + fgetc(file);
  121. res = (res<<8) + fgetc(file);
  122. return res;
  123. }
  124.  
  125. uint8_t _firstBits4(int byte){
  126. return (byte>>4);
  127. }
  128.  
  129. uint8_t _lastBits4(int byte){
  130. return byte-((byte>>4)<<4);
  131. }
  132. uint8_t _firstByte(int bytes){
  133. return (bytes>>8);
  134. }
  135.  
  136. uint8_t _lastByte(int bytes){
  137. return bytes-((bytes>>8)<<8);
  138. }
  139.  
  140. int _ReadMthdChunk(FILE *file, _MthdCD *MthdChunkData, int print){
  141. uint32_t chkName = _ReadByte4(file);
  142. if (chkName != 0x4D546864){
  143. return 0;
  144. }
  145. uint32_t chkLength = _ReadByte4(file);
  146. if (chkLength != 0x00000006){
  147. return 0;
  148. }
  149. MthdChunkData->format = _ReadByte2(file);
  150. MthdChunkData->tracks_count = _ReadByte2(file);
  151. MthdChunkData->time_division = _ReadByte2(file);
  152. if (MthdChunkData->time_divisionType & (1<<16)){
  153. MthdChunkData->time_divisionType = 1;
  154. }
  155. else{
  156. MthdChunkData->time_divisionType = 0;
  157. }
  158. if (print){
  159. printf("\n\n\n--------------------------------------------------------------------------------\nParsed MThd:\n\n");
  160. printf("Chunk Name: %26s%c%c%c%c\n","",(char)(chkName>>24),(char)((chkName>>16)%0x100),(char)((chkName>>8)%0x100),(char)((chkName)%0x100));
  161. printf("Chunk Size: %24d bytes\n\n",chkLength);
  162. char str[25];
  163. switch (MthdChunkData->format){
  164. case 0x00000000:
  165. strcpy(str,"Single Track");
  166. break;
  167. case 0x00000001:
  168. strcpy(str,"Multiple Track");
  169. break;
  170. case 0x00000002:
  171. strcpy(str,"Multiple Song");
  172. break;
  173. default:
  174. return 0;
  175. }
  176. printf("Midi Format: %29s\n",str);
  177. printf("Number of Tracks: %24d\n",MthdChunkData->tracks_count);
  178. switch(MthdChunkData->time_divisionType){
  179. case 0x00:
  180. strcpy(str,"Ticks per Quarter Note");
  181. break;
  182. case 0x01:
  183. strcpy(str,"Frames per Second");
  184. break;
  185. default:
  186. return 0;
  187. }
  188. printf("Time Division Type: %22s\nTime Division Value: %21d\n",str,MthdChunkData->time_division);
  189. }
  190. return 1;
  191. }
  192.  
  193. int _ReadMtrkChunk(FILE *file, _MtrkCD *MtrkChunkData, int trackID, int print){
  194. //static int trackID = 0;
  195. int i,j;
  196. uint32_t chkName = _ReadByte4(file);
  197. if (chkName != 0x4D54726B){
  198. return 0;
  199. }
  200. MtrkChunkData->byteCount = _ReadByte4(file);
  201. uint32_t parsedLength = MtrkChunkData->byteCount;
  202.  
  203. uint8_t midiEventType;
  204. uint8_t midiChannel;
  205.  
  206. int l=0;
  207.  
  208. MtrkChunkData->elementCount=0;
  209. MtrkChunkData->deltaTime=(uint64_t *)(malloc(sizeof(uint64_t)));
  210. MtrkChunkData->eventType=(uint8_t *)(malloc(sizeof(uint8_t)));
  211. MtrkChunkData->metaEventValues=(_metaEventStruct *)(malloc(sizeof(_metaEventStruct)));
  212. MtrkChunkData->midiEventValues=(_midiEventStruct *)(malloc(sizeof(_midiEventStruct)));
  213. MtrkChunkData->sysExEventValues=(_sysExEventStruct *)(malloc(sizeof(_sysExEventStruct)));
  214.  
  215. while (parsedLength > 0){
  216. MtrkChunkData->deltaTime=(realloc(MtrkChunkData->deltaTime,sizeof(uint64_t) * (MtrkChunkData->elementCount+1)));
  217. MtrkChunkData->eventType=(realloc(MtrkChunkData->eventType,sizeof(uint8_t) * (MtrkChunkData->elementCount+1)));
  218. MtrkChunkData->metaEventValues=(realloc(MtrkChunkData->metaEventValues,sizeof(_metaEventStruct) * (MtrkChunkData->elementCount+1)));
  219. MtrkChunkData->midiEventValues=(realloc(MtrkChunkData->midiEventValues,sizeof(_midiEventStruct) * (MtrkChunkData->elementCount+1)));
  220. MtrkChunkData->sysExEventValues=(realloc(MtrkChunkData->sysExEventValues,sizeof(_sysExEventStruct) * (MtrkChunkData->elementCount+1)));
  221.  
  222. //getch();
  223. //printf("looped... toBeParsedLength is %d \n",parsedLength);
  224. ((MtrkChunkData->deltaTime)[MtrkChunkData->elementCount]) = _ReadVariableLength(file,&l);
  225. //printf("Variable length: %d\n",MtrkChunkData->deltaTime);
  226. parsedLength-=l;
  227. uint8_t nByte = _ReadByte(file);
  228. //printf("nByte: 0x%X\n",nByte);
  229. parsedLength-=1;
  230. //check nByte for event type
  231. switch(nByte){
  232. //meta event case
  233. case 0xFF:
  234. ((MtrkChunkData->eventType)[MtrkChunkData->elementCount])=1;
  235. //printf("Found META event\n");
  236. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).type = _ReadByte(file);
  237. //printf("Meta event 0x%X\n",metaEventType);
  238. parsedLength-=1;
  239. switch(((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).type){
  240. //might seem trivial to seperate types since all is scanned the same way but it is actually needed for separating conversion and track combination
  241. case SEQUENCE_NUMBER:
  242. case KEY_SIGNATURE:
  243. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadByte(file);
  244. parsedLength-=1;
  245. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  246. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  247. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  248. parsedLength-=1;
  249. }
  250. break;
  251. case SEQUENCE_SPECIFIC:
  252. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  253. parsedLength-=l;
  254. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  255. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  256. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  257. parsedLength-=1;
  258. }
  259. break;
  260. case TEXT:
  261. case COPYRIGHT_NOTICE:
  262. case SEQUENCE_TRACK_NAME:
  263. case INSTRUMENT_NAME:
  264. case LYRICS:
  265. case MARKER:
  266. case CUE_POINT:
  267. case 0x09: //unknown text event
  268. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  269. parsedLength-=l;
  270. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  271. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  272. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  273. parsedLength-=1;
  274. }
  275. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i]='\0';
  276. break;
  277. case MIDI_CHANNEL_PREFIX:
  278. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  279. parsedLength-=l;
  280. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  281. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  282. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  283. parsedLength-=1;
  284. }
  285. break;
  286. case SET_TEMPO:
  287. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  288. parsedLength-=l;
  289. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  290. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  291. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  292. parsedLength-=1;
  293. }
  294. break;
  295. case SMPTE_OFFSET:
  296. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  297. parsedLength-=l;
  298. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  299. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  300. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  301. parsedLength-=1;
  302. }
  303. break;
  304. case TIME_SIGNATURE:
  305. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  306. parsedLength-=l;
  307. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  308. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  309. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  310. parsedLength-=1;
  311. }
  312. break;
  313. case END_OF_TRACK:
  314. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  315. parsedLength-=l;
  316. ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length));
  317. for (i=0;i<((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).length;i++){
  318. (((MtrkChunkData->metaEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  319. parsedLength-=1;
  320. }
  321. break;
  322. default:
  323. return 0;
  324. }
  325. break;
  326. //system exclusive event case
  327. case 0xF0:
  328. case 0xF7:
  329. ((MtrkChunkData->eventType)[MtrkChunkData->elementCount])=2;
  330. //printf("Found System Exclusive event\n");
  331. ((MtrkChunkData->sysExEventValues)[MtrkChunkData->elementCount]).length=_ReadVariableLength(file,&l);
  332. parsedLength-=l;
  333. ((MtrkChunkData->sysExEventValues)[MtrkChunkData->elementCount]).data=(uint8_t *)(malloc(sizeof(uint8_t) * ((MtrkChunkData->sysExEventValues)[MtrkChunkData->elementCount]).length));
  334. for (i=0;i<((MtrkChunkData->sysExEventValues)[MtrkChunkData->elementCount]).length;i++){
  335. (((MtrkChunkData->sysExEventValues)[MtrkChunkData->elementCount]).data)[i] = _ReadByte(file);
  336. parsedLength-=1;
  337. }
  338. break;
  339. //midi event case
  340. default:
  341. ((MtrkChunkData->eventType)[MtrkChunkData->elementCount])=0;
  342. //printf("Found MIDI event\n");
  343. midiEventType = _firstBits4(nByte);
  344. midiChannel = _lastBits4(nByte);
  345. //printf("MIDI event type: 0x%X\n",midiEventType);
  346. switch (midiEventType){
  347. case NOTE_OFF:
  348. case NOTE_ON:
  349. case NOTE_AFTERTOUCH:
  350. case CONTROLLER:
  351. case PITCH_BEND:
  352. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount]).type = midiEventType;
  353. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount]).channel = midiChannel;
  354. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount]).param1 = _ReadByte(file);
  355. parsedLength-=1;
  356. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount].param2) = _ReadByte(file);
  357. parsedLength-=1;
  358. break;
  359. case PROGRAM_CHANGE:
  360. case PROGRAM_AFTERTOUCH:
  361. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount]).type = midiEventType;
  362. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount]).channel = midiChannel;
  363. ((MtrkChunkData->midiEventValues)[MtrkChunkData->elementCount]).param1 = _ReadByte(file);
  364. parsedLength-=1;
  365. break;
  366. default:
  367. return 0;
  368. }
  369. break;
  370. }
  371. (MtrkChunkData->elementCount)++;
  372. }
  373. if (print){
  374. printf("\n\n\n--------------------------------------------------------------------------------\n");
  375. printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  376. printf("--------------------------------------------------------------------------------\nParsed MTrk[%d]:\n\n",trackID);
  377. printf("Chunk Name: %26s%c%c%c%c\n","",(char)(chkName>>24),(char)((chkName>>16)%0x100),(char)((chkName>>8)%0x100),(char)((chkName)%0x100));
  378. printf("Chunk Size: %24d bytes\n",MtrkChunkData->byteCount);
  379. printf("Number of Events: %24d\n",MtrkChunkData->elementCount);
  380. printf("\nEvents:\n");
  381. char str[40]={'\0'};
  382. for (i=0;i<MtrkChunkData->elementCount;i++){
  383. printf("\nDelta Time Value: %18d ticks\n",MtrkChunkData->deltaTime[i]);
  384. switch(MtrkChunkData->eventType[i]){
  385. case 2:
  386. strcpy(str,"System Exclusive Event");
  387. break;
  388. case 1:
  389. strcpy(str,"META Event");
  390. break;
  391. case 0:
  392. strcpy(str,"MIDI Event");
  393. break;
  394. }
  395. printf("Event Type: %30s\n",str);
  396. if (MtrkChunkData->eventType[i] == 1){
  397. switch(MtrkChunkData->metaEventValues[i].type){
  398. case SEQUENCE_NUMBER:
  399. strcpy(str,"Sequence Number Event");
  400. break;
  401. case TEXT:
  402. strcpy(str,"Text Event");
  403. break;
  404. case COPYRIGHT_NOTICE:
  405. strcpy(str,"Copyright Notice Event");
  406. break;
  407. case SEQUENCE_TRACK_NAME:
  408. strcpy(str,"Sequence / Track Name Event");
  409. break;
  410. case INSTRUMENT_NAME:
  411. strcpy(str,"Instrument Name Event");
  412. break;
  413. case LYRICS:
  414. strcpy(str,"Lyrics Event");
  415. break;
  416. case MARKER:
  417. strcpy(str,"Marker Event");
  418. break;
  419. case CUE_POINT:
  420. strcpy(str,"Cue Point Event");
  421. break;
  422. case 0x09:
  423. strcpy(str,"Unknown Text Type Event");
  424. break;
  425. case MIDI_CHANNEL_PREFIX:
  426. strcpy(str,"MIDI Channel Prefix Event");
  427. break;
  428. case END_OF_TRACK:
  429. strcpy(str,"End of Track Event");
  430. break;
  431. case SET_TEMPO:
  432. strcpy(str,"Set Tempo Event");
  433. break;
  434. case SMPTE_OFFSET:
  435. strcpy(str,"SMPTE Offset Event");
  436. break;
  437. case TIME_SIGNATURE:
  438. strcpy(str,"Time Signature Event");
  439. break;
  440. case KEY_SIGNATURE:
  441. strcpy(str,"Key Signature Event");
  442. break;
  443. case SEQUENCE_SPECIFIC:
  444. strcpy(str,"Sequencer Specific Event");
  445. break;
  446. default:
  447. strcpy(str,"UNKNOWN EVENT");
  448. }
  449. printf("Event Sub-Type: %26s\n",str);
  450. switch(MtrkChunkData->metaEventValues[i].type){
  451. case SEQUENCE_NUMBER:
  452. printf("Event Parameters:\n");
  453. printf("Value: %0x04X\n",MtrkChunkData->metaEventValues[i].data[0]<<8+MtrkChunkData->metaEventValues[i].data[1]);
  454. break;
  455. case TEXT:
  456. case COPYRIGHT_NOTICE:
  457. case SEQUENCE_TRACK_NAME:
  458. case INSTRUMENT_NAME:
  459. case LYRICS:
  460. case MARKER:
  461. case CUE_POINT:
  462. case 0x09:
  463. printf("Event Parameters:\n");
  464. printf("%s\n",(char *)MtrkChunkData->metaEventValues[i].data);
  465. break;
  466. case MIDI_CHANNEL_PREFIX:
  467. printf("Event Parameters:\n");
  468. printf("Channel: %d\n",MtrkChunkData->metaEventValues[i].data[0]);
  469. break;
  470. case SET_TEMPO:
  471. printf("Event Parameters:\n");
  472. printf("Value: %8u Microseconds per Quarter Note\n",(MtrkChunkData->metaEventValues[i].data[0]<<16)+(MtrkChunkData->metaEventValues[i].data[1]<<8)+MtrkChunkData->metaEventValues[i].data[2]);
  473. break;
  474. case SMPTE_OFFSET:
  475. printf("Event Parameters:\n");
  476. printf("Hour: %-2d Min: %-2d Sec: %-2d Frames: %-2d Sub-Frames: %-2d\n",MtrkChunkData->metaEventValues[i].data[0],MtrkChunkData->metaEventValues[i].data[1],MtrkChunkData->metaEventValues[i].data[2],MtrkChunkData->metaEventValues[i].data[3],MtrkChunkData->metaEventValues[i].data[4]);
  477. break;
  478. case TIME_SIGNATURE:
  479. printf("Event Parameters:\n");
  480. printf("Numerator: %-3d Denominator: %-3d Metronome: %-3d 1/32: %-3d\n",MtrkChunkData->metaEventValues[i].data[0],MtrkChunkData->metaEventValues[i].data[1],MtrkChunkData->metaEventValues[i].data[2],MtrkChunkData->metaEventValues[i].data[3]);
  481. break;
  482. case KEY_SIGNATURE:
  483. printf("Event Parameters:\n");
  484. printf("Key: %+2d Scale: %d\n",MtrkChunkData->metaEventValues[i].data[0],MtrkChunkData->metaEventValues[i].data[1]);
  485. break;
  486. default:
  487. break;
  488. }
  489. }
  490. else if (MtrkChunkData->eventType[i] == 2){
  491. printf("Event Parameters:\n Value: 0x");
  492. for (j=0;j<MtrkChunkData->sysExEventValues[i].length;j++){
  493. printf("%02X",MtrkChunkData->sysExEventValues[i].data[j]);
  494. }
  495. printf("\n");
  496. }
  497. else{
  498. switch(MtrkChunkData->midiEventValues[i].type){
  499. case NOTE_OFF:
  500. strcpy(str,"Note-Off Event");
  501. break;
  502. case NOTE_ON:
  503. strcpy(str,"Note-On Event");
  504. break;
  505. case NOTE_AFTERTOUCH:
  506. strcpy(str,"Note Aftertouch Event");
  507. break;
  508. case CONTROLLER:
  509. strcpy(str,"Controller Event");
  510. break;
  511. case PROGRAM_CHANGE:
  512. strcpy(str,"Program Change Event");
  513. break;
  514. case PROGRAM_AFTERTOUCH:
  515. strcpy(str,"Program Aftertouch Event");
  516. break;
  517. case PITCH_BEND:
  518. strcpy(str,"Pitch Bend Event");
  519. break;
  520. default:
  521. strcpy(str,"UNKNOWN Event");
  522. }
  523. printf("Event Sub-Type: %26s\n",str);
  524. switch(MtrkChunkData->midiEventValues[i].type){
  525. case NOTE_OFF:
  526. case NOTE_ON:
  527. printf("Event Parameters:\n");
  528. printf("Note Number: %d Note Velocity: %d\n",MtrkChunkData->midiEventValues[i].param1,MtrkChunkData->midiEventValues[i].param2);
  529. break;
  530. case NOTE_AFTERTOUCH:
  531. printf("Event Parameters:\n");
  532. printf("Note Number: %d Aftertouch Value: %d\n",MtrkChunkData->midiEventValues[i].param1,MtrkChunkData->midiEventValues[i].param2);
  533. break;
  534. case CONTROLLER:
  535. printf("Event Parameters:\n");
  536. printf("Controller Number: %d Controller Value: %d\n",MtrkChunkData->midiEventValues[i].param1,MtrkChunkData->midiEventValues[i].param2);
  537. break;
  538. case PROGRAM_CHANGE:
  539. printf("Event Parameters:\n");
  540. printf("Program Number: %d\n",MtrkChunkData->midiEventValues[i].param1);
  541. break;
  542. case PROGRAM_AFTERTOUCH:
  543. printf("Event Parameters:\n");
  544. printf("Aftertouch Value: %d\n",MtrkChunkData->midiEventValues[i].param1);
  545. break;
  546. case PITCH_BEND:
  547. printf("Event Parameters:\n");
  548. printf("Pitch Value: %d\n",MtrkChunkData->midiEventValues[i].param1 + (MtrkChunkData->midiEventValues[i].param2>>8));
  549. break;
  550. default:
  551. break;
  552. }
  553. }
  554. printf("Press ANY key to continue...\n");
  555. getch();
  556. }
  557. }
  558. return 1;
  559. }
  560.  
  561. int _ParseMidi(char *fileName, int print, int save){
  562. FILE *midiFile;
  563. _MthdCD *MthdData = (_MthdCD *)(malloc(sizeof(_MthdCD)));
  564. midiFile = fopen(fileName, "rb");
  565. if (midiFile == NULL){
  566. printf("Failed to open the file. Are you sure the file exists?\n");
  567. return 0;
  568. }
  569. if (!_ReadMthdChunk(midiFile,MthdData, print)){
  570. printf("Error reading MThd Chunk. Bad MThd.\n");
  571. return 0;
  572. }
  573.  
  574. _MtrkCD **MtrkDatas = (_MtrkCD **)(malloc(sizeof(_MtrkCD *)));
  575. uint64_t i,j,k,p;
  576. for (p=0;p<MthdData->tracks_count;p++){
  577. MtrkDatas[p] = (_MtrkCD *)(malloc(sizeof(_MtrkCD)));
  578. if(!_ReadMtrkChunk(midiFile,MtrkDatas[p],p,print)){
  579. printf("Error reading MTrk Chunk. Bad MTrk.\n");
  580. return 0;
  581. }
  582. }
  583.  
  584. fclose(midiFile);
  585.  
  586. if (save){
  587. char saveFileName[40];
  588. strcpy(saveFileName,fileName);
  589. strcpy(saveFileName+strlen(fileName)-4," Parsed.txt");
  590. FILE *saveFile;
  591. //printf("saveFileName: %s.",saveFileName);
  592.  
  593. saveFile = fopen(saveFileName,"w");
  594. if (saveFile == NULL){
  595. printf("Failed to open save file.\n");
  596. return 0;
  597. }
  598.  
  599. fprintf(saveFile,"\n\n\n--------------------------------------------------------------------------------\n\n\n\nParsed MThd:\n\n");
  600. fprintf(saveFile,"Chunk Name: %26sMThd\n","");
  601. fprintf(saveFile,"Chunk Size: %23s6 bytes\n\n","");
  602. char str[40];
  603. switch (MthdData->format){
  604. case 0x00000000:
  605. strcpy(str,"Single Track");
  606. break;
  607. case 0x00000001:
  608. strcpy(str,"Multiple Track");
  609. break;
  610. case 0x00000002:
  611. strcpy(str,"Multiple Song");
  612. break;
  613. default:
  614. return 0;
  615. }
  616. fprintf(saveFile,"Midi Format: %29s\n",str);
  617. fprintf(saveFile,"Number of Tracks: %24d\n",MthdData->tracks_count);
  618. switch(MthdData->time_divisionType){
  619. case 0x00:
  620. strcpy(str,"Ticks per Quarter Note");
  621. break;
  622. case 0x01:
  623. strcpy(str,"Frames per Second");
  624. break;
  625. default:
  626. return 0;
  627. }
  628. fprintf(saveFile,"Time Division Type: %22s\nTime Division Value: %21d\n",str,MthdData->time_division);
  629.  
  630. for (k=0;k<(MthdData->tracks_count);k++){
  631. _MtrkCD *MtrkChunkData = MtrkDatas[k];
  632. fprintf(saveFile,"\n\n\n--------------------------------------------------------------------------------\n");
  633. fprintf(saveFile,"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
  634. fprintf(saveFile,"--------------------------------------------------------------------------------\n\n\n\nParsed MTrk[%d]:\n\n",k);
  635. fprintf(saveFile,"Chunk Name: %26sMTrk\n","");
  636. fprintf(saveFile,"Chunk Size: %24d bytes\n",MtrkChunkData->byteCount);
  637. fprintf(saveFile,"Number of Events: %24d\n",MtrkChunkData->elementCount);
  638. fprintf(saveFile,"\nEvents:\n");
  639. for (i=0;i<MtrkChunkData->elementCount;i++){
  640. fprintf(saveFile,"\nDelta Time Value: %18d ticks\n",(MtrkChunkData->deltaTime)[i]);
  641. switch((MtrkChunkData->eventType)[i]){
  642. case 2:
  643. strcpy(str,"System Exclusive Event");
  644. break;
  645. case 1:
  646. strcpy(str,"META Event");
  647. break;
  648. case 0:
  649. strcpy(str,"MIDI Event");
  650. break;
  651. }
  652. fprintf(saveFile,"Event Type: %30s\n",str);
  653. if (MtrkChunkData->eventType[i] == 1){
  654. switch(((MtrkChunkData->metaEventValues)[i]).type){
  655. case SEQUENCE_NUMBER:
  656. strcpy(str,"Sequence Number Event");
  657. break;
  658. case TEXT:
  659. strcpy(str,"Text Event");
  660. break;
  661. case COPYRIGHT_NOTICE:
  662. strcpy(str,"Copyright Notice Event");
  663. break;
  664. case SEQUENCE_TRACK_NAME:
  665. strcpy(str,"Sequence / Track Name Event");
  666. break;
  667. case INSTRUMENT_NAME:
  668. strcpy(str,"Instrument Name Event");
  669. break;
  670. case LYRICS:
  671. strcpy(str,"Lyrics Event");
  672. break;
  673. case MARKER:
  674. strcpy(str,"Marker Event");
  675. break;
  676. case CUE_POINT:
  677. strcpy(str,"Cue Point Event");
  678. break;
  679. case 0x09:
  680. strcpy(str,"Unknown Text Type Event");
  681. break;
  682. case MIDI_CHANNEL_PREFIX:
  683. strcpy(str,"MIDI Channel Prefix Event");
  684. break;
  685. case END_OF_TRACK:
  686. strcpy(str,"End of Track Event");
  687. break;
  688. case SET_TEMPO:
  689. strcpy(str,"Set Tempo Event");
  690. break;
  691. case SMPTE_OFFSET:
  692. strcpy(str,"SMPTE Offset Event");
  693. break;
  694. case TIME_SIGNATURE:
  695. strcpy(str,"Time Signature Event");
  696. break;
  697. case KEY_SIGNATURE:
  698. strcpy(str,"Key Signature Event");
  699. break;
  700. case SEQUENCE_SPECIFIC:
  701. strcpy(str,"Sequencer Specific Event");
  702. break;
  703. default:
  704. strcpy(str,"UNKNOWN EVENT");
  705. }
  706. fprintf(saveFile,"Event Sub-Type: %26s\n",str);
  707. switch(MtrkChunkData->metaEventValues[i].type){
  708. case SEQUENCE_NUMBER:
  709. fprintf(saveFile,"Event Parameters:\n");
  710. fprintf(saveFile,"Value: %0x04X\n",(((((MtrkChunkData->metaEventValues)[i]).data)[0])<<8)+((((MtrkChunkData->metaEventValues)[i]).data)[1]));
  711. break;
  712. case TEXT:
  713. case COPYRIGHT_NOTICE:
  714. case SEQUENCE_TRACK_NAME:
  715. case INSTRUMENT_NAME:
  716. case LYRICS:
  717. case MARKER:
  718. case CUE_POINT:
  719. case 0x09:
  720. fprintf(saveFile,"Event Parameters:\n");
  721. fprintf(saveFile,"%s\n",(char *)(((MtrkChunkData->metaEventValues)[i]).data));
  722. break;
  723. case MIDI_CHANNEL_PREFIX:
  724. fprintf(saveFile,"Event Parameters:\n");
  725. fprintf(saveFile,"Channel: %d\n",((((MtrkChunkData->metaEventValues)[i]).data)[0]));
  726. break;
  727. case SET_TEMPO:
  728. fprintf(saveFile,"Event Parameters:\n");
  729. fprintf(saveFile,"Value: %8u Microseconds per Quarter Note\n",((MtrkChunkData->metaEventValues[i].data[0])<<16)+((MtrkChunkData->metaEventValues[i].data[1])<<8)+(MtrkChunkData->metaEventValues[i].data[2]));
  730. break;
  731. case SMPTE_OFFSET:
  732. fprintf(saveFile,"Event Parameters:\n");
  733. fprintf(saveFile,"Hour: %-2d Min: %-2d Sec: %-2d Frames: %-2d Sub-Frames: %-2d\n",MtrkChunkData->metaEventValues[i].data[0],MtrkChunkData->metaEventValues[i].data[1],MtrkChunkData->metaEventValues[i].data[2],MtrkChunkData->metaEventValues[i].data[3],MtrkChunkData->metaEventValues[i].data[4]);
  734. break;
  735. case TIME_SIGNATURE:
  736. fprintf(saveFile,"Event Parameters:\n");
  737. fprintf(saveFile,"Numerator: %-3d Denominator: %-3d Metronome: %-3d 1/32: %-3d\n",MtrkChunkData->metaEventValues[i].data[0],MtrkChunkData->metaEventValues[i].data[1],MtrkChunkData->metaEventValues[i].data[2],MtrkChunkData->metaEventValues[i].data[3]);
  738. break;
  739. case KEY_SIGNATURE:
  740. fprintf(saveFile,"Event Parameters:\n");
  741. fprintf(saveFile,"Key: %+2d Scale: %d\n",MtrkChunkData->metaEventValues[i].data[0],MtrkChunkData->metaEventValues[i].data[1]);
  742. break;
  743. default:
  744. break;
  745. }
  746. }
  747. else if (MtrkChunkData->eventType[i] == 2){
  748. fprintf(saveFile,"Event Parameters:\n Value: 0x");
  749. for (j=0;j<(((MtrkChunkData->sysExEventValues)[i]).length);j++){
  750. fprintf(saveFile,"%02X",MtrkChunkData->sysExEventValues[i].data[j]);
  751. }
  752. fprintf(saveFile,"\n");
  753. }
  754. else{
  755. switch(MtrkChunkData->midiEventValues[i].type){
  756. case NOTE_OFF:
  757. strcpy(str,"Note-Off Event");
  758. break;
  759. case NOTE_ON:
  760. strcpy(str,"Note-On Event");
  761. break;
  762. case NOTE_AFTERTOUCH:
  763. strcpy(str,"Note Aftertouch Event");
  764. break;
  765. case CONTROLLER:
  766. strcpy(str,"Controller Event");
  767. break;
  768. case PROGRAM_CHANGE:
  769. strcpy(str,"Program Change Event");
  770. break;
  771. case PROGRAM_AFTERTOUCH:
  772. strcpy(str,"Program Aftertouch Event");
  773. break;
  774. case PITCH_BEND:
  775. strcpy(str,"Pitch Bend Event");
  776. break;
  777. default:
  778. strcpy(str,"UNKNOWN Event");
  779. }
  780. fprintf(saveFile,"Event Sub-Type: %26s\n",str);
  781. switch(MtrkChunkData->midiEventValues[i].type){
  782. case NOTE_OFF:
  783. case NOTE_ON:
  784. fprintf(saveFile,"Event Parameters:\n");
  785. fprintf(saveFile,"Note Number: %d Note Velocity: %d\n",MtrkChunkData->midiEventValues[i].param1,MtrkChunkData->midiEventValues[i].param2);
  786. break;
  787. case NOTE_AFTERTOUCH:
  788. fprintf(saveFile,"Event Parameters:\n");
  789. fprintf(saveFile,"Note Number: %d Aftertouch Value: %d\n",MtrkChunkData->midiEventValues[i].param1,MtrkChunkData->midiEventValues[i].param2);
  790. break;
  791. case CONTROLLER:
  792. fprintf(saveFile,"Event Parameters:\n");
  793. fprintf(saveFile,"Controller Number: %d Controller Value: %d\n",MtrkChunkData->midiEventValues[i].param1,MtrkChunkData->midiEventValues[i].param2);
  794. break;
  795. case PROGRAM_CHANGE:
  796. fprintf(saveFile,"Event Parameters:\n");
  797. fprintf(saveFile,"Program Number: %d\n",MtrkChunkData->midiEventValues[i].param1);
  798. break;
  799. case PROGRAM_AFTERTOUCH:
  800. fprintf(saveFile,"Event Parameters:\n");
  801. fprintf(saveFile,"Aftertouch Value: %d\n",MtrkChunkData->midiEventValues[i].param1);
  802. break;
  803. case PITCH_BEND:
  804. fprintf(saveFile,"Event Parameters:\n");
  805. fprintf(saveFile,"Pitch Value: %d\n",MtrkChunkData->midiEventValues[i].param1 + (MtrkChunkData->midiEventValues[i].param2>>8));
  806. break;
  807. default:
  808. break;
  809. }
  810. }
  811. }
  812. }
  813.  
  814. fprintf(saveFile,"\n\n\n--------------------------------------------------------------------------------\n\n\n");
  815. fprintf(saveFile,"Additional Information:\n");
  816. uint64_t totalSize=0;
  817. totalSize += 14; //MThd has fixed size of 14 bytes
  818. for (k=0;k<MthdData->tracks_count;k++){
  819. _MtrkCD *MtrkChunkData = MtrkDatas[k];
  820. totalSize += MtrkChunkData->byteCount;
  821. }
  822. fprintf(saveFile,"\nFile is OK!\nTotal: %u bytes\n",totalSize);
  823. fclose(saveFile);
  824. }
  825. return 1;
  826. }
  827.  
  828. int main(){
  829. // use all variables as unsigned as long as it's feasible, otherwise you will risk wasting at least one bit of data os Sig
  830. char fileName[40];
  831. int opt;
  832. int ret;
  833. printf("Enter filename: ");
  834. fflush(stdin);
  835. scanf("%[^\n]39s",fileName);
  836. printf("1- Check File\n2- Parse File\n3- Save File\n");
  837. scanf("%d",&opt);
  838. switch(opt){
  839. case 1:
  840. ret = _ParseMidi(fileName,0,0);
  841. break;
  842. case 2:
  843. ret = _ParseMidi(fileName,1,0);
  844. break;
  845. case 3:
  846. ret = _ParseMidi(fileName,0,1);
  847. break;
  848. default:
  849. printf("Invalid input\n");
  850. break;
  851. }
  852. if (!ret){
  853. printf("File has error(s).\n");
  854. }
  855. else{
  856. printf("File is OK!\n");
  857. }
  858. printf("Press ENTER to exit the application.\n");
  859. fflush(stdin);
  860. gets(fileName);
  861. return 0;
  862. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
home.mid
3
compilation info
prog.c: In function ‘_ReadMtrkChunk’:
prog.c:379:32: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
   printf("Number of Events: %24d\n",MtrkChunkData->elementCount);
                                ^
prog.c:383:35: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
    printf("\nDelta Time Value: %18d ticks\n",MtrkChunkData->deltaTime[i]);
                                   ^
prog.c:453:76: warning: suggest parentheses around ‘+’ inside ‘<<’ [-Wparentheses]
       printf("Value: %0x04X\n",MtrkChunkData->metaEventValues[i].data[0]<<8+MtrkChunkData->metaEventValues[i].data[1]);
                                                                           ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.c:555:4: warning: implicit declaration of function ‘getch’ [-Wimplicit-function-declaration]
    getch();
    ^~~~~
prog.c: In function ‘_ParseMidi’:
prog.c:634:123: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
    fprintf(saveFile,"--------------------------------------------------------------------------------\n\n\n\nParsed MTrk[%d]:\n\n",k);
                                                                                                                           ^
prog.c:637:43: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
    fprintf(saveFile,"Number of Events: %24d\n",MtrkChunkData->elementCount);
                                           ^
prog.c:640:46: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
     fprintf(saveFile,"\nDelta Time Value: %18d ticks\n",(MtrkChunkData->deltaTime)[i]);
                                              ^
prog.c:822:44: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
   fprintf(saveFile,"\nFile is OK!\nTotal: %u bytes\n",totalSize);
                                            ^
prog.c: In function ‘main’:
prog.c:860:2: warning: implicit declaration of function ‘gets’ [-Wimplicit-function-declaration]
  gets(fileName);
  ^~~~
prog.c:852:5: warning: ‘ret’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  if (!ret){
     ^
/home/iNzB6e/ccsKHaIh.o: In function `main':
prog.c:(.text.startup+0xa6): warning: the `gets' function is dangerous and should not be used.
/home/iNzB6e/ccsKHaIh.o: In function `_ReadMtrkChunk':
prog.c:(.text+0xd90): undefined reference to `getch'
collect2: error: ld returned 1 exit status
stdout
Standard output is empty