Last active
March 4, 2024 05:25
-
-
Save bakueikozo/5a9b3303a27322f848acadc53c6396e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
typedef unsigned short uint16_t; | |
typedef unsigned char uint8_t; | |
#pragma pack(1) | |
typedef struct _noteOnOffData { | |
unsigned int tickOn; | |
unsigned int tickOff; | |
char pitch; | |
char velocity; | |
} noteOnOff; | |
typedef struct _list { | |
noteOnOff *chList[16]; | |
int counts[16]; | |
} noteList; | |
noteList nl; | |
struct PTrackInfo { | |
// YPTI | |
uint16_t track_count; | |
struct _trackmetadata { | |
uint8_t track_number; | |
uint8_t flags; | |
uint16_t use_channel_grouping_flags; | |
uint16_t default_channel_groups[16]; | |
uint16_t channel_groups[16]; | |
struct _channel_metadata { | |
uint8_t attributes; | |
uint8_t ports; | |
uint8_t control_change_ax; | |
uint8_t control_change_cx; | |
} channel_metadata[16]; | |
uint16_t sys_ex_ports; | |
} track_metadata[4]; // temporary alloc | |
// struct _trackmetadata track_metadata[] ; | |
}; | |
int parseTrack(char *p){ | |
// | |
p=p+4; /// header | |
p=p+4; /// size | |
struct PTrackInfo info; | |
info.track_count= (p[0] << 8) | p[1]; | |
p+=2; | |
int copySize = sizeof(uint16_t) + sizeof(struct _trackmetadata) * info.track_count; | |
printf("track metadata copying size = %d(0x%x)\n",copySize,copySize); | |
memcpy(&info.track_metadata,p,copySize); | |
printf("track count==%d\n",info.track_count); | |
return 0; | |
} | |
char *MTrackDelta(char *p,unsigned int *pDur){ | |
unsigned int *pDur_local; | |
unsigned char *pData_local; | |
if( *p < 0x40 ){ | |
pData_local = p + 1; | |
*pDur = (unsigned int)*p; | |
}else if( p[1] < 0x40 ){ | |
*pDur = (unsigned int)*p; | |
pData_local = p + 2; | |
*pDur = (unsigned int)p[1] * 0x40 + *pDur; | |
}else if( p[2] < 0x40 ){ | |
*pDur = (unsigned int)*p; | |
*pDur = (unsigned int)p[1] * 0x40 + *pDur; | |
pData_local = p + 3; | |
*pDur = (unsigned int)p[2] * 0x1000 + *pDur; | |
}else { | |
printf("delta parse error(0x%x)",*p); | |
pData_local = p + 1; | |
*pDur = 0; | |
} | |
return pData_local; | |
} | |
int MTrack(char *p){ | |
char *pStart=p; | |
for(int n=0;n<16;n++){ | |
printf("%02x ",p[n]); | |
} | |
printf("\n"); | |
p=p+4; // header | |
int size = ((p[0] << 24) & 0xff000000) + ((p[1] << 16) & 0x00ff0000) + ((p[2] << 8) & 0x0000ff00) + (p[3] & 0xff); | |
unsigned int tick = 0; | |
p=p+4; // size | |
// printf("MTrack(%p) size=%d(%x)\n",p,size,size); | |
char message; | |
unsigned int length=0; | |
while( p-pStart <= size /*(p[0] + p[1] + p[2] + p[3]) != 0*/ ) { | |
char param; | |
if( (*p & 0xf0 )== 0xf0 ){ | |
printf("status=0x%x ", *p ); | |
message = *p; | |
p++; | |
printf("tick=%d ",length); | |
// message is last messaege | |
switch(message){ | |
case 0xF1: | |
case 0xF2: | |
case 0xF4: | |
case 0xF5: | |
// 1byte message: | |
printf(" %02x\n", message); | |
break; | |
case 0xFF: | |
printf("sysex: "); | |
do{ | |
printf("%02x ", *p ); | |
p++; | |
}while( *p != 0xfe ); | |
p++; | |
printf(" \n"); | |
break; | |
case 0xF3: | |
case 0xF6: | |
case 0xF8: | |
param = *p; | |
p++; | |
printf(" %02x - %02x\n", message,param ); | |
break; | |
default: | |
printf("unknown message 0x%x@%p\n",message,(p-pStart)); | |
} | |
}else{ | |
p=MTrackDelta(p,&tick); | |
length=length+tick; | |
} | |
} | |
return 0; | |
} | |
unsigned char * CommonCalcContDuration(unsigned char *pData,u_int32_t *pDur) | |
{ | |
u_int32_t *pDur_local; | |
unsigned char *pData_local; | |
u_int32_t uwTmpDur; | |
*pDur = 0; | |
pData_local = pData; | |
while ( !(*pData_local & 0x80) && (*pData_local != '\0')) { | |
// printf("pData_local=%x\n",*pData_local); | |
pData_local = MTrackDelta(pData_local,&uwTmpDur); | |
// printf("mtrdelta %d\n",uwTmpDur); | |
*pDur = *pDur + uwTmpDur; | |
} | |
return pData_local; | |
} | |
char* PTrackDelta(char *p,unsigned int *pDur){ | |
} | |
void noteMake(int ch,unsigned int tick,unsigned int tickOff,char pitch,char vel){ | |
nl.chList[ch][nl.counts[ch]].tickOn=tick; | |
nl.chList[ch][nl.counts[ch]].tickOff=tickOff; | |
nl.chList[ch][nl.counts[ch]].pitch=pitch; | |
nl.chList[ch][nl.counts[ch]].velocity=vel; | |
nl.counts[ch]++; | |
} | |
int PTrack(char *p){ | |
int count[16] = {0 }; | |
char *pStart=p; | |
for(int n=0;n<32;n++){ | |
printf("%02x ",p[n]); | |
} | |
printf("\n"); | |
p=p+4; // header | |
int size = ((p[0] << 24) & 0xff000000) + ((p[1] << 16) & 0x00ff0000) + ((p[2] << 8) & 0x0000ff00) + (p[3] & 0xff); | |
unsigned int tick = 0; | |
p=p+4; // size | |
unsigned int dur=0,length=0; | |
int pitch,vel,ch; | |
while( memcmp(p,"\x00\x00\x00\x00",4)!= 0 ){ | |
// printf("p=%x\n",*p); | |
char status= (*p)&0x80; | |
if( status ){ | |
switch( (*p) &0xf0){ | |
case 0x90: | |
printf("@%d noteon ch=%d pitch=%d ",length, p[0]&0x0f,p[1]); | |
count[(*p)>>4]++; | |
pitch=p[1]; | |
ch=p[0]&0x0f; | |
vel=64; | |
p++; | |
p++; | |
// printf("delta[%02x]\n",*p); | |
p=MTrackDelta(p,&dur); | |
noteMake(ch,length,length+dur,pitch,64); | |
// printf("delta after[%02x] ,dur=%d\n",*p,dur); | |
printf(" length=%d\n",dur); | |
break; | |
case 0x80: | |
printf("@%d noteon ch=%d pitch=%d vel=%d ",length, p[0]&0x0f,p[1],p[2]); | |
count[(*p)>>4]++; | |
pitch=p[1]; | |
ch=p[0]&0x0f; | |
vel=p[2]; | |
p++; | |
p++; | |
p++; | |
printf("80-note on\n"); | |
// printf("delta[%02x]\n",*p); | |
p=MTrackDelta(p,&dur); | |
// printf("delta after[%02x] ,dur=%d\n",*p,dur); | |
printf("length=%d\n",dur); | |
noteMake(ch,length,length+dur,pitch,vel); | |
break; | |
case 0xA0: | |
p++; | |
p++; | |
count[(*p)>>4]++; | |
break; | |
case 0xB0: | |
p++; | |
p++; | |
p++; | |
count[(*p)>>4]++; | |
break; | |
case 0xC0: | |
p++; | |
p++; | |
count[(*p)>>4]++; | |
break; | |
case 0xD0: | |
p++; | |
p++; | |
count[(*p)>>4]++; | |
break; | |
case 0xE0: | |
p++; | |
p++; | |
p++; | |
count[(*p)>>4]++; | |
break; | |
default: | |
switch(*p){ | |
case 0xF0: | |
//printf("sysex:%02x\n",*p); | |
do{ | |
p++; | |
} while( *p != 0xf7 ); | |
p++; | |
break; | |
case 0xF8: | |
p++; | |
p++; | |
p++; | |
break; | |
case 0xF9: | |
p++; | |
break; | |
case 0xFA: | |
p++; | |
break; | |
case 0xFD: | |
p++; | |
break; | |
case 0xFE: | |
{ | |
char anh=*p; | |
p++; | |
p++; | |
if( (anh & 0xf0) == 0xa0 ) { p++; } | |
printf("alter fe\n"); | |
break; | |
} | |
} | |
} | |
}else{ | |
if( *p == 0 ) break; | |
// printf("delta[%02x]\n",*p); | |
p=CommonCalcContDuration(p,&dur); | |
// printf("delta after[%02x] ,dur=%d\n",*p,dur); | |
length += dur; | |
// printf("Length=%d\n",length); | |
} | |
} | |
for(int n=8;n<=0xe;n++){ | |
printf("0x%x %d\n", n<<4 , count[n]); | |
} | |
} | |
int main(int argc,char **argv){ | |
if( argc < 1 ) return 0; | |
FILE *fp=fopen(argv[1],"rb"); | |
if( fp == NULL ) { fprintf(stderr,"file open error %s",argv[1]);} | |
for(int n=0;n<16;n++){ | |
nl.chList[n]=calloc(sizeof(noteOnOff),10240); | |
nl.counts[n]=0; | |
} | |
int size; | |
fseek(fp,0,SEEK_END); | |
size=ftell(fp); | |
fseek(fp,0,SEEK_SET); | |
char *p=calloc(1,size); | |
fread(p,1,size,fp); | |
for(int n=0;n<size-4;n++){ | |
if( memcmp(p+n,"\xffMR",3)==0){ | |
printf("MTrack @%p\n",n); | |
MTrack(p+n); | |
} | |
if( memcmp(p+n,"YP3I",4)==0){ | |
printf("P3Track Infomaiton@%p\n",n); | |
} | |
if( memcmp(p+n,"YPTI",4)==0){ | |
printf("PTrack Infomaiton@%p\n",n); | |
parseTrack( p+n ); | |
} | |
if( memcmp(p+n,"YPXI",4)==0){ | |
printf("PTrack Extended Infomaiton@%p\n",n); | |
} | |
if( memcmp(p+n,"\xffPR",3)==0){ | |
printf("PTrack @%p\n",n); | |
PTrack(p+n); | |
} | |
} | |
for(int n=0;n<16;n++){ | |
const char* pn[12] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B" }; | |
for(int t=0;t<nl.counts[n];t++){ | |
printf("@[ch%02d]%d(%d) pitch=O%d %s length=%d\n",n,nl.chList[n][t].tickOn,t | |
,nl.chList[n][t].pitch/12,pn[nl.chList[n][t].pitch%12], | |
nl.chList[n][t].tickOff-nl.chList[n][t].tickOn); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment