home *** CD-ROM | disk | FTP | other *** search
- /**
- ADLIB.C, low level sound driver V1.03
- ===== To be used with OUTCHIP.ASM file. =====
-
- Copyright Ad Lib Inc, 1988, 1989
-
- 1988/06/22, Dale Glowinski, Marc Savary, Ad Lib Inc.
- 1989/04/20, Marc savary.
-
-
-
-
- The following routines are public (see each routine for further
- documentation):
-
- SoundColdInit( port)
- SoundWarmInit()
- SetMode( mode)
- Set3812( state)
- SetPitchRange( pR)
- SetGParam( amD, vibD, nSel)
- SetVoiceTimbre( voice, paramArray)
- SetVoiceVolume( voice, volume)
- SetVoicePitch( voice, pitchBend)
- NoteOn( voice, pitch)
- NoteOff( voice)
-
- **/
-
- #include "adlib.h"
-
- /*
- In percussive mode, the last 4 voices ( SD TOM HH CYMB) are created
- using melodic voices 7 & 8. A noise generator use channels 7 & 8
- frequency information for creating rhythm instruments. Best result
- are obtained by setting TOM two octaves below mid C and SD 7 half-tones
- above TOM.
- In this implementation, only the TOM pitch may vary, with the SD always
- set 7 half-tones above.
- */
-
- #define TOM_PITCH 24 /* best frequency, in range of 0 to 95 */
- #define TOM_TO_SD 7 /* 7 half-tones between voice 7 & 8 */
- #define SD_PITCH (TOM_PITCH + TOM_TO_SD)
-
- #define NR_STEP_PITCH 25 /* 25 steps within a half-tone for pitch bend */
-
- #define GetLocPrm( slot, prm)( (unsigned)paramSlot[ slot][ prm])
- #define HighByte( word) ( ((char *)(&word))[ 1]) /* 80x86-8 only .. */
- #define RhythmMode() (percussion)
-
- typedef char SLOT_PARAM;
-
-
- /*
- -----------------------------------------------------------------
- */
-
- unsigned genAddr; /* address of sound chip */
-
- static char percBits; /* control bits of percussive voices */
- static char percMasks[] = {
- 0x10, 0x08, 0x04, 0x02, 0x01
- };
-
- static char notePitch[ 11]; /* pitch of last note-on of each voice */
- static char voiceKeyOn[ 11]; /* state of keyOn bit of each voice */
-
- static char noteDIV12[ 96]; /* table of (0..95) DIV 12 */
- static char noteMOD12[ 96]; /* table of (0..95) MOD 12 */
-
- static char slotRelVolume[ 18]; /* relative volume of slots */
-
-
- /* definition of the ELECTRIC-PIANO voice (opr0 & opr1) */
- static char pianoParamsOp0[ nbLocParam] = {
- 1, 1, 3, 15, 5, 0, 1, 3, 15, 0, 0, 0, 1, 0 };
- static char pianoParamsOp1[ nbLocParam] = {
- 0, 1, 1, 15, 7, 0, 2, 4, 0, 0, 0, 1, 0, 0 };
-
- /* definition of default percussive voices: */
- static char bdOpr0[] = { 0, 0, 0, 10, 4, 0, 8, 12, 11, 0, 0, 0, 1, 0 };
- static char bdOpr1[] = { 0, 0, 0, 13, 4, 0, 6, 15, 0, 0, 0, 0, 1, 0 };
- static char sdOpr[] = { 0, 12, 0, 15, 11, 0, 8, 5, 0, 0, 0, 0, 0, 0 };
- static char tomOpr[] = { 0, 4, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0 };
- static char cymbOpr[] ={ 0, 1, 0, 15, 11, 0, 5, 5, 0, 0, 0, 0, 0, 0 };
- static char hhOpr[] = { 0, 1, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0 };
-
- static SLOT_PARAM paramSlot[ 18][ nbLocParam]; /* all the parameters of slots... */
-
- static char amDepth; /* chip global parameters .. */
- static char vibDepth; /* ... */
- static char noteSel; /* ... */
- static char percussion; /* percussion mode parameter */
-
- /* Slot numbers as a function of the voice and the operator.
- ( melodic only)
- */
- char slotVoice[] [ 2] = {
- {0, 3}, /* voix 0 */
- {1, 4}, /* 1 */
- {2, 5}, /* 2 */
- {6, 9}, /* 3 */
- {7, 10}, /* 4 */
- {8, 11}, /* 5 */
- {12, 15}, /* 6 */
- {13, 16}, /* 7 */
- {14, 17} /* 8 */
- };
-
-
- /* Slot numbers for the percussive voices.
- 0 indicates that there is only one slot.
- */
- char slotPerc[] [ 2] = {
- {12, 15}, /* Bass Drum: slot 12 et 15 */
- {16, 0}, /* SD: slot 16 */
- {14, 0}, /* TOM: slot 14 */
- {17, 0}, /* TOP-CYM: slot 17 */
- {13, 0} /* HH: slot 13 */
- };
-
- /*
- This table gives the offset of each slot within the chip.
- offset = fn( slot)
- */
- static char offsetSlot[] = {
- 0, 1, 2, 3, 4, 5,
- 8, 9, 10, 11, 12, 13,
- 16, 17, 18, 19, 20, 21
- };
-
-
- /* This table indicates if the slot is a modulator (0) or a carrier (1).
- opr = fn( slot)
- */
- static char operSlot[] = {
- 0, 0, 0, /* 1 2 3 */
- 1, 1, 1, /* 4 5 6 */
- 0, 0, 0, /* 7 8 9 */
- 1, 1, 1, /* 10 11 12 */
- 0, 0, 0, /* 13 14 15 */
- 1, 1, 1, /* 16 17 18 */
- };
-
- /* This table gives the voice number associated with each slot.
- (melodic mode only)
- voice = fn( slot)
- */
- static char voiceSlot[] = {
- 0, 1, 2,
- 0, 1, 2,
- 3, 4, 5,
- 3, 4, 5,
- 6, 7, 8,
- 6, 7, 8,
- };
-
-
- static unsigned fNumNotes[ NR_STEP_PITCH] [ 12];
- static int halfToneOffset[ 11];
- static unsigned * fNumFreqPtr[ 11];
- static int pitchRange; /* pitch variation, half-tone [+1,+12] */
- static int pitchRangeStep; /* == pitchRange * NR_STEP_PITCH */
- static int modeWaveSel; /* != 0 if used with the 'wave-select' parameters */
-
-
- extern SndOutput(); /* in file OUTCHIP.ASM */
-
-
-
- /*
- ----------------------------------------------------------
- */
-
-
-
-
- /*
- Must be called for start-up initialisation.
-
- Return 0 if harware not found.
- */
- int SoundColdInit( port)
- unsigned port; /* io port address of sound board (0x388) */
- {
- int hardware;
-
- genAddr = port;
- hardware = BoardInstalled();
- SoundWarmInit();
- return hardware;
- } /* SoundColdInit() */
-
-
- /*
- -----------------------------------------------
- Initialize the chip in melodic mode (mode == 0),
- set all 9 voices to electric-piano timbres,
- set the 3 global parameters to zero,
- set the pitch bend range to 1 half-tone,
- set the pitch bend of each voice to 0x2000 (no detune),
- set the volume of each voice to maximum level,
- and enable the wave-select parameter.
- -----------------------------------------------
- */
- SoundWarmInit()
- {
- int i;
-
- InitSlotVolume();
- InitFNums();
- SetMode( 0); /* melodic mode */
- SetGParam( 0, 0, 0); /* init global parameters */
- for( i = 0 ; i < 9; i++)
- SoundChut( i);
- SetPitchRange( 1); /* default pitch range is 1 half-tone */
- Set3812( 1);
- } /* SoundWarmInit() */
-
-
-
- /*
- ---------------------------------------------
- Put the chip in melodic mode (mode == 0),
- or in percussive mode ( mode != 0).
-
- If the melodic mode is chosen, all voices are
- set to electric-piano, else the first 5 are set
- to electric-piano, and the percussion voices
- to their default timbres.
- ---------------------------------------------
- */
- SetMode( mode)
- int mode;
- {
-
- if( mode){
- SoundChut( BD);
- SoundChut( SD);
- SoundChut( TOM);
-
- /* set the frequency for the last 4 percussion voices: */
- SetFreq( TOM, TOM_PITCH, 0);
- SetFreq( SD, SD_PITCH, 0);
- }
- percussion = mode;
- percBits = 0;
-
- InitSlotParams();
- SndSAmVibRhythm();
- } /* SetMode() */
-
-
-
-
- /*
- Enable (state != 0) / disable (state == 0)
- the wave-select parameters.
-
- If you do not want to use the wave-select parameters, call
- this function with a value of 0 AFTER calling SoundColdInit()
- or SoundWarmInit().
- */
- Set3812( state)
- {
- int i;
-
- modeWaveSel = state ? 0x20 : 0;
- for( i = 0; i < 18; i++)
- SndOutput( 0xE0 + offsetSlot[ i], 0);
- SndOutput( 1, modeWaveSel);
- } /* Set3812() */
-
-
-
- /*
- Routine to change the pitch bend range. The value can be from
- 1 to 12 (in half-tones).
-
- For example, the value 12 means that the pitch bend will
- range from -12 (pitchBend == 0, see function 'SetVoicePitch()')
- to +12 (pitchBend == 0x3fff) half-tones.
-
- The change will be effective as of the next call to
- 'SetVoicePitch()'.
- */
- SetPitchRange( pR)
- unsigned pR;
- {
- if( pR > 12)
- pR = 12;
- if( pR < 1)
- pR = 1;
- pitchRange = pR;
- pitchRangeStep = pitchRange * NR_STEP_PITCH;
- } /* SetPitchRange() */
-
-
- /*
- ----------------------------------------------
- Set the 3 global parameters AmDepth,
- VibDepth & NoteSel
-
- The change takes place immediately.
- ----------------------------------------------
- */
- SetGParam( amD, vibD, nSel)
- int amD, vibD, nSel;
- {
- amDepth = amD;
- vibDepth = vibD;
- noteSel = nSel;
-
- SndSAmVibRhythm();
- SndSNoteSel();
- } /* SetGParam() */
-
-
-
-
-
- /*
- -------------------------------------------------
- Set the parameters of the voice 'voice'.
-
- In melodic mode, 'voice' varies from 0 to 8.
- In percussive mode, voices 0 to 5 are melodic
- and 6 to 10 are percussive.
-
- A timbre (melodic or percussive) is defined as follows:
- the 13 first parameters of operator 0 ( ksl, multi, feedBack,
- attack, sustain, eg-typem decay, release, level, am, vib, ksr, fm)
- followed by the 13 parameters of operator 1 (if a percussive voice, all
- the parameters are zero), followed by the wave-select parameter for
- the operators 0 and 1.
-
- 'paramArray' is structured as follows:
- struct {
- int opr0Prm[ 13]; first 13 parameters
- int opr1Prm[ 13]; must be 0 if percussive timbre
- int opr0WaveSel; last parameter
- int opr1WaveSel; must be 0 if percussive timbre
- } TimbreDef;
-
- The old timbre files (*.INS) do not contain the parameters
- 'opr0WaveSel' and 'opr1WaveSel'.
- Set these two parameters to zero if you are using the old file
- format.
- -------------------------------------------------
- */
- SetVoiceTimbre( voice, paramArray)
- int voice, * paramArray;
- {
- int wave0, wave1;
- int * prm1, * wavePtr;
-
- wavePtr = paramArray + 2 * ( nbLocParam -1);
- wave0 = * wavePtr++;
- wave1 = * wavePtr;
- prm1 = paramArray + nbLocParam -1;
-
- if( !RhythmMode() || voice < BD) { /* melodic only */
- SetSlotParam( (int)slotVoice[ voice][ 0], paramArray, wave0);
- SetSlotParam( (int)slotVoice[ voice][ 1], prm1, wave1);
- }
- else if( voice == BD) { /* Bass Drum */
- SetSlotParam( (int)slotPerc[ 0][ 0], paramArray, wave0);
- SetSlotParam( (int)slotPerc[ 0][ 1], prm1, wave1);
- }
- else /* percussion, 1 slot */
- SetSlotParam( (int)slotPerc[ voice -BD][ 0], paramArray, wave0);
- } /* SetVoiceTimbre() */
-
-
-
-
- /*
- --------------------------------------------------
- Set the volume of the voice 'voice' to 'volume'.
-
- The resulting output level is (timbreVolume * volume / 127).
- The change takes place immediately.
-
- 0 <= volume <= 127
- --------------------------------------------------
- */
- SetVoiceVolume( voice, volume)
- unsigned volume; /* 0 - 0x7f */
- {
- int slot;
- char * slots;
-
- #if 1
- if( !RhythmMode() || voice < BD)
- slot = slotVoice[ voice][ 1];
- else
- slot = slotPerc[ voice -BD][ voice == BD ? 1 : 0];
-
- if( volume > MAX_VOLUME)
- volume = MAX_VOLUME;
- slotRelVolume[ slot] = volume;
- SndSKslLevel( slot);
- #else /* code that modify the two oper. volume of an additive sound: */
- if( volume > MAX_VOLUME)
- volume = MAX_VOLUME;
-
- if( !RhythmMode() || voice <= BD) {
- slots = slotVoice[ voice];
- slotRelVolume[ slots[ 1]] = volume;
- SndSKslLevel( slots[ 1]);
- if( !GetLocPrm( slots[ 0], prmFm)) {
- /* additive syntesis: set volume of first slot too */
- slotRelVolume[ slots[ 0]] = volume;
- SndSKslLevel( slots[ 0]);
- }
- }
- else {
- slot = slotPerc[ voice -BD][ 0];
- slotRelVolume[ slot] = volume;
- SndSKslLevel( slot);
- }
- #endif
- } /* SetVoiceVolume() */
-
-
- /*
- -------------------------------------------------
- Change the pitch value of a voice.
-
- The variation in pitch is a function of the previous call
- to 'SetPitchRange()' and the value of 'pitchBend'.
- A value of 0 means -half-tone * pitchRange,
- 0x2000 means no variation (exact pitch) and
- 0x3fff means +half-tone * pitchRange.
-
- Does not affect the percussive voices, except for the bass drum.
-
- The change takes place immediately.
-
- 0 <= pitchBend <= 0x3fff, 0x2000 == exact tuning
- -------------------------------------------------
- */
- SetVoicePitch( voice, pitchBend)
- unsigned voice;
- unsigned pitchBend;
- {
- if( ! RhythmMode() || voice <= BD) {
- /* melodic + bass-drum */
- if( pitchBend > MAX_PITCH)
- pitchBend = MAX_PITCH;
- ChangePitch( voice, pitchBend);
- SetFreq( voice, notePitch[ voice], voiceKeyOn[ voice]);
- }
- } /* SetVoicePitch() */
-
-
-
- /*
- -----------------------------------------------------------
- Routine to start a note playing.
-
- 0 <= voice <= 8 in melodic mode,
- 0 <= voice <= 10 in percussive mode;
- 0 <= pitch <= 127, 60 == MID_C ( the card can play between 12 and 107 )
- -----------------------------------------------------------
- */
- NoteOn( voice, pitch)
- unsigned voice;
- int pitch; /* 0 - 127 */
- {
- pitch -= ( MID_C - CHIP_MID_C);
- if( pitch < 0)
- pitch = 0;
-
- if( voice < BD || ! RhythmMode())
- /* this is a melodic voice */
- SetFreq( voice, pitch, 1);
- else {
- /* this is a percussive voice */
- if( voice == BD)
- SetFreq( BD, pitch, 0);
- else if( voice == TOM) {
- /* for the last 4 percussions, only the TOM may change in frequency,
- modifying the three others: */
- SetFreq( TOM, pitch, 0);
- SetFreq( SD, pitch + TOM_TO_SD, 0); /* f7 = 3 * f8 */
- }
-
- percBits |= percMasks[ voice - BD];
- SndSAmVibRhythm();
- }
- } /* NoteOn() */
-
-
- /*
- Routine to stop playing the note which was started in 'NoteOn()'.
-
- 0 <= voice <= 8 in melodic mode,
- 0 <= voice <= 10 in percussive mode;
- */
- NoteOff( voice)
- unsigned voice;
- {
- if( !RhythmMode() || voice < BD)
- SetFreq( voice, notePitch[ voice], 0); /* shut off */
- else {
- percBits &= ~percMasks[ voice - BD];
- SndSAmVibRhythm();
- }
- } /* NoteOff() */
-
-
-
-
-
- /*
- ------------------------------------------------------------------------
- static functions ...
- ------------------------------------------------------------------------
- */
-
-
- /*
- In melodic mode, initialize all voices to electric-pianos.
-
- In percussive mode, initialize the first 6 voices to electric-pianos
- and the percussive voices to their default timbres.
- */
- static InitSlotParams()
- {
- int i;
-
- for( i = 0; i < 18; i++)
- if( operSlot[ i])
- SetCharSlotParam( i, pianoParamsOp1, 0);
- else
- SetCharSlotParam( i, pianoParamsOp0, 0);
- if( RhythmMode()) {
- SetCharSlotParam( 12, bdOpr0, 0);
- SetCharSlotParam( 15, bdOpr1, 0);
- SetCharSlotParam( 16, sdOpr, 0);
- SetCharSlotParam( 14, tomOpr, 0);
- SetCharSlotParam( 17, cymbOpr, 0);
- SetCharSlotParam( 13, hhOpr, 0);
- }
- } /* InitSlotParams() */
-
-
-
-
- /*
- Set the volume of all slots.
- */
- static InitSlotVolume()
- {
- int i;
-
- for( i = 0; i < 18; i++)
- slotRelVolume[ i] = MAX_VOLUME;
- } /* InitSlotVolume() */
-
-
-
-
- /*
- Return binary value of the frequency 260.44 ( C)
- shifted by +/- numdeltaDemiTon/denDeltaDemiTon multiplied by 8.
-
- If the numerator (numDeltaDemiTon) is positive, the frequency is
- increased; if negative, it is decreased.
-
- Fo = Fb( 1 + 0.06 num /den)
- Fnum8 = Fo * 65536 * 72 / 3.58e6
-
- -100 <= numDeltaDemiTon <= +100
- 1 <= denDeltaDemiTon <= 100
- */
- static long CalcPremFNum( numDeltaDemiTon, denDeltaDemiTon)
- {
- long f8, fNum8, d100;
-
- d100 = denDeltaDemiTon * 100;
- f8 = ( d100 + 6 * numDeltaDemiTon) * (26044L * 2L); /* 260.44 * 100 * 2 */
- f8 /= d100 * 25;
- fNum8 = f8 * 16384; /*( 16384L * 9L); */
- fNum8 *= 9L;
- fNum8 /= 179L * 625L;
- return fNum8;
- } /* CalcPremFNum() */
-
-
- /*
- Initialize a line in the frequency table with shifted frequency values.
- The values are shifted a fraction (num/den) of a half-tone.
- See following routine.
- */
- static SetFNum( fNumVec, num, den)
- unsigned * fNumVec;
- {
- int i;
- long val;
-
- *fNumVec++ = (unsigned)(4 +(val = CalcPremFNum( num, den))) >> 3;
- for ( i = 1; i < 12; i++) {
- val *= 106;
- *fNumVec++ = (unsigned)(4 +(val /= 100)) >> 3;
- }
- } /* SetFNum() */
-
-
- /*
- Initialize all lines of the frequency table. Each line represents
- 12 half-tones shifted by (n/NR_STEP_PITCH), where 'n' is the line number
- and ranges from 1 to NR_STEP_PITCH.
- */
- static InitFNums()
- {
- unsigned i, j, k, num, numStep, pas;
-
- numStep = 100 / NR_STEP_PITCH;
- for( num = pas = 0; pas < NR_STEP_PITCH; pas++, num += numStep)
- SetFNum( fNumNotes[ pas], num, 100);
- for( i = 0; i < 11; i++) {
- fNumFreqPtr[ i] = (unsigned *) fNumNotes[ 0];
- halfToneOffset[ i] = 0;
- }
-
- k = 0;
- for( i = 0; i < 8; i++)
- for( j = 0; j < 12; j++, k++) {
- noteDIV12[ k] = i;
- noteMOD12[ k] = j;
- }
- } /* InitFNums() */
-
-
- /*
- Routine to set 'halfToneOffset[]' & 'fNumFreqPtr[]'.
- These two global variables are used to determine the frequency
- variation to use when a note is played.
-
- 0 <= pitchBend <= 3fffH
- */
- static ChangePitch( voice, pitchBend)
- int voice;
- int pitchBend; /* 0 - 3fffH, 2000H == exact tuning */
- {
- int t1, t2, delta;
- long l;
- static long oldL = ~0;
- static int oldHt;
- static unsigned * oldPtr;
-
- l = (long)(pitchBend - MID_PITCH) * pitchRangeStep;
- if( oldL == l) { /* optimisation ... */
- fNumFreqPtr[ voice] = oldPtr;
- halfToneOffset[ voice] = oldHt;
- }
- else {
- t1 = l / MID_PITCH;
- if( t1 < 0) {
- t2 = NR_STEP_PITCH -1 -t1;
- oldHt = halfToneOffset[ voice] = -(t2 / NR_STEP_PITCH);
- delta = (t2 - NR_STEP_PITCH +1) % NR_STEP_PITCH;
- if( delta)
- delta = NR_STEP_PITCH - delta;
- }
- else {
- oldHt = halfToneOffset[ voice] = t1 / NR_STEP_PITCH;
- delta = t1 % NR_STEP_PITCH;
- }
- oldPtr = fNumFreqPtr[ voice] = (unsigned *) fNumNotes[ delta];
- oldL = l;
- }
- } /* ChangePitch() */
-
-
-
- /*
- Used to change the parameter 'param' of the slot 'slot'
- with the value 'val'. The chip registers are updated.
- */
- SetASlotParam( slot, param, val)
- int slot, val;
- int param; /* parameter number */
- {
- paramSlot[ slot][ param] = val;
- SndSetPrm( slot, param);
- } /* SetASlotParam() */
-
-
-
-
-
-
-
- /*
- ------------------------------------------------------
- Set the 14 parameters ( 13 in 'param', 1 in 'waveSel')
- of slot 'slot'. Update the parameter array and the chip.
- ------------------------------------------------------
- */
- static SetSlotParam( slot, param, waveSel)
- unsigned slot, * param, waveSel;
- {
- int i, k;
- SLOT_PARAM * ptr;
-
- for( i = 0, ptr = ¶mSlot[ slot][ 0]; i < nbLocParam -1; i++)
- *ptr++ = *param++;
- *ptr = waveSel &= 0x3;
- SndSetAllPrm( slot);
- } /* SetSlotParam() */
-
- SetCharSlotParam( slot, cParam, waveSel)
- unsigned slot, waveSel;
- char * cParam;
- {
- int param[ nbLocParam];
- int i;
-
- for( i = 0; i < nbLocParam -1; i++)
- param[ i] = *cParam++;
- SetSlotParam( slot, param, waveSel);
- } /* SetCharSlotParam() */
-
-
- /*
- -----------------------------------------------
- Update the parameter 'prm' for the slot 'slot'.
- Update the chip registers.
- -----------------------------------------------
- */
- static SndSetPrm( slot, prm)
- int slot, prm;
- {
-
- switch( prm) {
- case prmPercussion:
- case prmAmDepth:
- case prmVibDepth:
- SndSAmVibRhythm();
- break;
-
- case prmNoteSel:
- SndSNoteSel();
- break;
-
- case prmKsl:
- case prmLevel:
- SndSKslLevel( slot);
- break;
-
- case prmFm:
- case prmFeedBack:
- SndSFeedFm( slot);
- break;
-
- case prmAttack:
- case prmDecay:
- SndSAttDecay( slot);
- break;
-
- case prmRelease:
- case prmSustain:
- SndSSusRelease( slot);
- break;
-
- case prmMulti:
- case prmVib:
- case prmStaining:
- case prmKsr:
- case prmAm:
- SndSAVEK( slot);
- break;
-
- case prmWaveSel:
- SndWaveSelect( slot);
- break;
- }
- } /* SndSetPrm() */
-
-
-
- /*-------------------------------------------------
- Transfer all the parameters from slot 'slot' to
- the chip.
- */
- static SndSetAllPrm( slot)
- {
- SndSAmVibRhythm();
- SndSNoteSel();
- SndSKslLevel( slot);
- SndSFeedFm( slot);
- SndSAttDecay( slot);
- SndSSusRelease( slot);
- SndSAVEK( slot);
- SndWaveSelect( slot);
- } /* SndSetAllPrm() */
-
-
- /*
- KSL, LEVEL
- */
- static SndSKslLevel( slot)
- {
- unsigned t1;
-
- t1 = 63 - (GetLocPrm( slot, prmLevel) & 0x3f); /* amplitude */
- t1 = slotRelVolume[ slot] * t1;
- t1 += t1 + MAX_VOLUME; /* round off to 0.5 */
- t1 = 63 - t1 / ( 2 * MAX_VOLUME);
-
- t1 |= GetLocPrm( slot, prmKsl) << 6;
- SndOutput( 0x40 + (int)offsetSlot[ slot], t1);
- }
-
-
- /* --------------------------------------------
- Note sel
- */
- static SndSNoteSel()
- {
- SndOutput( 0x08, noteSel ? 64 : 0);
- } /* SndSNoteSel() */
-
-
-
- /* --------------------------------------------
- FEED-BACK and FM (connection).
- Applicable only to operator 0 in melodic mode.
- */
- static SndSFeedFm( slot)
- {
- unsigned t1;
-
- if( operSlot[ slot])
- return;
- t1 = GetLocPrm( slot, prmFeedBack) << 1;
- t1 |= GetLocPrm( slot, prmFm) ? 0 : 1;
- SndOutput( 0xC0 + (int)voiceSlot[ slot], t1);
- }
-
-
- /*
- ATTACK, DECAY
- */
- static SndSAttDecay( slot)
- {
- unsigned t1;
-
- t1 = GetLocPrm( slot, prmAttack) << 4;
- t1 |= GetLocPrm( slot, prmDecay) & 0xf;
- SndOutput( 0x60 + (int)offsetSlot[ slot], t1);
- }
-
-
- /*
- SUSTAIN, RELEASE
- */
- static SndSSusRelease( slot)
- {
- unsigned t1;
-
- t1 = GetLocPrm( slot, prmSustain) << 4;
- t1 |= GetLocPrm( slot, prmRelease) & 0xf;
- SndOutput( 0x80 + (int)offsetSlot[ slot], t1);
- }
-
-
-
- /*
- AM, VIB, EG-TYP( Sustaining), KSR, MULTI
- */
- static SndSAVEK( slot)
- {
- unsigned t1;
-
- t1 = GetLocPrm( slot, prmAm) ? 0x80 : 0;
- t1 += GetLocPrm( slot, prmVib) ? 0x40 : 0;
- t1 += GetLocPrm( slot, prmStaining) ? 0x20 : 0;
- t1 += GetLocPrm( slot, prmKsr) ? 0x10 : 0;
- t1 += GetLocPrm( slot, prmMulti) & 0xf;
- SndOutput( 0x20 + (int)offsetSlot[ slot], t1);
- } /* SndSAVEK() */
-
-
- /*
- Set the values: AM Depth, VIB depth & Rhythm
- */
- static SndSAmVibRhythm()
- {
- unsigned t1;
-
- t1 = amDepth ? 0x80 : 0;
- t1 |= vibDepth ? 0x40 : 0;
- t1 |= RhythmMode() ? 0x20 : 0;
- t1 |= percBits;
- SndOutput( 0xBD, t1);
- }
-
-
- /*
- Set the wave-select parameter.
- */
- static SndWaveSelect( slot)
- {
- unsigned wave;
-
- if( modeWaveSel)
- wave = GetLocPrm( slot, prmWaveSel) & 0x03;
- else
- wave = 0;
- SndOutput( 0xE0 + offsetSlot[ slot], wave);
- } /* SndWaveSelect() */
-
-
- /*
- Change pitch of voices 0 to 8, for melodic or percussive mode.
- */
- SetFreq( voice, pitch, keyOn)
- unsigned voice; /* voice number */
- int pitch; /* 0 - 95 */
- unsigned keyOn; /* Set key-on/off */
- {
- unsigned int fNbr, t1;
-
- voiceKeyOn[ voice] = keyOn;
- notePitch[ voice] = pitch;
- pitch += halfToneOffset[ voice];
- if( pitch > 95)
- pitch = 95;
- if( pitch < 0)
- pitch = 0;
- fNbr = * ( fNumFreqPtr[ voice] + noteMOD12[ pitch]);
- SndOutput( 0xA0 +voice, fNbr);
- t1 = keyOn ? 32 : 0;
- t1 += ( (unsigned)noteDIV12[ pitch] << 2) + ( 0x3 & HighByte( fNbr) );
- SndOutput( 0xB0 +voice, t1);
- }
-
-
-
- /*
- Set the frequency of voice 'voice' to 0 hertz.
- */
- static SoundChut( voice)
- int voice;
- {
- SndOutput( 0xA0 +voice, 0);
- SndOutput( 0xB0 +voice, 0);
- } /* SoundChut() */
-
-
-
- /*
- Return 0 if board is not installed
- */
- int BoardInstalled()
- {
- unsigned t1, t2, i;
-
- SndOutput( 4, 0x60); /* mask T1 & T2 */
- SndOutput( 4, 0x80); /* reset IRQ */
- t1 = inp( genAddr); /* read status register */
- SndOutput( 2, 0xff); /* set timer-1 latch */
- SndOutput( 4, 0x21); /* unmask & start T1 */
- for( i = 0; i < 200; i++) /* 100 uSec delay for timer-1 overflow */
- inp( genAddr);
- t2 = inp( genAddr); /* read status register */
- SndOutput( 4, 0x60);
- SndOutput( 4, 0x80);
- return (t1 & 0xE0) == 0 && (t2 & 0xE0) == 0xC0;
- }
-
-