Skip to content

Instantly share code, notes, and snippets.

@bakueikozo
Last active March 4, 2024 05:25
Show Gist options
  • Save bakueikozo/5a9b3303a27322f848acadc53c6396e2 to your computer and use it in GitHub Desktop.
Save bakueikozo/5a9b3303a27322f848acadc53c6396e2 to your computer and use it in GitHub Desktop.
#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