/****************************************/ /* Low-level control of the EMU8000 */ /* (c) Grinus/ToM, 1996 */ /****************************************/ // My Types typedef unsigned char BYTE; typedef unsigned int WORD; typedef unsigned long DWORD; #define HBYTE(w) (*((BYTE *)&w + 1)) #define HWORD(l) (*((WORD *)&l + 1)) /*******************************/ /* EMU8000 Registers */ /*******************************/ // The low byte of the address is reserved for a G-channel number (0 to 29). #define AWE_CurrPitch 0x0000 /* (00 620) D ... CurrPitch (W) & PitchCounter (W) CurrPitch: a linear pitch (0000..FFFF), still sliding to DestPitch. */ #define AWE_DP_Rev_Pan 0x0400 /* (20 620) D ... DestPitch (W) & Reverb (B) & RightPan (B) DestPitch: a destination value for the CurrPitch (derived from Pitch). HINT: It's good to set CurrPitch and DestPitch before starting the note to avoid a very short pitch slide, which can appear. RightPan: a volume of the right speaker (0..zero, 255..full) */ #define AWE_CurrV_FC 0x0800 /* (40 620) D ... CurrVolume (W) & CurrFC (B) & ?? (B) CurrVolume: a linear volume, still sliding to DestVolume (0..0xEAC0) CurrFilterCutoff: a linear value ([Hz] - 100) / 31.25 */ #define AWE_DestV_FC 0x0C00 /* (60 620) D ... DestVolume (W) & DestFC (B) & ?? (B) DestVolume: a destination value for the CurrVolume (0..0xEAC0) (derived from Volume and ENV2). HINTS: It can be used to mute the sample immediately after stopping ENV2. Read this register to get the current volume envelope value. DestFilterCutoff: ... */ #define AWE_10 0x1000 /* (80 620) D ... ??? 00000000 */ #define AWE_14 0x1400 /* (A0 620) D ... ??? 00000000 */ #define AWE_Pan_Loops 0x1800 /* (C0 620) D ... LeftPan (B) & LoopS (3B) LeftPan: a volume of the left speaker (0..zero, 255..full) */ #define AWE_Cho_Loope 0x1C00 // (E0 620) D ... Chorus (B) & LoopE (3B) #define AWE_Flt_Start 0x2000 // (00 A20) D ... FilterQ (4b) & RAMmode (4b) & CurrPos (3B) #define AWE_24 0x2400 // (20 A20) ? ... efect ctrl, RAM access, ... #define AWE_RdAdrD 0x2414 // (34 A20) D ... address for sample RAM reading #define AWE_WrAdrD 0x2416 // (36 A20) D ... address for sample RAM writing #define AWE_DataW 0x241A // (3A A20) W ... sample RAM data #define AWE_CLK 0x261B // (3B A22) W ... read Clock Counter (44100Hz) #define AWE_28 0x2800 // (40 A20) W ... efect params #define AWE_2A 0x2A00 // (40 A22) W ... #define AWE_2C 0x2C00 // (60 A20) W ... #define AWE_2E 0x2E00 // (40 A22) W ... -"- #define AWE_Env2Dly 0x3000 /* (80 A20) W ... ENV2 Delay Delay: 0x8000 - [us]/725 HINT: a description of the envelope parameters is available in ADIP dox. */ #define AWE_Env2Ho_Att 0x3200 /* (80 A22) W ... ENV2 Hold & Attack HoldTime: 0x7F - [ms]/92 AttackTime: 11878/[ms] - 1 ( 00..20 for time>=360ms ) 0x20 + 16 * ln2(360/[ms]) ( 20..7E for time< 360ms ) 0x7F ( 7F for time==0ms ) */ #define AWE_Env2Su_Dcy 0x3400 /* (A0 A20) W ... ENV2 Sustain & Decay Sustain: 0x7F - [-dB] * 8 / 6 7.bit = 0: Note On (to start the sample, ENV, ...) 7.bit = 1: Note Off (to start the Decay) DecayTime: 2 * log(0.5) * log(23756/[ms]) (0x7F...0ms) 7.bit -> stop ENV2 (to freeze the actual value) It has no effect when increasing the volume! HINT: Use this register just for NoteOn/NoteOff ! Do not use it for changing the volume. */ #define AWE_Lfo1Dly 0x3600 // (A0 A22) W ... LFO1 Delay #define AWE_Env1Dly 0x3800 // (C0 A20) W ... ENV1 Delay #define AWE_Env1Ho_Att 0x3A00 // (C0 A22) W ... ENV1 Hold & Attack #define AWE_Env1Su_Dcy 0x3C00 // (E0 A20) W ... ENV1 Sustain & Decay #define AWE_Lfo2Dly 0x3E00 // (E0 A22) W ... LFO2 Delay #define AWE_Pitch 0x4000 /* (00 E20) W ... Pitch Pitch: 57344 - 4096*log(44100/[Hz]) HINT: This is the main pitch control. Don't use the linear pitch regs! */ #define AWE_FC_Vol 0x4400 /* (20 E20) W ... FiltCutoff & Volume FiltCutoff: ([Hz] - 100) / 31.25 Volume: [-dB] * 16 / 6 (255 ... silent) HINT: This is the main volume control. Don't use the linear volume regs! */ #define AWE_Env1tP_tF 0x4800 /* (40 E20) W ... ENV1 ToPitch & ToFilter ToPitch: [cents] * 8 / 75 (signed) ToFilter: [cents] * 8 / 225 (signed) */ #define AWE_Lfo1tP_tF 0x4C00 // (60 E20) W ... LFO1 ToPitch & ToFilter #define AWE_Lfo1tV_F 0x5000 /* (80 E20) W ... LFO1 ToVolume & Freq ToVolume: [dB] * 12 / 128 Freq: [Hz] * 21.44 / 256 */ #define AWE_Lfo2tP_F 0x5400 // (A0 E20) W ... LFO2 ToPitch & Freq #define AWE_58 0x5800 // (C0 E20) W ... ??? 0000 #define AWE_5C 0x5C00 // (E0 E20) W ... ??? used in Detect() /**********************************/ /* Other EMU8000 definitions */ /**********************************/ #define MINLOOP 4 // the minimal sample loop length #define ANTICLICK 4 // the number of anti-click samples (at least 3) // Starting address of the sample RAM (4MB reserved for ROM) #define TOPRAM 0x200000 // Chorus Params typedef struct { WORD FbkLevel; // Feedback Level (0xE600-0xE6FF) WORD Delay; // Delay (0-0x0DA3) [1/44100 sec] WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF) DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec] DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF) } CHORUS_TYPE; /****************************/ /* Function prototypes */ /****************************/ void AweWrW(WORD reg, WORD data); WORD AweRdW(WORD reg); void AweWrD(WORD reg, WORD hdata, WORD ldata); DWORD AweRdD(WORD reg); void AweWait(WORD delay); int AweDetect(); void AweEnableRam(int rmode); void AweDisableRam(); int AweInitHw(); void AweTerminate(); void AweChorusType(int type); void AweReverbType(int type); void AweTrebleBass(int bass, int treble); void AweWrBlock(WORD far *buf, WORD num_samps); void AweNoteOn(int gChan, BYTE Volume, BYTE Pan, BYTE Reverb, BYTE Chorus, WORD AwePitch, WORD AweLinPitch, DWORD Start, DWORD LoopS, DWORD LoopE ); void NoteOff(int gChan); void CutNote(int gChan);