/* This program converts Kurzweil files (*.krz) files to Yamaha TX16W .W wave files. Usage: krz2tx filename.krz It outputs one TX16W .W?? file for each sample found in the .krz file. K2000 files can be found at cs.uwp.edu /pub/music/kurzweil/sounds TX16W info can be found at ftp-ls7.informatik.uni-dortmund.de in /pub/tx16w. Copyright Mark Lakata (c) 1994 Absolutely freeware, do whatever the hell you want with it. */ #define SoftwareVersion ".93 August 14, 1994" #define Verbose 1 #include #ifndef SEEK_SET #define SEEK_SET 0 #endif /* this macro rounds UP to the nearest even 4 byte boundary */ #define evenlongword(x) (((x)%4)?((x)-((x)%4)+4):(x)) int PrepareDOSName(); struct WaveHeader_ { unsigned char filetype[6], /* = "LM8953", */ nulls[10], dummy_aeg[6], /* space for the AEG (never mind this) */ format, /* 0x49 = looped, 0xC9 = non-looped */ sample_rate, /* 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz */ atc_length[3], /* I'll get to this... */ rpt_length[3], unused[2]; /* set these to null, to be on the safe side */ } ; static char magic1[4] = {0, 0x06, 0x10, 0xF6}; static char magic2[4] = {0, 0x52, 0x00, 0x52}; unsigned long motorola4(x) unsigned long x; { unsigned char *b; b=(unsigned char *)&x; return b[0]*0x01000000 + b[1]*0x00010000 + b[2]*0x00000100 + b[3]*0x00000001; } unsigned short motorola2(x) unsigned short x; { unsigned char *b; b=(unsigned char *)&x; return b[0]*0x0100 + b[1]*0x0001; } main(argc,argv) int argc; char *argv[]; { char header[4]; unsigned long header_length; unsigned long header_stuff[6]; unsigned long object_type; unsigned short object_num; unsigned short object_len; unsigned short name_len; char name[80]; unsigned long rest,rest1,rest2; unsigned long *longwordbuffer; char crap[4]; int data_len,i; int maxallocated = 0x100; char FileName[256],tmpfile[256]; struct WaveHeader_ WH; long LoopLength,AttackLength,BytesWritten,w1,w2,j,Version,savepos, SampleLength,TXLoopLength,TXAttackLength; char extension[5]; int Status,filecount=1; FILE *in,*out; printf("Kurzweil K2000 sample stealer to TX16W format (%s)\n", SoftwareVersion); printf(" by Mark Lakata \n\n"); if (argc < 2) { printf("Usage: krz2tx filename.krz [dest_dir]\n\n"); exit(1); } if ((in = fopen(argv[1],"r")) == NULL) { fprintf(stderr,"Can't open file %s\n",argv[1]); exit(1); } /* beginning decoding .krz file */ fread(header,4,1,in); if (strncmp(header,"PRAM",4)!= 0 ) { fprintf(stderr,"Input file is not a Kurzweil K2000 file\n"); exit(1); } fread(&header_length,1,4,in); header_length = motorola4(header_length); /* if (Verbose) printf("header length = %8.8lx\n",header_length); */ /* this stuff is junk, for all I care about, but let's read it anyways */ fread(header_stuff,6,4,in); longwordbuffer = (unsigned long *) malloc(maxallocated*4); while(ftell(in) < header_length) { fread(&object_type,1,4,in); object_type = motorola4(object_type); /* objects all ways start with FFFF. If there has been a mistake, then stop reading objects! */ if (object_type<0xFFFF0000) break; fread(&object_num,1,2,in); object_num = motorola2(object_num); /* this is the length of the object, measured in bytes, but counting from the "object_type" offset. The object is padded so that the next object lies on a even 4-byte boundary */ fread(&object_len,1,2,in); object_len = motorola2(object_len); /* the name length is measured in bytes, counting from the "name_len" offset */ fread(&name_len,1,2,in); name_len = motorola2(name_len); if (name_len > 2) /* the name is null terminated, so sometimes strlen(name) < (name_len-2). The name is padded to even 2-byte boundaries (why?). */ fread(name,name_len-2,1,in); else { fprintf(stderr,"name is too short! = %d\n",name_len); name[0]=0; } if (Verbose) printf("Object #%8.8lx %4.4x length=%l4.4x '%s'\n", object_type,object_num,object_len,name); /* evenlongword(object_len) is the number of bytes in this object */ /* 'rest' is the number of bytes to the next object */ /* data_len is the maximum number of 4byte longwords that could fit in this object; the remaining (rest2) bytes are skipped */ rest = evenlongword(object_len)-4-name_len; rest2 = rest%4; rest1 = rest-rest2; data_len = rest1/4; if (data_len>maxallocated) { longwordbuffer = (unsigned long *)realloc(longwordbuffer,data_len*4); maxallocated = data_len; } /* ok, read in the data as long words */ if (data_len>0) { fread(longwordbuffer,data_len,4,in); for(i=0;i 0) fread(crap,rest2,1,in); /* this seems to be the indicator of a "sample" structure. The structure looks something like this: longword description --------------------------- 0 0x00010000 1 0x00080000 2 ? 3.3 byte3= original MIDI note #, 0x3C = 60 = middle C 3.[210] ?? (sample rate?) 700A00 700E00 F00000 F00000 700000 4 something to do with the sample length 5 sample start 6 sample start, raw? 7 loop start 8 sample end 9 ?? 0x00080006 0x00080012 (mono /stereo ??) 10 ?? 0x000084DE 0x000084DD 0x00007CCC 0x000063E7 0x00005893 (if [9] = 00080006) 11 ?? 0x00009999 12 ?? 0x00000000 13 ?? 0xF9C00000 end (if [9] = 00080012) 11 ?? 0xFFFF0001 12 ?? 0x00000000 13 ?? 0xF9C00000 14 ?? 0xFFFF0001 15 ?? 0x00000000 16 ?? 0xF9C00000 end */ if (longwordbuffer[0] == 0x00010000) { if (Verbose) { /* printf("Sample FOUND!\n"); printf("OK = %2x %8.8lx %8.8lx %8.8lx\n", longwordbuffer[3]/0x01000000, longwordbuffer[6],longwordbuffer[7],longwordbuffer[8]); /* /* for(i=0;i '%s'",badchars,out); */ /* remove vowels (strip all vowels after the first letter) */ j=0; for(i=outlen-1;i >=1 && outlen > 8; i--) { if (strchr(vowels,out[i]) != NULL) { for(j=i+1;j<=outlen;j++) out[j-1]=out[j]; outlen--; /* if (Verbose) printf(" -[Strip %s]-> %s ",vowels,out); */ } } /* if it still too long, just lop it off */ if (outlen>8) { out[8] = 0; outlen = 8; /* if (Verbose) printf("-[Lop]-> %s\n",out); */ } return outlen; }