psx.wiki
Log in
Main page
Hardware
Hardware tests
System software
SDKs
File formats
Games
Tools
History
All pages
page
view source
history
View source for SPU ADSR and Volume
← SPU ADSR and Volume
You do not have permission to edit this page.
Log in
to edit.
--- title: SPU ADSR and Volume type: register summary: Envelope and volume sweep encodings of the SPU voices. category: Hardware --- ## Summary Each [SPU](/hardware/spu/) voice has an envelope generator and a left and right volume. The envelope has separate rates for attack, decay, sustain and release, and a settable sustain level. Linear or exponential curves can be chosen for each phase except decay, which is always exponential.[^hw45] The volume of each side is set apart from the envelope. It can be held constant or changed over time by linear increment, linear decrement, reverse indexed increment or indexed decrement.[^hw46] The register addresses are listed in [SPU Registers](/hardware/spu/registers/). ## Envelope Phases Key On starts the attack at an envelope level of zero. The hardware then goes through attack, decay and sustain by itself, and moves from sustain to release when Key Off is written.[^spxadsr] Attack rises to the maximum level 7FFFh and decay falls to the sustain level. Sustain rises or falls until Key Off, and release falls to zero.[^spxadsr] Sony's conceptual diagram shows the same four phases and five settings:[^ref15114] Table: Rate and level setting ranges | Attribute | Structure Member | Setting Range | | --- | --- | --- | | Attack rate | attr.ar | 0x00 to 0x7f | | Decay rate | attr.dr | 0x0 to 0xf | | Sustain rate | attr.sr | 0x00 to 0x7f | | Release rate | attr.rr | 0x00 to 0x1f | | Sustain level | attr.sl | 0x0 to 0xf | The rate curves that libspu accepts for each phase are as follows. Decay cannot be set because only exponential decrease may be used for it.[^ref15114] Table: ADSR rate modes | Attribute | Settable modes | | --- | --- | | Attack rate (attr.a_mode) | SPU_VOICE_LINEARIncN, SPU_VOICE_EXPIncN | | Sustain rate (attr.s_mode) | SPU_VOICE_LINEARIncN, SPU_VOICE_LINEARDecN, SPU_VOICE_EXPIncN, SPU_VOICE_EXPDec | | Release rate (attr.r_mode) | SPU_VOICE_LINEARDecN, SPU_VOICE_EXPDec | ## ADSR1 and ADSR2 ADSR1 (1F801C08h + N x 10h) and ADSR2 (1F801C0Ah + N x 10h) together hold one 32-bit envelope setting. ADSR1 is bits 0 to 15 and ADSR2 is bits 16 to 31.[^spxadsr] Each rate is a shift and a step: the shift runs from fast to slow, and the step adds +7, +6, +5 or +4 when the level rises or -8, -7, -6 or -5 when it falls. The ranges of libspu match these fields: the 7-bit attack and sustain rates (0x00 to 0x7f) are a 5-bit shift and a 2-bit step, the 5-bit release rate is the shift alone, and the 4-bit decay rate is the decay shift.[^spxadsr][^ref15114] Table: ADSR bits | Bits | Contents | | --- | --- | | 31 | Sustain mode (0 = linear, 1 = exponential) | | 30 | Sustain direction (0 = increase, 1 = decrease) | | 29 | Not used, should be zero | | 24 to 28 | Sustain shift (0 to 1Fh) | | 22 to 23 | Sustain step (0 to 3) | | 21 | Release mode (0 = linear, 1 = exponential) | | 16 to 20 | Release shift (0 to 1Fh). Release always decreases with step -8. | | 15 | Attack mode (0 = linear, 1 = exponential). Attack always increases. | | 10 to 14 | Attack shift (0 to 1Fh) | | 8 to 9 | Attack step (0 to 3 for +7 to +4) | | 4 to 7 | Decay shift (0 to 0Fh). Decay is always exponential with step -8. | | 0 to 3 | Sustain level. The level is (N + 1) x 800h. | libspu can also write the two halfwords directly from the VagAtr members adsr1 and adsr2. In that case only SPU_VOICE_ADSR_ADSR1 and SPU_VOICE_ADSR_ADSR2 may be set for the envelope in attr.mask.[^ref15115] ## Envelope Step The envelope advances once per 44.1 kHz cycle by the following rule. The step and the counter increment are worked out from the shift and step of the current phase.[^spxenv] ``` AdsrStep = 7 - StepValue if Decreasing xor PhaseNegative: AdsrStep = not AdsrStep ; +7..+4 becomes -8..-5 AdsrStep = AdsrStep << max(0, 11 - ShiftValue) CounterIncrement = 8000h >> max(0, ShiftValue - 11) if exponential and increasing and Level > 6000h: if ShiftValue < 10: AdsrStep = AdsrStep / 4 else if ShiftValue >= 11: CounterIncrement = CounterIncrement / 4 else: AdsrStep = AdsrStep / 2, CounterIncrement = CounterIncrement / 2 else if exponential and decreasing: AdsrStep = AdsrStep * Level / 8000h if (StepValue | (ShiftValue << 2)) is not all ones: CounterIncrement = max(CounterIncrement, 1) Counter = Counter + CounterIncrement if Counter bit 15 is clear: no step this cycle Level = Level + AdsrStep, then saturate ``` The exponential increase is therefore not a true curve. It is a linear increase that changes to a slower rate above level 6000h.[^spxenv] A rate with every bit set never steps and never saturates, so the level stays where it is. This is the value 7Fh for attack and sustain and 1Fh for decay and release.[^spxenv] ## ENVX ENVX (1F801C0Ch + N x 10h) reads the current envelope level (0 to +7FFFh). Software most often reads it to find whether a voice has finished its release and is idle.[^spxadsr] A write to ENVX sets the level directly. However, the generator overwrites the level from an internal register at its next step.[^spxadsr] ## Volume Registers MVOLL and MVOLR (main volume) and VOLL and VOLR of each voice have two modes. Bit 15 selects the mode.[^spxvol] Table: Volume register in direct mode | Bits | Contents | | --- | --- | | 15 | 0 (direct mode) | | 0 to 14 | Volume / 2 (-4000h to +3FFFh for a volume of -8000h to +7FFEh) | Table: Volume register in sweep mode | Bits | Contents | | --- | --- | | 15 | 1 (sweep mode) | | 14 | Sweep mode (0 = linear, 1 = exponential) | | 13 | Sweep direction (0 = increase, 1 = decrease) | | 12 | Sweep phase (0 = positive, 1 = negative) | | 7 to 11 | Not used, should be zero | | 2 to 6 | Sweep shift (0 to 1Fh, fast to slow) | | 0 to 1 | Sweep step (0 to 3 for +7 to +4 or -8 to -5) | A sweep is a second envelope on top of the ADSR envelope. Unlike the ADSR envelope it can differ between left and right, which allows effects such as a pan from left to right.[^spxvol] It starts at the current volume and moves toward +7FFFh or 0000h by the same stepping rule as the envelope.[^spxvol][^spxenv] The direct-mode value is applied at the next 44.1 kHz cycle. Software that sets a start level in direct mode and then a sweep must therefore wait between the two writes.[^spxvol] A negative volume inverts the phase of the output and is otherwise the same as a positive volume.[^spxneg] Games use phase inversion for Dolby Surround, where an inverted sound plays from the rear speakers.[^spxenv] ## libspu Volume Modes Sony's libspu names the volume modes as follows. The direct mode takes -0x4000 to 0x3fff and the sweep modes take a rate of 0x00 to 0x7f.[^ref15112] Table: Volume mode and volume setting ranges | Mode (phase) | SPU_VOICE_VOLMODEx | SPU_VOICE_VOLx | | --- | --- | --- | | Direct mode | SPU_VOICE_DIRECT | -0x4000 to 0x3fff | | Linear inc. mode | SPU_VOICE_LINEARIncN | 0x00 to 0x7f (normal) | | Linear inc. mode | SPU_VOICE_LINEARIncR | 0x00 to 0x7f (inverted) | | Linear dec. mode | SPU_VOICE_LINEARDecN | 0x00 to 0x7f (normal) | | Linear dec. mode | SPU_VOICE_LINEARDecR | 0x00 to 0x7f (inverted) | | Expon. inc. mode | SPU_VOICE_EXPIncN | 0x00 to 0x7f (normal) | | Expon. inc. mode | SPU_VOICE_EXPIncR | 0x00 to 0x7f (inverted) | | Expon. dec. mode | SPU_VOICE_EXPDec | 0x00 to 0x7f | Direct mode is the default and gives a fixed volume. The increase and decrease modes move the current volume to the maximum or the minimum value, in normal phase when the current volume is positive and in inverted phase when it is negative. The exponential decrease mode works the same whatever the sign of the current volume.[^ref15113] ## References [^hw45]: Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 4-5, Figure 4-4. [^hw46]: Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 4-6, Figure 4-5. [^ref15112]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 15-112, Table 15-7. [^ref15113]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 15-113. [^ref15114]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 15-114, Figure 15-1, Table 15-10, Table 15-11. [^ref15115]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 15-115. [^spxadsr]: psx-spx. Sound Processing Unit (SPU), SPU Volume and ADSR Generator, ADSR1, ADSR2 and ENVX. https://psx-spx.consoledev.net/soundprocessingunitspu/ [^spxvol]: psx-spx. Sound Processing Unit (SPU), SPU Volume and ADSR Generator, MVOLL, MVOLR, VOLL and VOLR. https://psx-spx.consoledev.net/soundprocessingunitspu/ [^spxenv]: psx-spx. Sound Processing Unit (SPU), Envelope Operation depending on Shift/Step/Mode/Direction. https://psx-spx.consoledev.net/soundprocessingunitspu/ [^spxneg]: psx-spx. Sound Processing Unit (SPU), SPU Volume and ADSR Generator, Note. https://psx-spx.consoledev.net/soundprocessingunitspu/