home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TopWare 18: Liquid
/
Image.iso
/
liquid
/
top1120
/
build.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-10
|
20KB
|
706 lines
; /*\
;---|*|----====< build.c >====----
;---|*|
;---|*| This program displays the contents of the selected bank patches,
;---|*| then dumps it to disk
;---|*|
;---|*| Copyright (c) 1993,1994 V.E.S.A, Inc. All Rights Reserved.
;---|*|
;---|*| VBE/AI 1.0 Specification
;---|*| February 2, 1994. 1.00 release
;---|*|
; \*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "bank.h"
#include "..\..\..\vbeai.h"
; /*\
;---|*|----====< global constants >====----
; \*/
#define TRUE -1
#define FALSE 0
FILE *fn; // pointer to the stream
FILE *ouf; // output file
BANKHEADER Header;
TIMBRE Instr;
INSHEADER InstrList[1000]; // array of 1000 instrument headers
int InstrIndex; // current index to the instrument array
int InstrChanged; // changes have occured flag
int NewFreq = 60; // percussive patch frequencies
#define INSTMAX 256
int instidx = 0;
long instruments[256] = {0};
long vaipoffset = 0; // offset to the patch chunk header
; /*\
;---|*|---====< VBE/AI OPL2 Patch Structure >====----
; \*/
typedef struct {
char opl2ksl; // ksl
char opl2freqMult; // freqMult
char opl2feedBack; // feedBack // used by operator 0 only
char opl2attack; // attack
char opl2sustLevel ;// sustLevel
char opl2sustain; // sustain
char opl2decay; // decay
char opl2release; // release
char opl2output; // output
char opl2am; // am
char opl2vib; // vib
char opl2ksr; // ksr
char opl2fm; // fm // used by operator 0 only
} opl2opr;
typedef struct {
int opl2type; // patch type
char opl2mode; // mode: 0 = melodic, 1 = percussive
char opl2percVoice; // percVoice: if mode == 1, voice number to be used
opl2opr opl2op0; // operator 0 parameters;
opl2opr opl2op1; // operator 1 parameters;
char opl2wave0; // waveform for operator 0
char opl2wave1; // waveform for operator 1
} opl2patch;
opl2patch opl2inst =
{
0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0
};
// the following structures are listed with indentation
// to indicate nesting levels of the VBE/AI patch library
RIFFhdr riffhdr = { "RIFF", 0L };
VAILhdr vailhdr = { "vail", 0L };
ZSTRhdr zstrhdr = { "ZSTR", 0L };
VAIPhdr vaiphdr = { "vaip", 0L };
VAIIhdr vaiihdr = { "vaii", 8L, 0L, 0L };
VAIDhdr vaidhdr = { "vaid", 0L };
; /*\
;---|*|----====< prototypes >====----
; \*/
void DisplayInstrument ( FILE *,int, int );
void DoExit ( int );
int GetEntry ( );
void OpenBankFile ( int, char * );
int CopyToNew ( opl2patch *, TIMBRE *, int );
void DumpInstrument ( int );
void LoadTextStrings ( );
WriteRIFFHeader ( FILE *, long );
WriteInstrument ( opl2patch *);
; /*\
;---|*|------------------------==============================---------------------
;---|*|---------------------====< Start of Execution >====---------------------
;---|*|---------------------==============================---------------------
; \*/
main(argc,argv)
int argc;
char *argv[];
{
int index;
fpos_t len;
// get the bank file name
OpenBankFile(argc,argv[1]); // will not return if bad file read
// open the target bank file
ouf = fopen ("output.bnk","wb+");
// process the list till done
WriteRIFFHeader (ouf,0);
while (1) {
if ((index = GetEntry()) <= -1)
break;
DumpInstrument(index);
}
fgetpos (ouf,&len);
WriteRIFFHeader (ouf,(long)len); // len = total file length
DoExit(0);
}
; /*\
;---|*|------------------------=======================------------------------
;---|*|------------------------====< Subroutines >====------------------------
;---|*|------------------------=======================------------------------
; \*/
; /*\
;---|*|----====< DisplayInstrument ( int, int ) >====----
;---|*|
;---|*| This displays the instrument contents, thats all...
;---|*|
;---|*| Entry Conditions:
;---|*| None
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
\*/
void DisplayInstrument(f,index,cls)
FILE *f;
int index;
int cls;
{
TIMBRE *i;
// print each element
i = &Instr;
//// fprintf (f,"Index=%-3d Instrument Name \"%s\" Offset=%-3d\n",index+1,InstrList[index].name,InstrList[index].index);
//// fprintf (f,"============================================\n");
//// fprintf (f," 1)mode : %2u\n",i->mode );
//// fprintf (f," 2)Voice : %2u\n",i->percVoice );
//// fprintf (f,"==== OPERATOR 0 ==== ==== OPERATOR 1 ====\n");
//// fprintf (f," 3) ksl = %4u 17) ksl = %4u \n",i->op0.ksl , i->op1.ksl );
//// fprintf (f," 4) freqMult = %4u 18) freqMult = %4u \n",i->op0.freqMult , i->op1.freqMult );
//// fprintf (f," 5) feedBack = %4u 19) N/U (PAN) %4u \n",i->op0.feedBack , i->op1.feedBack );
//// fprintf (f," 6) attack = %4u 20) attack = %4u \n",i->op0.attack , i->op1.attack );
//// fprintf (f," 7) sustLevel= %4u 21) sustLevel= %4u \n",i->op0.sustLevel, i->op1.sustLevel);
//// fprintf (f," 8) sustain = %4u 22) sustain = %4u \n",i->op0.sustain , i->op1.sustain );
//// fprintf (f," 10) decay = %4u 23) decay = %4u \n",i->op0.decay , i->op1.decay );
//// fprintf (f," 11) release = %4u 24) release = %4u \n",i->op0.release , i->op1.release );
//// fprintf (f," 12) output = %4u 25) output = %4u \n",i->op0.output , i->op1.output );
//// fprintf (f," 13) am = %4u 26) am = %4u \n",i->op0.am , i->op1.am );
//// fprintf (f," 14) vib = %4u 27) vib = %4u \n",i->op0.vib , i->op1.vib );
//// fprintf (f," 15) ksr = %4u 28) ksr = %4u \n",i->op0.ksr , i->op1.ksr );
//// fprintf (f," 16) fm = %4u 29) N/U %4u \n",i->op0.fm , i->op1.fm );
//// fprintf (f," 30)op0 wave : %2u\n", i->wave0 );
//// fprintf (f," 31)op1 wave : %2u\n", i->wave1 );
////
}
; /*\
;---|*|----====< DisplayNewInstrument ( int, int ) >====----
;---|*|
;---|*| This displays the instrument contents, thats all...
;---|*|
;---|*| Entry Conditions:
;---|*| None
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
\*/
void DisplayNewInstrument(f,index,d)
FILE *f;
int index;
opl2patch *d;
{
// print each element
//// fprintf (f,"============================================\n");
//// fprintf (f," 1)mode : %2u\n",d->opl2mode );
//// fprintf (f," 2)Voice : %2u\n",d->opl2percVoice );
//// fprintf (f,"==== OPERATOR 0 ==== ==== OPERATOR 1 ====\n");
//// fprintf (f," 3) ksl = %4u 17) ksl = %4u \n",d->opl2op0.opl2ksl , d->opl2op1.opl2ksl );
//// fprintf (f," 4) freqMult = %4u 18) freqMult = %4u \n",d->opl2op0.opl2freqMult , d->opl2op1.opl2freqMult );
//// fprintf (f," 5) feedBack = %4u 19) N/U (PAN) %4u \n",d->opl2op0.opl2feedBack , d->opl2op1.opl2feedBack );
//// fprintf (f," 6) attack = %4u 20) attack = %4u \n",d->opl2op0.opl2attack , d->opl2op1.opl2attack );
//// fprintf (f," 7) sustLevel= %4u 21) sustLevel= %4u \n",d->opl2op0.opl2sustLevel, d->opl2op1.opl2sustLevel);
//// fprintf (f," 8) sustain = %4u 22) sustain = %4u \n",d->opl2op0.opl2sustain , d->opl2op1.opl2sustain );
//// fprintf (f," 10) decay = %4u 23) decay = %4u \n",d->opl2op0.opl2decay , d->opl2op1.opl2decay );
//// fprintf (f," 11) release = %4u 24) release = %4u \n",d->opl2op0.opl2release , d->opl2op1.opl2release );
//// fprintf (f," 12) output = %4u 25) output = %4u \n",d->opl2op0.opl2output , d->opl2op1.opl2output );
//// fprintf (f," 13) am = %4u 26) am = %4u \n",d->opl2op0.opl2am , d->opl2op1.opl2am );
//// fprintf (f," 14) vib = %4u 27) vib = %4u \n",d->opl2op0.opl2vib , d->opl2op1.opl2vib );
//// fprintf (f," 15) ksr = %4u 28) ksr = %4u \n",d->opl2op0.opl2ksr , d->opl2op1.opl2ksr );
//// fprintf (f," 16) fm = %4u 29) N/U %4u \n",d->opl2op0.opl2fm , d->opl2op1.opl2fm );
//// fprintf (f," 30)op0 wave : %2u\n", d->opl2wave0 );
//// fprintf (f," 31)op1 wave : %2u\n", d->opl2wave1 );
////
}
; /*\
;---|*|----====< CopyToNew >====----
;---|*|
;---|*| Copy the instrument to the VBE/AI format
;---|*|
;---|*| Entry Conditions:
;---|*| None
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
\*/
CopyToNew (d,s,p)
opl2patch *d;
TIMBRE *s;
int p; // patch #
{
// place the specified frequency in the old percussive field
d->opl2percVoice = NewFreq | 0x80;
if (s->mode)
printf ("\aThere is a non-melodic mode specified in patch #%d!\n",p);
d->opl2type = MIDI_PATCH_OPL2;
d->opl2mode = s->mode;
d->opl2op0.opl2ksl = s->op0.ksl;
d->opl2op0.opl2freqMult = s->op0.freqMult;
d->opl2op0.opl2feedBack = s->op0.feedBack;
d->opl2op0.opl2attack = s->op0.attack;
d->opl2op0.opl2sustLevel= s->op0.sustLevel;
d->opl2op0.opl2sustain = s->op0.sustain;
d->opl2op0.opl2decay = s->op0.decay;
d->opl2op0.opl2release = s->op0.release;
d->opl2op0.opl2output = s->op0.output;
d->opl2op0.opl2am = s->op0.am;
d->opl2op0.opl2vib = s->op0.vib;
d->opl2op0.opl2ksr = s->op0.ksr;
d->opl2op0.opl2fm = s->op0.fm;
d->opl2op1.opl2ksl = s->op1.ksl;
d->opl2op1.opl2freqMult = s->op1.freqMult;
d->opl2op1.opl2feedBack = s->op1.feedBack;
d->opl2op1.opl2attack = s->op1.attack;
d->opl2op1.opl2sustLevel= s->op1.sustLevel;
d->opl2op1.opl2sustain = s->op1.sustain;
d->opl2op1.opl2decay = s->op1.decay;
d->opl2op1.opl2release = s->op1.release;
d->opl2op1.opl2output = s->op1.output;
d->opl2op1.opl2am = s->op1.am;
d->opl2op1.opl2vib = s->op1.vib;
d->opl2op1.opl2ksr = s->op1.ksr;
d->opl2op1.opl2fm = s->op1.fm;
d->opl2wave0 = s->wave0;
d->opl2wave1 = s->wave1;
}
; /*\
;---|*|----====< DoExit(int) >====----
;---|*|
;---|*| Shutdown and exit to DOS
;---|*|
;---|*| Entry Conditions:
;---|*| int = completion code
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
; \*/
void DoExit(cc)
int cc;
{
// if the instrument bank is opened, close to save all...
if (fn)
fclose (fn);
if (ouf)
fclose (ouf);
// bye...
exit(cc);
}
; /*\
;---|*|----====< DumpInstrument() >====----
;---|*|
;---|*| This displays the instrument contents, then Dumps the
;---|*| operator to the output file.
;---|*|
;---|*| Entry Conditions:
;---|*| int = the index of the instrument
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
; \*/
void DumpInstrument(index)
int index;
{
long pos;
char buff[11];
// position the file pointer to that record
pos = (InstrList[index].index * sizeof(TIMBRE)) + Header.offsetTimbre;
fseek ( fn, pos, SEEK_SET );
// read in the instrument record
if (fread(&Instr,sizeof(TIMBRE),1,fn) != 1) {
printf ("Cannot read that instrument!\n");
return;
}
if (Instr.mode)
printf ("===============Percussive mode patch!=================\n");
// display and edit, display and edit, display and edit...
DisplayInstrument(stdout,index,1);
CopyToNew (&opl2inst,&Instr,index);
DisplayNewInstrument(stdout,index,&opl2inst);
WriteInstrument(&opl2inst);
}
; /*\
;---|*|----====< GetEntry >====----
;---|*|
;---|*| Get the next bank index #
;---|*|
;---|*| Entry Conditions:
;---|*| none
;---|*|
;---|*| Exit Conditions:
;---|*| -1 if done, else 0+ for the index
;---|*|
; \*/
int GetEntry()
{
char buff[100];
int result;
while (1) {
if (feof(stdin)) {
printf ("end of input\n");
return(-1);
}
printf ("\nEnter an Index, (0 to exit, [ENTER] for next page) :");
fgets(buff,99,stdin);
printf ("%s\n",buff);
if (isdigit(buff[0]))
if (sscanf(buff,"%d %d",&result,&NewFreq) == 2)
return (--result);
}
}
; /*\
;---|*|----====< OpenBankFile >====----
;---|*|
;---|*| Open the bank file, and read in the header block.
;---|*|
;---|*| Entry Conditions:
;---|*|
;---|*| char *f is the possible file name
;---|*|
;---|*| Exit Conditions:
;---|*| if in error, the routine returns directly to DOS.
;---|*|
; \*/
void OpenBankFile (argc,f)
int argc;
char *f;
{
INSHEADER Iname; // current instrment header
// if no arguments, just give helps
if (argc < 2) {
printf ("\nBANK -- By Media Vision, Inc.\n\n");
printf ("To Use: DOS>BANK [FILENAME.BNK] [CREDITS]\n\n",f);
exit(0);
}
// attemp the open
if ((fn = fopen (f,"r+b")) == 0) {
printf ("Cannot open the bank file: \"%s\"\n",f);
DoExit (-1);
}
// read in the header
if (fread(&Header,sizeof(BANKHEADER),1,fn) != 1) {
printf ("Cannot read the bank's header record!");
DoExit (-1);
}
// exit if no index entries are used
if (Header.nrDefined == 0) {
printf ("There are no valid entries in this bank!");
DoExit (-1);
}
// load the instrument index into memory starting with the first record
InstrIndex = 0;
// read each header till done...
do {
if (fread(&Iname,sizeof(INSHEADER),1,fn) != 1) {
printf ("Unexpected end of file read the index!\n");
DoExit(-1);
}
// save only if the data is valid
if (Iname.used) {
// save the instrument index data
memcpy
(
(void *)&InstrList[InstrIndex++],
(void *)&Iname,
sizeof (INSHEADER)
);
}
} while (InstrIndex != Header.nrDefined);
// InstrIndex will point to the last good entry
InstrIndex--;
}
; /*\
;---|*|----====< WriteInstrument >====----
;---|*|
;---|*| Write the instrument out to disk
;---|*|
;---|*| Entry Conditions:
;---|*| none
;---|*|
;---|*| Exit Conditions:
;---|*| none
;---|*|
; \*/
WriteInstrument(d)
opl2patch *d;
{
int n;
fpos_t p;
char *s = (char *) &vaidhdr;
// build the header
vaidhdr.vaidlen = sizeof(opl2patch);
// if we get the file position, save it in the table
if (!fgetpos (ouf,&p))
instruments[instidx++] = (long)p - vaipoffset;
// write the patch header to disk
for (n=sizeof(VAIDhdr);n;n--)
fputc (*s++,ouf);
// write the patch to disk
s = (char *)d;
for (n=sizeof(opl2patch);n;n--)
fputc (*s++,ouf);
}
; /*\
;---|*|----====< WriteRIFFHeader >====----
;---|*|
;---|*| Write the instrument out to disk
;---|*|
;---|*| Entry Conditions:
;---|*| none
;---|*|
;---|*| Exit Conditions:
;---|*| none
;---|*|
; \*/
WriteRIFFHeader (ouf,len)
FILE *ouf;
long len;
{
char *s;
int n,x;
fpos_t p;
long l;
// start at the beginning
fsetpos (ouf,0);
// write the "RIFF" header
len -= sizeof (RIFFhdr); // remove this length
s = (char *) &riffhdr;
riffhdr.rcount = len;
for (n=sizeof(RIFFhdr);n;n--)
fputc (*s++,ouf);
// write the "vail" header
len -= sizeof (VAILhdr); // remove this length
s = (char *) &vailhdr;
vailhdr.pcount = len;
for (n=sizeof(VAILhdr);n;n--)
fputc (*s++,ouf);
// write the "ZSTR" headers
LoadTextStrings();
// write the "vaip" header
if (!fgetpos (ouf,&p))
vaipoffset = (long)p;
vaiphdr.vaiplen = (instidx * sizeof(VAIIhdr))
+ (instidx * sizeof(VAIDhdr))
+ (instidx * sizeof(opl2patch));
s = (char *) &vaiphdr;
for (n=sizeof(VAIPhdr);n;n--)
fputc (*s++,ouf);
// write the "vaii" headers
for (x=0;x<INSTMAX;x++) {
// move the patch offset into the array
vaiihdr.poffset = instruments[x];
// move the patch length into the structure
vaiihdr.vaidln = sizeof (opl2patch);
// write out the array
s = (char *) &vaiihdr;
for (n=sizeof(VAIIhdr);n;n--)
fputc (*s++,ouf);
}
}
; /*\
;---|*|----====< LoadTextSTrings >====----
;---|*|
;---|*| Give credit for the bank file
;---|*|
;---|*| Entry Conditions:
;---|*| none
;---|*|
;---|*| Exit Conditions:
;---|*| none
;---|*|
; \*/
void LoadTextStrings()
{
FILE *tfil;
char str[100],*s;
int n;
ZSTRhdr thd;
thd.type[0] = 'Z';
thd.type[1] = 'S';
thd.type[2] = 'T';
thd.type[3] = 'R';
if ((tfil = fopen ("credits","r")) ==0)
return;
while (fgets(str,99,tfil)) {
s = str;
for (n=0;n<99;n++) {
if (*s == 0x0A)
*s == 0;
if (*s == 0x0D)
*s == 0;
if (!*s++)
break;
}
if ((thd.tlen = n) == 0)
break;
s = (char *)&thd;
for (n=8;n;n--)
fputc (*s++,ouf);
s = str;
for (n=thd.tlen;n;n--)
fputc (*s++,ouf);
}
fclose (tfil);
}
; /*\
;---|*| end of build.c
; \*/