aboutsummaryrefslogtreecommitdiff
path: root/emu8k_internal.h
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2022-02-05 02:41:17 +0100
committerJavier <dev.git@javispedro.com>2022-02-05 02:41:17 +0100
commit176ec23dd48c50c87e5394b702e2cf0fe72957db (patch)
tree7137f296963e3a8638c24ca08c47e70d0456d2ec /emu8k_internal.h
parent4d13ee7785a4184cf2a349fdec1af6cf9f05bfdf (diff)
downloadvmusic-176ec23dd48c50c87e5394b702e2cf0fe72957db.tar.gz
vmusic-176ec23dd48c50c87e5394b702e2cf0fe72957db.zip
add initial emu8k/SBAWE32 device using PCem's emu8k
Diffstat (limited to 'emu8k_internal.h')
-rw-r--r--emu8k_internal.h815
1 files changed, 815 insertions, 0 deletions
diff --git a/emu8k_internal.h b/emu8k_internal.h
new file mode 100644
index 0000000..a8e3ea8
--- /dev/null
+++ b/emu8k_internal.h
@@ -0,0 +1,815 @@
+/*
+ * PCem - IBM PC emulator
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Portions:
+ * VMusic - a VirtualBox extension pack with various music devices
+ * Copyright (C) 2022 Javier S. Pedro
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _EMU8K_INTERNAL_H_
+#define _EMU8K_INTERNAL_H_
+
+#include <stdint.h>
+
+#define MAXSOUNDBUFLEN (48000 / 10)
+
+#define BLOCK_SIZE_WORDS 0x10000
+
+/* All these defines are in samples, not in bytes. */
+#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
+#define EMU8K_RAM_MEM_START 0x200000
+#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0
+#define EMU8K_RAM_POINTERS_MASK 0x3F
+#define EMU8K_LFOCHORUS_SIZE 0x4000
+/*
+ * Everything in this file assumes little endian
+ */
+/* used for the increment of oscillator position*/
+typedef struct emu8k_mem_internal_t {
+ union {
+ uint64_t addr;
+ struct {
+ uint16_t fract_lw_address;
+ uint16_t fract_address;
+ uint32_t int_address;
+ };
+ };
+} emu8k_mem_internal_t;
+
+/* used for access to ram pointers from oscillator position. */
+typedef struct emu8k_mem_pointers_t {
+ union {
+ uint32_t addr;
+ struct {
+ uint16_t lw_address;
+ uint8_t hb_address;
+ uint8_t unused_address;
+ };
+ };
+} emu8k_mem_pointers_t;
+
+/*
+ * From the Soundfount 2.0 fileformat Spec.:
+ *
+ An envelope generates a control signal in six phases.
+ When key-on occurs, a delay period begins during which the envelope value is zero.
+ The envelope then rises in a convex curve to a value of one during the attack phase.
+ " Note that the attack is convex; the curve is nominally such that when applied to a
+ decibel or semitone parameter, the result is linear in amplitude or Hz respectively"
+
+ When a value of one is reached, the envelope enters a hold phase during which it remains at one.
+ When the hold phase ends, the envelope enters a decay phase during which its value decreases linearly to a sustain level.
+ " For the Volume Envelope, the decay phase linearly ramps toward the sustain level, causing a constant dB change for each time unit. "
+ When the sustain level is reached, the envelope enters sustain phase, during which the envelope stays at the sustain level.
+
+ Whenever a key-off occurs, the envelope immediately enters a release phase during which the value linearly ramps from the current value to zero.
+ " For the Volume Envelope, the release phase linearly ramps toward zero from the current level, causing a constant dB change for each time unit"
+
+ When zero is reached, the envelope value remains at zero.
+
+ Modulation of pitch and filter cutoff are in octaves, semitones, and cents.
+ These parameters can be modulated to varying degree, either positively or negatively, by the modulation envelope.
+ The degree of modulation is specified in cents for the full-scale attack peak.
+
+ The volume envelope operates in dB, with the attack peak providing a full scale output, appropriately scaled by the initial volume.
+ The zero value, however, is actually zero gain.
+ The implementation in the EMU8000 provides for 96 dB of amplitude control.
+ When 96 dB of attenuation is reached in the final gain amplifier, an abrupt jump to zero gain
+ (infinite dB of attenuation) occurs. In a 16-bit system, this jump is inaudible
+*/
+/* It seems that the envelopes don't really have a decay/release stage,
+ * but instead they have a volume ramper that can be triggered
+ * automatically (after hold period), or manually (by activating release)
+ * and the "sustain" value is the target of any of both cases.
+ * Some programs like cubic player and AWEAmp use this, and it was
+ * described in the following way in Vince Vu/Judge Dredd's awe32p10.txt:
+ * If the MSB (most significant bit or bit 15) of this register is set,
+ * the Decay/Release will begin immediately, overriding the Delay, Attack,
+ * and Hold. Otherwise the Decay/Release will wait until the Delay, Attack,
+ * and Hold are finished. If you set the MSB of this register, you can use
+ * it as a volume ramper, as on the GUS. The upper byte (except the MSB),
+ * contains the destination volume, and the lower byte contains the ramp time.
+ */
+
+/* attack_amount is linear amplitude (added directly to value).
+ * ramp_amount_db is linear dB (added directly to value too, but needs conversion to get linear amplitude).
+ * value range is 21bits for both, linear amplitude being 1<<21 = 0dBFS and 0 = -96dBFS (which is shortcut to silence),
+ * and db amplutide being 0 = 0dBFS and -(1<<21) = -96dBFS (which is shortcut to silence).
+ * This allows to operate db values by simply adding them.
+ */
+typedef struct emu8k_envelope_t {
+ int state;
+ int32_t delay_samples, hold_samples, attack_samples;
+ int32_t value_amp_hz, value_db_oct;
+ int32_t sustain_value_db_oct;
+ int32_t attack_amount_amp_hz, ramp_amount_db_oct;
+} emu8k_envelope_t;
+
+
+
+typedef struct emu8k_chorus_eng_t {
+ int32_t write;
+ int32_t feedback;
+ int32_t delay_samples_central;
+ double lfodepth_multip;
+ double delay_offset_samples_right;
+ emu8k_mem_internal_t lfo_inc;
+ emu8k_mem_internal_t lfo_pos;
+
+ int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE];
+ int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE];
+
+} emu8k_chorus_eng_t;
+
+/* 32 * 242. 32 comes from the "right" room resso case.*/
+#define MAX_REFL_SIZE 7744
+
+
+/* Reverb parameters description, extracted from AST sources.
+ Mix level
+ Decay
+ Link return amp
+ Link type Switches between normal or panned
+ Room reso ( ms) L&R (Ref 6 +1)
+ Ref 1 x2 (11 ms)R
+ Ref 2 x4 (22 ms)R
+ Ref 3 x8 (44 ms)L
+ Ref 4 x13(71 ms)R
+ Ref 5 x19(105ms)L
+ Ref 6 x ( ms)R (multiplier changes with room reso)
+ Ref 1-6 filter L&R
+ Ref 1-6 amp L&R
+ Ref 1 feedback L&R
+ Ref 2 feedback L&R
+ Ref 3 feedback L&R
+ Ref 4 feedback L&R
+ Ref 5 feedback L&R
+ Ref 6 feedback L&R
+*/
+typedef struct emu8k_reverb_combfilter_t {
+ int read_pos;
+ int32_t reflection[MAX_REFL_SIZE];
+ float output_gain;
+ float feedback;
+ float damp1;
+ float damp2;
+ int bufsize;
+ int32_t filterstore;
+} emu8k_reverb_combfilter_t;
+
+typedef struct emu8k_reverb_eng_t {
+
+ int16_t out_mix;
+ int16_t link_return_amp; /* tail part output gain ? */
+ int8_t link_return_type;
+
+ uint8_t refl_in_amp;
+
+ emu8k_reverb_combfilter_t reflections[6];
+ emu8k_reverb_combfilter_t allpass[8];
+ emu8k_reverb_combfilter_t tailL;
+ emu8k_reverb_combfilter_t tailR;
+
+ emu8k_reverb_combfilter_t damper;
+} emu8k_reverb_eng_t;
+
+typedef struct emu8k_slide_t {
+ int32_t last;
+} emu8k_slide_t;
+
+
+typedef struct emu8k_voice_t
+{
+ union {
+ uint32_t cpf;
+ struct {
+ uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */
+ uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */
+ };
+ };
+ union {
+ uint32_t ptrx;
+ struct {
+ uint8_t ptrx_pan_aux;
+ uint8_t ptrx_revb_send;
+ uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */
+ };
+ };
+ union {
+ uint32_t cvcf;
+ struct {
+ uint16_t cvcf_curr_filt_ctoff;
+ uint16_t cvcf_curr_volume;
+ };
+ };
+ emu8k_slide_t volumeslide;
+ union {
+ uint32_t vtft;
+ struct {
+ uint16_t vtft_filter_target;
+ uint16_t vtft_vol_target; /* written to by the envelope engine. */
+ };
+ };
+ /* These registers are used at least by the Windows drivers, and seem to be resetting
+ * something, similarly to targets and current, but... of what?
+ * what is curious is that if they are already zero, they are not written to, so it really
+ * looks like they are information about the status of the channel. (lfo position maybe?) */
+ uint32_t unknown_data0_4;
+ uint32_t unknown_data0_5;
+ union {
+ uint32_t psst;
+ struct {
+ uint16_t psst_lw_address;
+ uint8_t psst_hw_address;
+ uint8_t psst_pan;
+ };
+ #define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
+ };
+ union {
+ uint32_t csl;
+ struct {
+ uint16_t csl_lw_address;
+ uint8_t csl_hw_address;
+ uint8_t csl_chor_send;
+ };
+ #define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
+ };
+ union {
+ uint32_t ccca;
+ struct {
+ uint16_t ccca_lw_addr;
+ uint8_t ccca_hb_addr;
+ uint8_t ccca_qcontrol;
+ };
+ };
+ #define CCCA_FILTQ_GET(ccca) (ccca>>28)
+ #define CCCA_FILTQ_SET(ccca,q) ccca = (ccca&0x0FFFFFFF) | (q<<28)
+ /* Bit 27 should always be zero */
+ #define CCCA_DMA_ACTIVE(ccca) (ccca&0x04000000)
+ #define CCCA_DMA_WRITE_MODE(ccca) (ccca&0x02000000)
+ #define CCCA_DMA_WRITE_RIGHT(ccca) (ccca&0x01000000)
+
+ uint16_t envvol;
+ #define ENVVOL_NODELAY(envol) (envvol&0x8000)
+ /* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
+ #define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol&0x8000) ? 0 : ((0x8000-(envvol&0x7FFF)) <<5)
+
+ uint16_t dcysusv;
+ #define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv&0x8000)
+ #define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv&0x0080)
+ #define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv>>8)&0x7F)
+ /* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */
+ #define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F-susvalue) << 21)/0x7F)
+ #define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv&0x7F)
+
+ uint16_t envval;
+ #define ENVVAL_NODELAY(enval) (envval&0x8000)
+ /* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
+ #define ENVVAL_TO_EMU_SAMPLES(envval)(envval&0x8000) ? 0 : ((0x8000-(envval&0x7FFF)) <<5)
+
+ uint16_t dcysus;
+ #define DCYSUS_IS_RELEASE(dcysus) (dcysus&0x8000)
+ #define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus>>8)&0x7F)
+ #define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21)/0x7F)
+ #define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus&0x7F)
+
+ uint16_t atkhldv;
+ #define ATKHLDV_TRIGGER(atkhldv) !(atkhldv&0x8000)
+ #define ATKHLDV_HOLD(atkhldv) ((atkhldv>>8)&0x7F)
+ #define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096*(0x7F-((atkhldv>>8)&0x7F)))
+ #define ATKHLDV_ATTACK(atkhldv) (atkhldv&0x7F)
+
+ uint16_t lfo1val, lfo2val;
+ #define LFOxVAL_NODELAY(lfoxval) (lfoxval&0x8000)
+ #define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval&0x8000) ? 0 : ((0x8000-(lfoxval&0x7FFF)) <<5)
+
+ uint16_t atkhld;
+ #define ATKHLD_TRIGGER(atkhld) !(atkhld&0x8000)
+ #define ATKHLD_HOLD(atkhld) ((atkhld>>8)&0x7F)
+ #define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096*(0x7F-((atkhld>>8)&0x7F)))
+ #define ATKHLD_ATTACK(atkhld) (atkhld&0x7F)
+
+
+ uint16_t ip;
+ #define INTIAL_PITCH_CENTER 0xE000
+ #define INTIAL_PITCH_OCTAVE 0x1000
+
+ union {
+ uint16_t ifatn;
+ struct{
+ uint8_t ifatn_attenuation;
+ uint8_t ifatn_init_filter;
+ };
+ };
+ union {
+ uint16_t pefe;
+ struct {
+ int8_t pefe_modenv_filter_height;
+ int8_t pefe_modenv_pitch_height;
+ };
+ };
+ union {
+ uint16_t fmmod;
+ struct {
+ int8_t fmmod_lfo1_filt_mod;
+ int8_t fmmod_lfo1_vibrato;
+ };
+ };
+ union {
+ uint16_t tremfrq;
+ struct {
+ uint8_t tremfrq_lfo1_freq;
+ int8_t tremfrq_lfo1_tremolo;
+ };
+ };
+ union {
+ uint16_t fm2frq2;
+ struct {
+ uint8_t fm2frq2_lfo2_freq;
+ int8_t fm2frq2_lfo2_vibrato;
+ };
+ };
+
+ int env_engine_on;
+
+ emu8k_mem_internal_t addr, loop_start, loop_end;
+
+ int32_t initial_att;
+ int32_t initial_filter;
+
+ emu8k_envelope_t vol_envelope;
+ emu8k_envelope_t mod_envelope;
+
+ int64_t lfo1_speed, lfo2_speed;
+ emu8k_mem_internal_t lfo1_count, lfo2_count;
+ int32_t lfo1_delay_samples, lfo2_delay_samples;
+ int vol_l, vol_r;
+
+ int16_t fixed_modenv_filter_height;
+ int16_t fixed_modenv_pitch_height;
+ int16_t fixed_lfo1_filt_mod;
+ int16_t fixed_lfo1_vibrato;
+ int16_t fixed_lfo1_tremolo;
+ int16_t fixed_lfo2_vibrato;
+
+ /* filter internal data. */
+ int filterq_idx;
+ int32_t filt_att;
+ int64_t filt_buffer[5];
+
+} emu8k_voice_t;
+
+typedef struct emu8k_t
+{
+ emu8k_voice_t voice[32];
+
+ uint16_t hwcf1, hwcf2, hwcf3;
+ uint32_t hwcf4, hwcf5, hwcf6, hwcf7;
+
+ uint16_t init1[32], init2[32], init3[32], init4[32];
+
+ uint32_t smalr, smarr, smalw, smarw;
+ uint16_t smld_buffer, smrd_buffer;
+
+ uint16_t wc;
+
+ uint16_t id;
+
+ /* The empty block is used to act as an unallocated memory returning zero. */
+ int16_t *ram, *rom, *empty;
+
+ /* RAM pointers are a way to avoid checking ram boundaries on read */
+ int16_t *ram_pointers[0x100];
+ uint32_t ram_end_addr;
+
+ int cur_reg, cur_voice;
+
+ int16_t out_l, out_r;
+
+ emu8k_chorus_eng_t chorus_engine;
+ int32_t chorus_in_buffer[MAXSOUNDBUFLEN];
+ emu8k_reverb_eng_t reverb_engine;
+ int32_t reverb_in_buffer[MAXSOUNDBUFLEN];
+
+ int pos;
+ int32_t buffer[MAXSOUNDBUFLEN * 2];
+} emu8k_t;
+
+
+
+/*
+
+Section E - Introduction to the EMU8000 Chip
+
+ The EMU8000 has its roots in E-mu's Proteus sample playback
+ modules and their renowned Emulator sampler. The EMU8000 has
+ 32 individual oscillators, each playing back at 44.1 kHz. By
+ incorporating sophisticated sample interpolation algorithms
+ and digital filtering, the EMU8000 is capable of producing
+ high fidelity sample playback.
+
+ The EMU8000 has an extensive modulation capability using two
+ sine-wave LFOs (Low Frequency Oscillator) and two multi-
+ stage envelope generators.
+
+ What exactly does modulation mean? Modulation means to
+ dynamically change a parameter of an audio signal, whether
+ it be the volume (amplitude modulation, or tremolo), pitch
+ (frequency modulation, or vibrato) or filter cutoff
+ frequency (filter modulation, or wah-wah). To modulate
+ something we would require a modulation source, and a
+ modulation destination. In the EMU8000, the modulation
+ sources are the LFOs and the envelope generators, and the
+ modulation destinations can be the pitch, the volume or the
+ filter cutoff frequency.
+
+ The EMU8000's LFOs and envelope generators provide a complex
+ modulation environment. Each sound producing element of the
+ EMU8000 consists of a resonant low-pass filter, two LFOs, in
+ which one modulates the pitch (LFO2), and the other
+ modulates pitch, filter cutoff and volume (LFO1)
+ simultaneously. There are two envelope generators; envelope
+ 1 contours both pitch and filter cutoff simultaneously, and
+ envelope 2 contours volume. The output stage consists of an
+ effects engine that mixes the dry signals with the
+ Reverb/chorus level signals to produce the final mix.
+
+ What are the EMU8000 sound elements?
+
+ Each of the sound elements in an EMU8000 consists of the
+ following:
+
+ Oscillator
+ An oscillator is the source of an audio signal.
+
+ Low Pass Filter
+ The low pass filter is responsible for modifying the
+ timbres of an instrument. The low pass filter's filter
+ cutoff values can be varied from 100 Hz to 8000 Hz. By
+ changing the values of the filter cutoff, a myriad of
+ analogue sounding filter sweeps can be achieved. An
+ example of a GM instrument that makes use of filter sweep
+ is instrument number 87, Lead 7 (fifths).
+
+ Amplifier
+ The amplifier determines the loudness of an audio signal.
+
+ LFO1
+ An LFO, or Low Frequency Oscillator, is normally used to
+ periodically modulate, that is, change a sound parameter,
+ whether it be volume (amplitude modulation), pitch
+ (frequency modulation) or filter cutoff (filter
+ modulation). It operates at sub-audio frequency from
+ 0.042 Hz to 10.71 Hz. The LFO1 in the EMU8000 modulates
+ the pitch, volume and filter cutoff simultaneously.
+
+ LFO2
+ The LFO2 is similar to the LFO1, except that it modulates
+ the pitch of the audio signal only.
+
+ Resonance
+ A filter alone would be like an equalizer, making a
+ bright audio signal duller, but the addition of resonance
+ greatly increases the creative potential of a filter.
+ Increasing the resonance of a filter makes it emphasize
+ signals at the cutoff frequency, giving the audio signal
+ a subtle wah-wah, that is, imagine a siren sound going
+ from bright to dull to bright again periodically.
+
+ LFO1 to Volume (Tremolo)
+ The LFO1's output is routed to the amplifier, with the
+ depth of oscillation determined by LFO1 to Volume. LFO1
+ to Volume produces tremolo, which is a periodic
+ fluctuation of volume. Lets say you are listening to a
+ piece of music on your home stereo system. When you
+ rapidly increase and decrease the playback volume, you
+ are creating tremolo effect, and the speed in which you
+ increases and decreases the volume is the tremolo rate
+ (which corresponds to the speed at which the LFO is
+ oscillating). An example of a GM instrument that makes
+ use of LFO1 to Volume is instrument number 45, Tremolo
+ Strings.
+
+ LFO1 to Filter Cutoff (Wah-Wah)
+ The LFO1's output is routed to the filter, with the depth
+ of oscillation determined by LFO1 to Filter. LFO1 to
+ Filter produces a periodic fluctuation in the filter
+ cutoff frequency, producing an effect very similar to
+ that of a wah-wah guitar (see resonance for a description
+ of wah-wah) An example of a GM instrument that makes
+ use of LFO1 to Filter Cutoff is instrument number 19,
+ Rock Organ.
+
+ LFO1 to Pitch (Vibrato)
+ The LFO1's output is routed to the oscillator, with the
+ depth of oscillation determined by LFO1 to Pitch. LFO1 to
+ Pitch produces a periodic fluctuation in the pitch of the
+ oscillator, producing a vibrato effect. An example of a
+ GM instrument that makes use of LFO1 to Pitch is
+ instrument number 57, Trumpet.
+
+ LFO2 to Pitch (Vibrato)
+ The LFO1 in the EMU8000 can simultaneously modulate
+ pitch, volume and filter. LFO2, on the other hand,
+ modulates only the pitch, with the depth of modulation
+ determined by LFO2 to Pitch. LFO2 to Pitch produces a
+ periodic fluctuation in the pitch of the oscillator,
+ producing a vibrato effect. When this is coupled with
+ LFO1 to Pitch, a complex vibrato effect can be achieved.
+
+ Volume Envelope
+ The character of a musical instrument is largely
+ determined by its volume envelope, the way in which the
+ level of the sound changes with time. For example,
+ percussive sounds usually start suddenly and then die
+ away, whereas a bowed sound might take quite some time to
+ start and then sustain at a more or less fixed level.
+
+ A six-stage envelope makes up the volume envelope of the
+ EMU8000. The six stages are delay, attack, hold, decay,
+ sustain and release. The stages can be described as
+ follows:
+
+ Delay The time between when a key is played and when
+ the attack phase begins
+ Attack The time it takes to go from zero to the peak
+ (full) level.
+ Hold The time the envelope will stay at the peak
+ level before starting the decay phase.
+ Decay The time it takes the envelope to go from the
+ peak level to the sustain level.
+ Sustain The level at which the envelope remains as long
+ as a key is held down.
+ Release The time it takes the envelope to fall to the
+ zero level after the key is released.
+
+ Using these six parameters can yield very realistic
+ reproduction of the volume envelope characteristics of
+ many musical instruments.
+
+ Pitch and Filter Envelope
+ The pitch and filter envelope is similar to the volume
+ envelope in that it has the same envelope stages. The
+ difference between them is that whereas the volume
+ envelope contours the volume of the instrument over time,
+ the pitch and filter envelope contours the pitch and
+ filter values of the instrument over time. The pitch
+ envelope is particularly useful in putting the finishing
+ touches in simulating a natural instrument. For example,
+ some wind instruments tend to go slightly sharp when they
+ are first blown, and this characteristic can be simulated
+ by setting up a pitch envelope with a fairly fast attack
+ and decay. The filter envelope, on the other hand, is
+ useful in creating synthetic sci-fi sound textures. An
+ example of a GM instrument that makes use of the filter
+ envelope is instrument number 86, Pad 8 (Sweep).
+
+ Pitch/Filter Envelope Modulation
+ These two parameters determine the modulation depth of
+ the pitch and filter envelope. In the wind instrument
+ example above, a small amount of pitch envelope
+ modulation is desirable to simulate its natural pitch
+ characteristics.
+
+ This rich modulation capability of the EMU8000 is fully
+ exploited by the SB AWE32 MIDI drivers. The driver also
+ provides you with a means to change these parameters over
+ MIDI in real time. Refer to the section "How do I change an
+ instrument's sound parameter in real time" for more
+ information.
+
+
+
+
+ Room 1 - 3
+ This group of reverb variation simulates the natural
+ ambiance of a room. Room 1 simulates a small room, Room 2
+ simulates a slightly bigger room, and Room 3 simulates a
+ big room.
+
+ Hall 1 - 2
+ This group of reverb variation simulates the natural
+ ambiance of a concert hall. It has greater depth than the
+ room variations. Again, Hall 1 simulates a small hall,
+ and Hall 2 simulates a larger hall.
+
+ Plate
+ Back in the old days, reverb effects were sometimes
+ produced using a metal plate, and this type of reverb
+ produces a metallic echo. The SB AWE32's Plate variation
+ simulates this form of reverb.
+
+ Delay
+ This reverb produces a delay, that is, echo effect.
+
+ Panning Delay
+ This reverb variation produces a delay effect that is
+ continuously panned left and right.
+
+ Chorus 1 - 4
+ Chorus produces a "beating" effect. The chorus effects
+ are more prominent going from chorus 1 to chorus 4.
+
+ Feedback Chorus
+ This chorus variation simulates a soft "swishing" effect.
+
+ Flanger
+ This chorus variation produces a more prominent feedback
+ chorus effect.
+
+ Short Delay
+ This chorus variation simulates a delay repeated in a
+ short time.
+
+ Short Delay (feed back)
+ This chorus variation simulates a short delay repeated
+ (feedback) many times.
+
+
+
+Registers to write the Chorus Parameters to (all are 16-bit, unless noted):
+(codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20)
+( 3409 = register 3, port A20, voice 9)
+
+0x3409
+0x340C
+0x3603
+0x1409 (32-Bit)
+0x140A (32-Bit)
+then write 0x8000 to 0x140D (32-Bit)
+and then 0x0000 to 0x140E (32-Bit)
+
+Chorus Parameters:
+
+Chorus 1 Chorus 2 Chorus 3 Chorus 4 Feedback Flanger
+
+0xE600 0xE608 0xE610 0xE620 0xE680 0xE6E0
+0x03F6 0x031A 0x031A 0x0269 0x04D3 0x044E
+0xBC2C 0xBC6E 0xBC84 0xBC6E 0xBCA6 0xBC37
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
+0x006D 0x017C 0x0083 0x017C 0x005B 0x0026
+
+Short Delay Short Delay + Feedback
+
+0xE600 0xE6C0
+0x0B06 0x0B06
+0xBC00 0xBC00
+0xE000 0xE000
+0x0083 0x0083
+
+// 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;
+
+
+Registers to write the Reverb Parameters to (they are all 16-bit):
+(codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20)
+( 3409 = register 3, port A20, voice 9)
+
+0x2403,0x2405,0x361F,0x2407,0x2614,0x2616,0x240F,0x2417,
+0x241F,0x2607,0x260F,0x2617,0x261D,0x261F,0x3401,0x3403,
+0x2409,0x240B,0x2411,0x2413,0x2419,0x241B,0x2601,0x2603,
+0x2609,0x260B,0x2611,0x2613
+
+Reverb Parameters:
+
+Room 1:
+
+0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,0x72A4,
+0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,0xA490,0xA590,
+0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
+0x8428,0x8528,0x8428,0x8528
+
+Room 2:
+
+0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
+0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540,
+0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
+0x8428,0x8528,0x8428,0x8528
+
+Room 3:
+
+0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
+0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,0xA490,0xA590,
+0x842C,0x852C,0x842C,0x852C,0x842B,0x852B,0x842B,0x852B,
+0x842A,0x852A,0x842A,0x852A
+
+Hall 1:
+
+0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
+0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540,
+0x842B,0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A,
+0x8429,0x8529,0x8429,0x8529
+
+Hall 2:
+
+0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,0x7234,
+0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,0xA404,0xA504,
+0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
+0x8428,0x8528,0x8428,0x8528
+
+Plate:
+
+0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,0x7234,
+0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,0xA440,0xA540,
+0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
+0x8428,0x8528,0x8428,0x8528
+
+Delay:
+
+0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,0x7204,
+0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF,
+0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
+0x8420,0x8520,0x8420,0x8520
+
+Panning Delay:
+
+0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,0x7204,
+0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF,
+0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
+0x8420,0x8520,0x8420,0x8520
+
+Registers to write the EQ Parameters to (16-Bit):
+(codified as in register,port,voice. port 0=0x620, 2=0x622, 4=0xA20, 6=0xA22, 8=0xE20)
+( 3409 = register 3, port A20, voice 9)
+
+Bass:
+
+0x3601
+0x3611
+
+Treble:
+
+0x3411
+0x3413
+0x341B
+0x3607
+0x360B
+0x360D
+0x3617
+0x3619
+
+Total:
+
+write the 0x0263 + 3rd parameter of the Bass EQ + 9th parameter of Treble EQ to 0x3615.
+write the 0x8363 + 3rd parameter of the Bass EQ + 9th parameter of Treble EQ to 0x3615.
+
+
+Bass Parameters:
+
+0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
+
+0xD26A 0xD25B 0xD24C 0xD23D 0xD21F 0xC208 0xC219 0xC22A 0xC24C 0xC26E 0xC248 0xC26A
+0xD36A 0xD35B 0xD34C 0xD33D 0xC31F 0xC308 0xC308 0xC32A 0xC34C 0xC36E 0xC384 0xC36A
+0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002
+
+Treble Parameters:
+
+0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
+0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821E 0x821D 0x821C
+0xC26A 0xC25B 0xC24C 0xC23D 0xC21F 0xD208 0xD208 0xD208 0xD208 0xD208 0xD219 0xD22A
+0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031E 0x031D 0x031C
+0xC36A 0xC35B 0xC34C 0xC33D 0xC31F 0xD308 0xD308 0xD308 0xD308 0xD308 0xD319 0xD32A
+0x021E 0x021E 0x021E 0x021E 0x021E 0x021E 0x021D 0x021C 0x021A 0x0219 0x0219 0x0219
+0xD208 0xD208 0xD208 0xD208 0xD208 0xD208 0xD219 0xD22A 0xD24C 0xD26E 0xD26E 0xD26E
+0x831E 0x831E 0x831E 0x831E 0x831E 0x831E 0x831D 0x831C 0x831A 0x8319 0x8319 0x8319
+0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E
+0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002
+*/
+
+#endif /* _SOUND_EMU8K_H_ */