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 >
Wrap
C/C++ Source or Header
|
1989-05-09
|
10KB
|
366 lines
/***************************************************************\
* GPlayer V 0.0 Sonix/DMCS Score ummmm...player *
* *
* By Greg Cunningham, *
* Nomad Development *
* *
* SMUS/DMCS/8SVX IFF form reader *
* And other stuff too. *
* *
* Notes: I have no idea what all this does!!! *
* But it may contain usefull info for a music player. *
* Questions: *
* What's the Sonix SNX1: chunk? *
* How do you figure out Sonix instrument forms? *
* And how about TRAK/UBR1 notes? *
\***************************************************************/
#include <Exec/Types.h>
#include <Exec/Memory.h>
#include <Proto/Dos.h>
#include <Proto/Exec.h>
#define MAKE_ID(a,b,c,d)\
(((long)(a)<<24)+((long)(b)<<16)+((long)(c)<<8)+(long)(d))
#define FORM MAKE_ID('F','O','R','M')
#define SMUS MAKE_ID('S','M','U','S')
#define SHDR MAKE_ID('S','H','D','R')
#define NAME MAKE_ID('N','A','M','E')
#define AUTH MAKE_ID('A','U','T','H')
#define Copy MAKE_ID('S','N','X','1')
#define SNX1 MAKE_ID('S','N','X','1')
#define ANNO MAKE_ID('A','N','N','O')
#define INS1 MAKE_ID('I','N','S','1')
#define TRAK MAKE_ID('T','R','A','K')
#define Copyrt MAKE_ID('(','c',')',' ')
/*_Sonix SampledSound_________________*/
#define Samp MAKE_ID('S','a','m','p')
/*__________8SVX______________________*/
#define BODY MAKE_ID('B','O','D','Y')
#define ESVX MAKE_ID('8','S','V','X')
#define VHDR MAKE_ID('V','H','D','R')
#define ATAK MAKE_ID('A','T','A','K')
#define RLSE MAKE_ID('R','L','S','E')
/*__________DMCS______________________*/
#define DMCS MAKE_ID('D','M','C','S')
#define USC1 MAKE_ID('U','S','C','1')
#define UBR1 MAKE_ID('U','B','R','1')
#define UVLT MAKE_ID('U','V','L','T')
#define UIID MAKE_ID('U','I','I','D')
/*_____Score_______*/
#define INS1_Name 0
#define INS1_MIDI 1
#define SID_FirstNote 0
#define SID_LastNote 127
#define SID_Rest 128
#define SID_Instrument 129
#define SID_TimeSig 130
#define SID_KeySig 131
#define SID_Dynamic 132
#define SID_MIDI_Chnl 133
#define SID_MIDI_Preset 134
#define SID_Clef 135
#define SID_Tempo 136
#define SID_Mark 255
#define noteChord (1<<7)
#define noteTieOut (1<<6)
#define noteNShift 4
#define noteN3 (1<<noteNShift)
#define noteN5 (2<<noteNShift)
#define noteN7 (3<<noteNShift)
#define noteNMask noteN7
#define noteDot (1<<3)
#define noteDShift 0
#define noteD1 (0<<noteDShift)
#define noteD2 (1<<noteDShift)
#define noteD4 (2<<noteDShift)
#define noteD8 (3<<noteDShift)
#define noteD16 (4<<noteDShift)
#define noteD32 (5<<noteDShift)
#define noteD64 (6<<noteDShift)
#define noteD128 (7<<noteDShift)
#define noteDMask noteD128
#define noteDurMask 0x3F
#define IsChord(snote) (((UWORD)snote)¬eChord)
#define IsTied(snote) (((UWORD)snote)¬eTieOut)
#define NTuplet(snote) ((((UWORD)snote)¬eNMask)>>noteNShift)
#define IsDot(snote) (((UWORD)snote)¬eDot)
#define Division(snote) ((((UWORD)snote)¬eDMask)>>noteDShift)
#define timeNMask 0xF8
#define timeNShift 3
#define timeDMask 7
#define TimeNSig(sTime) ((((UWORD)sTime)&timeNMask)>>timeNShift)
#define TimeDSig(sTime) (((UWORD)sTime)&timeDMask)
typedef struct{UWORD tempo; UBYTE volume,ctTrack; }SScoreHeader;
typedef struct{UBYTE iRegister,type,data1,data2,name[60]; }RefInstrument;
typedef struct{UBYTE sID,data; }SEvent;
typedef struct{
unsigned tone :8,
chord :1,
tieOut :1,
nTuplet :2,
dot :1,
division :3;
}SNote;
typedef struct{
unsigned type :8,
timeNSig :5,
timeDSig :3;
}STimeSig;
/*_____8SVX________*/
#define Unity 0x10000L
#define sCmpNone 0
#define sCmpFibDelta 1
typedef struct{
ULONG oneShotHiSamples,repeatHiSamples,samplesPerHiCycle;
UWORD samplesPerSec;
UBYTE ctOctave,sCompression;
LONG volume;
}Voice8Header;
typedef struct{
UWORD duration;
LONG dest;
}EGPoint;
/*_____IFF Chunk___*/
union typekludge{char type_str[4]; long type_long;};
struct ChunkHeader{union typekludge chunktype; long chunksize;};
struct FileHandle *File=0;
SScoreHeader shdr;
RefInstrument Inst[20];
Voice8Header vhdr;
struct ChunkHeader ch;
UBYTE insnum=0,traknum=0,Buf[80],InstDir[30],voicenum=0,dmcs=0;
BYTE *Trak[4];
LONG TrakSize[4];
void skipchunk(size)long size; {Seek(File,size,0);}
readform(formsize)
long formsize;
{
long subtype;
UBYTE is_8SVX=0;
if(!getsubtype(&subtype)) return(0);
formsize -=sizeof(subtype);
if(subtype==DMCS){ printf("FORM: DMCS\n"); dmcs=1;}
else if(subtype==SMUS) printf("FORM: SMUS\n");
else if(subtype==ESVX){printf("FORM: 8SVX\n"); is_8SVX=1;}
else return(0);
while(formsize>0){
if(!getchunkheader(&ch)) return(0);
formsize -=sizeof(ch);
switch(ch.chunktype.type_long){
case SHDR:
Read(File,&shdr,ch.chunksize);
printf("SHDR: Tempo=%d Volume=%d Tracks=%d\n",
shdr.tempo,shdr.volume,shdr.ctTrack);
break;
case VHDR:
Read(File,&vhdr,ch.chunksize);
printf("VHDR: OneShotHiSamples=%ld RepeatHiSamples=%ld\n",
vhdr.oneShotHiSamples,vhdr.repeatHiSamples);
printf("SamplesPerHiCycle=%ld SamplesPerSec=%ld Octave=%d\n",
vhdr.samplesPerHiCycle,vhdr.samplesPerSec,vhdr.ctOctave);
voicenum++; break;
case NAME:
Read(File,Buf,ch.chunksize);
Buf[ch.chunksize]=0;
printf("NAME: %s\n",Buf);
break;
case INS1:
Read(File,&Inst[insnum],ch.chunksize);
Inst[insnum].name[ch.chunksize-4]=0;
printf("INS1: Instrument[%d]=%s\n",insnum+1,Inst[insnum].name);
insnum++; break;
case TRAK:/* Sonix notes */
TrakSize[traknum]=ch.chunksize;
Trak[traknum]=(BYTE *)AllocMem(TrakSize[traknum],MEMF_CHIP);
Read(File,Trak[traknum],ch.chunksize);
printf("TRAK: Track[%d] Bytes=%ld\n",traknum+1,ch.chunksize);
traknum++; break;
case SNX1:
skipchunk(ch.chunksize); /* Important for Sonix */
printf("SNX1: Bytes=%ld\n",ch.chunksize);
break;
case AUTH:
Read(File,Buf,ch.chunksize);
Buf[ch.chunksize]=0;
printf("AUTH: %s\n",Buf);
break;
case ANNO:
skipchunk(ch.chunksize);
printf("ANNO: Beats me!\n");
break;
case ATAK:
skipchunk(ch.chunksize);
printf("ATAK: Bytes=%ld\n",ch.chunksize);
break;
case RLSE:
skipchunk(ch.chunksize);
printf("RLSE: Bytes=%ld\n",ch.chunksize);
break;
case BODY:
skipchunk(ch.chunksize);
printf("BODY: Bytes=%ld\n",ch.chunksize);
/**
if(vhdr[vh_num]->sCompression){
temp=(BYTE *)AllocMem(ch.chunksize<<1,MEMF_CHIP);
DUnpack(buf,ch.chunksize,temp);
FreeMem(buf,ch.chunksize);
buf=temp;
}
**/
break;
case Copyrt:
Read(File,Buf,ch.chunksize);
Buf[ch.chunksize]=0;
printf("%s\n",Buf);
break;
case USC1:
skipchunk(ch.chunksize);
printf("USC1: Bytes=%ld\n",ch.chunksize);
break;
case UBR1:/* DMCS notes & text */
skipchunk(ch.chunksize);
printf("UBR1: Bytes=%ld\n",ch.chunksize);
break;
case UVLT:
skipchunk(ch.chunksize);
printf("ULVT: Bytes=%ld\n",ch.chunksize);
break;
case UIID:
Read(File,&Inst[insnum].name,ch.chunksize);
Inst[insnum].name[ch.chunksize]=0;
printf("UIID: Instrument[%d]=%s\n",insnum+1,Inst[insnum].name);
insnum++; break;
default: skipchunk(ch.chunksize); break;
}
formsize -=ch.chunksize;
if(ch.chunksize&1){formsize--; Seek(File,1,0);}
}
return(1);
}
getchunkheader(header) struct ChunkHeader *header;
{return(Read(File,header,sizeof(*header)));}
getsubtype(type) long *type;
{return(Read(File,type,sizeof(*type)));}
void FreeTraks()
{
int i;
for(i=0;i<4;i++)
if(Trak[i]) FreeMem(Trak[i],TrakSize[i]);
}
void LoadInst()
{
int i;
for(i=0;i<insnum;i++){
if(!strcmp(Inst[i].name,"First Voice")) goto SKIP;
if(dmcs) sprintf(Buf,"%s%s",InstDir,Inst[i].name);
else sprintf(Buf,"%s%s.instr",InstDir,Inst[i].name);
printf("%-36s",Buf);
if(!(File=Open(Buf,1005))){printf("\n\nFile not found: %s\n"); return;}
getchunkheader(&ch);
if(ch.chunktype.type_long==FORM) readform(ch.chunksize);
else if(ch.chunktype.type_long==Samp){
printf("SampledSound\n"); Close(File);
printf("%s%s.ss",InstDir,Inst[i].name);
if(!(File=Open(Buf,1005))){printf("\n\nFile not found: %s\n",Buf); return;}
printf("\n");
}else printf("Sonix Editor Instrument\n");
if(File) Close(File);
SKIP:
}
}
main(argc,argv)
int argc;
char **argv;
{
printf("\n
GPlayer V 0.0 by Greg Cunningham.
\n");
printf("SMUS Score Player.\n\n");
if(argc<3){printf("Usage: GPlayer Score Instruments/\n"); goto Q;}
if(!(File=Open(argv[1],1005))){
sprintf(Buf,"%s.smus",argv[1]);
if(!(File=Open(Buf,1005)))
{printf("File not found: %s\n",Buf); goto Q;}
}
if(!getchunkheader(&ch)) goto Q;
if(ch.chunktype.type_long!=FORM) goto Q;
if(!readform(ch.chunksize)) goto Q;
if(File) Close(File);
strcpy(InstDir,argv[2]); LoadInst(); File=0;
FreeTraks();
printf("\n\n Sorry, can't get audio channels!\n"); /* Fake'em out */
Q:
if(File) Close(File);
exit(0); return(0);
}
/* Unpack Fibonacci-delta encoded data from n byte source
* buffer into 2*n byte dest buffer, given initial data
* value x. It returns the lats data value x so you can
* call it several times to incrementally decompress the data.
*/
BYTE codeToDelta[16]={-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
BYTE D1Unpack(source,n,dest,x) BYTE source[],dest[]; LONG n; BYTE x;
{
BYTE d;
LONG i,lim;
lim=n<<1;
for(i=0;i<lim;++i){
/* Decode a data nibble, high nibble then low nibble */
d=source[i>>1]; /* get a pair of nibbles */
if(i&1) /* select low or high nibble */
d&=0xf; /* mask to get the low nibble */
else d>>=4; /* shift to get the high nibble */
x +=codeToDelta[d]; /* add in the decoded delta */
dest[i]=x; /* store a 1 byte sample */
}
return(x);
}
/* Unpack Fibonacci-delta encoded data from n byte
* source buffer into 2*(n-2) byte dest buffer.
* Source buffer has a pad byte, an 8-bit initial
* value, followed by n-2 bytes comprising 2*(n-2)
* 4-bit encoded samples.
*/
void DUnpack(source,n,dest) BYTE source[],dest[]; LONG n;
{D1Unpack(source+2,n-2,dest,source[1]);}