home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 242.lha / GPlayer_v0.0 / GPlayer.c < prev    next >
C/C++ Source or Header  |  1989-05-09  |  10KB  |  366 lines

  1.  
  2.     /***************************************************************\
  3.     *    GPlayer V 0.0   Sonix/DMCS Score ummmm...player        *
  4.     *                                *
  5.     *                By Greg Cunningham,        *
  6.     *                    Nomad Development        *
  7.     *                                *
  8.     *    SMUS/DMCS/8SVX IFF form reader                *
  9.     *    And other stuff too.                    *
  10.     *                                *
  11.     *    Notes: I have no idea what all this does!!!        *
  12.     *    But it may contain usefull info for a music player.    *
  13.     *    Questions:                        *
  14.     *        What's the Sonix SNX1: chunk?            *
  15.     *        How do you figure out Sonix instrument forms?    *
  16.     *        And how about TRAK/UBR1 notes?            *
  17.     \***************************************************************/
  18.  
  19. #include    <Exec/Types.h>
  20. #include    <Exec/Memory.h>
  21. #include    <Proto/Dos.h>
  22. #include    <Proto/Exec.h>
  23.  
  24. #define MAKE_ID(a,b,c,d)\
  25.     (((long)(a)<<24)+((long)(b)<<16)+((long)(c)<<8)+(long)(d))
  26.  
  27. #define FORM    MAKE_ID('F','O','R','M')
  28. #define SMUS    MAKE_ID('S','M','U','S')
  29. #define SHDR    MAKE_ID('S','H','D','R')
  30. #define NAME    MAKE_ID('N','A','M','E')
  31. #define AUTH    MAKE_ID('A','U','T','H')
  32. #define Copy    MAKE_ID('S','N','X','1')
  33. #define SNX1    MAKE_ID('S','N','X','1')
  34. #define ANNO    MAKE_ID('A','N','N','O')
  35. #define INS1    MAKE_ID('I','N','S','1')
  36. #define TRAK    MAKE_ID('T','R','A','K')
  37. #define Copyrt    MAKE_ID('(','c',')',' ')
  38. /*_Sonix SampledSound_________________*/
  39. #define Samp    MAKE_ID('S','a','m','p')
  40. /*__________8SVX______________________*/
  41. #define BODY    MAKE_ID('B','O','D','Y')
  42. #define ESVX    MAKE_ID('8','S','V','X')
  43. #define VHDR    MAKE_ID('V','H','D','R')
  44. #define ATAK    MAKE_ID('A','T','A','K')
  45. #define RLSE    MAKE_ID('R','L','S','E')
  46. /*__________DMCS______________________*/
  47. #define DMCS    MAKE_ID('D','M','C','S')
  48. #define USC1    MAKE_ID('U','S','C','1')
  49. #define UBR1    MAKE_ID('U','B','R','1')
  50. #define UVLT    MAKE_ID('U','V','L','T')
  51. #define UIID    MAKE_ID('U','I','I','D')
  52.  
  53. /*_____Score_______*/
  54. #define INS1_Name    0
  55. #define INS1_MIDI    1
  56.  
  57. #define SID_FirstNote    0
  58. #define SID_LastNote    127
  59. #define SID_Rest    128
  60. #define SID_Instrument    129
  61. #define SID_TimeSig    130
  62. #define SID_KeySig    131
  63. #define SID_Dynamic    132
  64. #define SID_MIDI_Chnl    133
  65. #define SID_MIDI_Preset    134
  66. #define SID_Clef    135
  67. #define SID_Tempo    136
  68. #define SID_Mark    255
  69.  
  70. #define noteChord    (1<<7)
  71. #define noteTieOut    (1<<6)
  72. #define noteNShift    4
  73. #define noteN3        (1<<noteNShift)
  74. #define noteN5        (2<<noteNShift)
  75. #define noteN7        (3<<noteNShift)
  76. #define noteNMask    noteN7
  77. #define noteDot     (1<<3)
  78. #define noteDShift    0
  79. #define noteD1        (0<<noteDShift)
  80. #define noteD2        (1<<noteDShift)
  81. #define noteD4        (2<<noteDShift)
  82. #define noteD8        (3<<noteDShift)
  83. #define noteD16     (4<<noteDShift)
  84. #define noteD32     (5<<noteDShift)
  85. #define noteD64     (6<<noteDShift)
  86. #define noteD128    (7<<noteDShift)
  87. #define noteDMask    noteD128
  88. #define noteDurMask    0x3F
  89. #define IsChord(snote)    (((UWORD)snote)¬eChord)
  90. #define IsTied(snote)    (((UWORD)snote)¬eTieOut)
  91. #define NTuplet(snote)    ((((UWORD)snote)¬eNMask)>>noteNShift)
  92. #define IsDot(snote)    (((UWORD)snote)¬eDot)
  93. #define Division(snote) ((((UWORD)snote)¬eDMask)>>noteDShift)
  94.  
  95. #define timeNMask    0xF8
  96. #define timeNShift    3
  97. #define timeDMask    7
  98.  
  99. #define TimeNSig(sTime) ((((UWORD)sTime)&timeNMask)>>timeNShift)
  100. #define TimeDSig(sTime) (((UWORD)sTime)&timeDMask)
  101.  
  102. typedef struct{UWORD tempo; UBYTE volume,ctTrack;      }SScoreHeader;
  103. typedef struct{UBYTE iRegister,type,data1,data2,name[60]; }RefInstrument;
  104. typedef struct{UBYTE sID,data; }SEvent;
  105. typedef struct{
  106.   unsigned tone  :8,
  107.     chord     :1,
  108.     tieOut     :1,
  109.     nTuplet  :2,
  110.     dot     :1,
  111.     division :3;
  112.  }SNote;
  113.  
  114. typedef struct{
  115.  unsigned type     :8,
  116.     timeNSig :5,
  117.     timeDSig :3;
  118.  }STimeSig;
  119.  
  120.  
  121. /*_____8SVX________*/
  122. #define Unity     0x10000L
  123. #define sCmpNone    0
  124. #define sCmpFibDelta    1
  125.  
  126. typedef struct{
  127.     ULONG oneShotHiSamples,repeatHiSamples,samplesPerHiCycle;
  128.     UWORD samplesPerSec;
  129.     UBYTE ctOctave,sCompression;
  130.     LONG  volume;
  131.  }Voice8Header;
  132.  
  133. typedef struct{
  134.     UWORD duration;
  135.     LONG  dest;
  136.  }EGPoint;
  137.  
  138. /*_____IFF Chunk___*/
  139. union typekludge{char type_str[4]; long type_long;};
  140. struct ChunkHeader{union typekludge chunktype; long chunksize;};
  141.  
  142. struct FileHandle  *File=0;
  143. SScoreHeader       shdr;
  144. RefInstrument       Inst[20];
  145. Voice8Header       vhdr;
  146. struct ChunkHeader ch;
  147. UBYTE           insnum=0,traknum=0,Buf[80],InstDir[30],voicenum=0,dmcs=0;
  148. BYTE           *Trak[4];
  149. LONG           TrakSize[4];
  150.  
  151. void skipchunk(size)long size; {Seek(File,size,0);}
  152.  
  153.  
  154. readform(formsize)
  155. long     formsize;
  156. {
  157.  long  subtype;
  158.  UBYTE is_8SVX=0;
  159.  
  160.  if(!getsubtype(&subtype)) return(0);
  161.  formsize -=sizeof(subtype);
  162.  if(subtype==DMCS){    printf("FORM: DMCS\n"); dmcs=1;}
  163.  else if(subtype==SMUS) printf("FORM: SMUS\n");
  164.  else if(subtype==ESVX){printf("FORM: 8SVX\n"); is_8SVX=1;}
  165.  else return(0);
  166.  while(formsize>0){
  167.    if(!getchunkheader(&ch)) return(0);
  168.    formsize -=sizeof(ch);
  169.    switch(ch.chunktype.type_long){
  170.     case SHDR:
  171.         Read(File,&shdr,ch.chunksize);
  172.         printf("SHDR: Tempo=%d Volume=%d Tracks=%d\n",
  173.          shdr.tempo,shdr.volume,shdr.ctTrack);
  174.         break;
  175.     case VHDR:
  176.         Read(File,&vhdr,ch.chunksize);
  177.         printf("VHDR: OneShotHiSamples=%ld RepeatHiSamples=%ld\n",
  178.          vhdr.oneShotHiSamples,vhdr.repeatHiSamples);
  179.         printf("SamplesPerHiCycle=%ld SamplesPerSec=%ld Octave=%d\n",
  180.          vhdr.samplesPerHiCycle,vhdr.samplesPerSec,vhdr.ctOctave);
  181.         voicenum++; break;
  182.     case NAME:
  183.         Read(File,Buf,ch.chunksize);
  184.         Buf[ch.chunksize]=0;
  185.         printf("NAME: %s\n",Buf);
  186.         break;
  187.      case INS1:
  188.         Read(File,&Inst[insnum],ch.chunksize);
  189.         Inst[insnum].name[ch.chunksize-4]=0;
  190.         printf("INS1: Instrument[%d]=%s\n",insnum+1,Inst[insnum].name);
  191.         insnum++; break;
  192.     case TRAK:/* Sonix notes */
  193.         TrakSize[traknum]=ch.chunksize;
  194.         Trak[traknum]=(BYTE *)AllocMem(TrakSize[traknum],MEMF_CHIP);
  195.         Read(File,Trak[traknum],ch.chunksize);
  196.         printf("TRAK: Track[%d] Bytes=%ld\n",traknum+1,ch.chunksize);
  197.         traknum++; break;
  198.     case SNX1:
  199.         skipchunk(ch.chunksize); /* Important for Sonix */
  200.         printf("SNX1: Bytes=%ld\n",ch.chunksize);
  201.         break;
  202.     case AUTH:
  203.         Read(File,Buf,ch.chunksize);
  204.         Buf[ch.chunksize]=0;
  205.         printf("AUTH: %s\n",Buf);
  206.         break;
  207.     case ANNO:
  208.         skipchunk(ch.chunksize);
  209.         printf("ANNO: Beats me!\n");
  210.         break;
  211.     case ATAK:
  212.         skipchunk(ch.chunksize);
  213.         printf("ATAK: Bytes=%ld\n",ch.chunksize);
  214.         break;
  215.     case RLSE:
  216.         skipchunk(ch.chunksize);
  217.         printf("RLSE: Bytes=%ld\n",ch.chunksize);
  218.         break;
  219.     case BODY:
  220.         skipchunk(ch.chunksize);
  221.         printf("BODY: Bytes=%ld\n",ch.chunksize);
  222.         /**
  223.         if(vhdr[vh_num]->sCompression){
  224.             temp=(BYTE *)AllocMem(ch.chunksize<<1,MEMF_CHIP); 
  225.             DUnpack(buf,ch.chunksize,temp); 
  226.             FreeMem(buf,ch.chunksize); 
  227.             buf=temp;
  228.         }
  229.         **/         
  230.         break;
  231.  
  232.     case Copyrt:
  233.         Read(File,Buf,ch.chunksize);
  234.         Buf[ch.chunksize]=0;
  235.         printf("%s\n",Buf);
  236.         break;
  237.     case USC1:
  238.         skipchunk(ch.chunksize);
  239.         printf("USC1: Bytes=%ld\n",ch.chunksize);
  240.         break;
  241.     case UBR1:/* DMCS notes & text */
  242.         skipchunk(ch.chunksize);
  243.         printf("UBR1: Bytes=%ld\n",ch.chunksize);
  244.         break;
  245.     case UVLT:
  246.         skipchunk(ch.chunksize);
  247.         printf("ULVT: Bytes=%ld\n",ch.chunksize);
  248.         break;
  249.     case UIID:
  250.         Read(File,&Inst[insnum].name,ch.chunksize);
  251.         Inst[insnum].name[ch.chunksize]=0;
  252.         printf("UIID: Instrument[%d]=%s\n",insnum+1,Inst[insnum].name);
  253.         insnum++; break;
  254.  
  255.     default: skipchunk(ch.chunksize); break;
  256.    }
  257.    formsize -=ch.chunksize;
  258.    if(ch.chunksize&1){formsize--; Seek(File,1,0);}
  259.  }
  260.  return(1);
  261. }
  262.  
  263. getchunkheader(header)    struct ChunkHeader *header;
  264. {return(Read(File,header,sizeof(*header)));}
  265.  
  266. getsubtype(type)    long *type;
  267. {return(Read(File,type,sizeof(*type)));}
  268.  
  269. void FreeTraks()
  270. {
  271.  int i;
  272.  
  273.  for(i=0;i<4;i++)
  274.     if(Trak[i]) FreeMem(Trak[i],TrakSize[i]);
  275. }
  276.  
  277. void LoadInst()
  278. {
  279.  int i;
  280.  
  281.  for(i=0;i<insnum;i++){
  282.    if(!strcmp(Inst[i].name,"First Voice")) goto SKIP;
  283.    if(dmcs) sprintf(Buf,"%s%s",InstDir,Inst[i].name);
  284.    else     sprintf(Buf,"%s%s.instr",InstDir,Inst[i].name);
  285.    printf("%-36s",Buf);
  286.    if(!(File=Open(Buf,1005))){printf("\n\nFile not found: %s\n"); return;}
  287.    getchunkheader(&ch);
  288.    if(ch.chunktype.type_long==FORM) readform(ch.chunksize);
  289.    else if(ch.chunktype.type_long==Samp){
  290.     printf("SampledSound\n"); Close(File);
  291.     printf("%s%s.ss",InstDir,Inst[i].name);
  292.     if(!(File=Open(Buf,1005))){printf("\n\nFile not found: %s\n",Buf); return;}
  293.     printf("\n");
  294.    }else printf("Sonix Editor Instrument\n");
  295.    if(File) Close(File);
  296. SKIP:
  297.  }
  298. }
  299.  
  300. main(argc,argv)
  301. int argc;
  302. char **argv;
  303. {
  304.  printf("\nGPlayer V 0.0 by Greg Cunningham.\n");
  305.  printf("SMUS Score Player.\n\n");
  306.  if(argc<3){printf("Usage: GPlayer Score Instruments/\n"); goto Q;}
  307.  
  308.  if(!(File=Open(argv[1],1005))){
  309.     sprintf(Buf,"%s.smus",argv[1]);
  310.     if(!(File=Open(Buf,1005)))
  311.         {printf("File not found: %s\n",Buf); goto Q;}
  312.  }
  313.  if(!getchunkheader(&ch))      goto Q;
  314.  if(ch.chunktype.type_long!=FORM) goto Q;
  315.  if(!readform(ch.chunksize))      goto Q;
  316.  if(File) Close(File);
  317.  
  318.  strcpy(InstDir,argv[2]); LoadInst(); File=0;
  319.  
  320.  FreeTraks();
  321.  printf("\n\n Sorry, can't get audio channels!\n"); /* Fake'em out */
  322. Q:
  323.  if(File) Close(File);
  324.  exit(0); return(0);
  325. }
  326.  
  327.  
  328.  
  329. /* Unpack Fibonacci-delta encoded data from n byte source
  330.  * buffer into 2*n byte dest buffer, given initial data
  331.  * value x.  It returns the lats data value x so you can
  332.  * call it several times to incrementally decompress the data.
  333.  */
  334.  
  335. BYTE codeToDelta[16]={-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
  336.  
  337. BYTE D1Unpack(source,n,dest,x) BYTE source[],dest[]; LONG n; BYTE x;
  338. {
  339.  BYTE d;
  340.  LONG i,lim;
  341.  
  342.  lim=n<<1;
  343.  for(i=0;i<lim;++i){
  344.  /* Decode a data nibble, high nibble then low nibble */
  345.     d=source[i>>1];     /* get a pair of nibbles */
  346.     if(i&1)            /* select low or high nibble */
  347.         d&=0xf;     /* mask to get the low nibble */
  348.     else    d>>=4;        /* shift to get the high nibble */
  349.     x +=codeToDelta[d];    /* add in the decoded delta */
  350.     dest[i]=x;        /* store a 1 byte sample */
  351.  }
  352.  return(x);
  353. }
  354.  
  355. /* Unpack Fibonacci-delta encoded data from n byte
  356.  * source buffer into 2*(n-2) byte dest buffer.
  357.  * Source buffer has a pad byte, an 8-bit initial
  358.  * value, followed by n-2 bytes comprising 2*(n-2)
  359.  * 4-bit encoded samples.
  360.  */
  361.  
  362. void DUnpack(source,n,dest) BYTE source[],dest[]; LONG n;
  363. {D1Unpack(source+2,n-2,dest,source[1]);}
  364.  
  365.  
  366.