SPU Reverb
Digital reverb unit of the SPU with its registers and its work area.
Summary
The SPU has a digital reverb that uses the sound buffer as its work area. Reverb is switched on or off voice by voice, and it can also be applied to the CD input.1 Sony provides reverb as a set of templates whose parameters can be adjusted, and only one type of reverb can be active at a time.2 Sony never documented the reverb registers. The names on this page are unofficial names from psx-spx.3
psx-spx describes the unit as a stereo Schroeder reverberator. It replaced the echo of the SNES sound chip, and its inputs from the CD-ROM drive and the expansion port can also be sent through it.4
Registers
Three registers outside the reverb area also control the reverb:5
| Address | Name | Contents |
|---|---|---|
| 1F801D84h | EVOLL | Reverb output volume left |
| 1F801D86h | EVOLR | Reverb output volume right |
| 1F801DA2h | ESA | Start address of the reverb work area |
| 1F801D98h, 1F801D9Ah | EON0, EON1 | Voices 0 to 23 sent to the reverb |
| 1F801DAAh | ATTR | Bit 7 reverb master enable, bit 2 CD input reverb, bit 3 external input reverb |
The reverb configuration area holds 32 registers. The volumes are signed 16-bit values from -8000h to +7FFFh. The addresses and displacements are in 8-byte units like every sound buffer address in the SPU.5
| Address | Name | Type | Contents |
|---|---|---|---|
| 1F801DC0h | dAPF1 | disp | APF offset 1 |
| 1F801DC2h | dAPF2 | disp | APF offset 2 |
| 1F801DC4h | vIIR | volume | Reflection volume 1 |
| 1F801DC6h | vCOMB1 | volume | Comb volume 1 |
| 1F801DC8h | vCOMB2 | volume | Comb volume 2 |
| 1F801DCAh | vCOMB3 | volume | Comb volume 3 |
| 1F801DCCh | vCOMB4 | volume | Comb volume 4 |
| 1F801DCEh | vWALL | volume | Reflection volume 2 |
| 1F801DD0h | vAPF1 | volume | APF volume 1 |
| 1F801DD2h | vAPF2 | volume | APF volume 2 |
| 1F801DD4h | mLSAME | src/dst | Same side reflection address 1 left |
| 1F801DD6h | mRSAME | src/dst | Same side reflection address 1 right |
| 1F801DD8h | mLCOMB1 | src | Comb address 1 left |
| 1F801DDAh | mRCOMB1 | src | Comb address 1 right |
| 1F801DDCh | mLCOMB2 | src | Comb address 2 left |
| 1F801DDEh | mRCOMB2 | src | Comb address 2 right |
| 1F801DE0h | dLSAME | src | Same side reflection address 2 left |
| 1F801DE2h | dRSAME | src | Same side reflection address 2 right |
| 1F801DE4h | mLDIFF | src/dst | Different side reflection address 1 left |
| 1F801DE6h | mRDIFF | src/dst | Different side reflection address 1 right |
| 1F801DE8h | mLCOMB3 | src | Comb address 3 left |
| 1F801DEAh | mRCOMB3 | src | Comb address 3 right |
| 1F801DECh | mLCOMB4 | src | Comb address 4 left |
| 1F801DEEh | mRCOMB4 | src | Comb address 4 right |
| 1F801DF0h | dLDIFF | src | Different side reflection address 2 left |
| 1F801DF2h | dRDIFF | src | Different side reflection address 2 right |
| 1F801DF4h | mLAPF1 | src/dst | APF address 1 left |
| 1F801DF6h | mRAPF1 | src/dst | APF address 1 right |
| 1F801DF8h | mLAPF2 | src/dst | APF address 2 left |
| 1F801DFAh | mRAPF2 | src/dst | APF address 2 right |
| 1F801DFCh | vLIN | volume | Input volume left |
| 1F801DFEh | vRIN | volume | Input volume right |
The src and dst registers are relative to the current buffer address, and the disp registers are relative to the src registers. ESA sets the start of the work area, while the end is fixed at 7FFFEh. A write to ESA also sets the current buffer address.5
A voice with its EON bit set goes to the mixer directly and to the reverb as well, so the dry sound is heard at once and the reverb later.5
Reverb Formula
The reverb runs at 22050 Hz. In each cycle it reads the inputs, works the reflections, the comb filter and two all-pass filters, and writes the output:6
Lin = vLIN * LeftInput ; voices with reverb enabled
Rin = vRIN * RightInput
; same side reflection
[mLSAME] = (Lin + [dLSAME]*vWALL - [mLSAME-2])*vIIR + [mLSAME-2]
[mRSAME] = (Rin + [dRSAME]*vWALL - [mRSAME-2])*vIIR + [mRSAME-2]
; different side reflection
[mLDIFF] = (Lin + [dRDIFF]*vWALL - [mLDIFF-2])*vIIR + [mLDIFF-2]
[mRDIFF] = (Rin + [dLDIFF]*vWALL - [mRDIFF-2])*vIIR + [mRDIFF-2]
; early echo (comb filter)
Lout = vCOMB1*[mLCOMB1] + vCOMB2*[mLCOMB2] + vCOMB3*[mLCOMB3] + vCOMB4*[mLCOMB4]
Rout = vCOMB1*[mRCOMB1] + vCOMB2*[mRCOMB2] + vCOMB3*[mRCOMB3] + vCOMB4*[mRCOMB4]
; late reverb, all-pass filter 1
Lout = Lout - vAPF1*[mLAPF1-dAPF1], [mLAPF1] = Lout, Lout = Lout*vAPF1 + [mLAPF1-dAPF1]
Rout = Rout - vAPF1*[mRAPF1-dAPF1], [mRAPF1] = Rout, Rout = Rout*vAPF1 + [mRAPF1-dAPF1]
; late reverb, all-pass filter 2
Lout = Lout - vAPF2*[mLAPF2-dAPF2], [mLAPF2] = Lout, Lout = Lout*vAPF2 + [mLAPF2-dAPF2]
Rout = Rout - vAPF2*[mRAPF2-dAPF2], [mRAPF2] = Rout, Rout = Rout*vAPF2 + [mRAPF2-dAPF2]
; output
LeftOutput = Lout * EVOLL
RightOutput = Rout * EVOLR
BufferAddress = max(ESA, (BufferAddress + 2) and 7FFFEh)
Every product is divided by 8000h to stay in 16 bits, and every value written to memory is saturated to -8000h to +7FFFh. All addresses are relative to the current buffer address and wrap within ESA to 7FFFEh.7 The hardware works the left side in one 44.1 kHz cycle and the right side in the next, which is why the whole unit runs at half rate.7 Input to and output from the unit are resampled with a 39-tap FIR filter.8
The work area holds signed 16-bit samples. The left and right addresses should place all left samples in one half of the area and all right samples in the other half. As the buffer address advances, each half then overwrites the oldest samples of the other.7
vIIR works only from -7FFFh to +7FFFh. When it is -8000h the result written to memory is negated.9
Reverb Disable
ATTR bit 7 stops the writes to the work area, but the reads go on. With vAPF2 at zero the output is the samples read at the APF2 address. With vAPF2 set the APF1 stage is used as well, and with both APF volumes set the comb stage too. The reflection stages are not used while reverb is disabled.10 To silence the reverb output, EVOLL and EVOLR are set to zero or the work area is cleared.5
Work Area
The work area runs from ESA to the end of the sound buffer. Its size depends on the reverb mode, and Sony gives the sizes as follows:11
| attr.mode | mode | hexadecimal | decimal |
|---|---|---|---|
| SPU_REV_MODE_OFF | off | 0 or 80 | 0 or 128 |
| SPU_REV_MODE_ROOM | room | 26c0 | 9920 |
| SPU_REV_MODE_STUDIO_A | studio (small) | 1f40 | 8000 |
| SPU_REV_MODE_STUDIO_B | studio (med) | 4840 | 18496 |
| SPU_REV_MODE_STUDIO_C | studio (big) | 6fe0 | 28640 |
| SPU_REV_MODE_HALL | hall | ade0 | 44512 |
| SPU_REV_MODE_SPACE | space echo | f6c0 | 63168 |
| SPU_REV_MODE_ECHO | echo | 18040 | 98368 |
| SPU_REV_MODE_DELAY | delay | 18040 | 98368 |
| SPU_REV_MODE_PIPE | half echo | 3c00 | 15360 |
The off mode takes 128 bytes when SpuReserveReverbWorkArea(SPU_ON) has been used and none otherwise.12 ESA for a mode is therefore (80000h - size) / 8. For the hall mode this is (80000h - ADE0h) / 8 = EA44h.13
A change of mode sets the reverb depth to 0, because the size of the work area changes and old data in it would produce noise. The depth must then be set again with SpuSetReverbModeParam() or SpuSetReverbDepth().11 Sony therefore asks that the mode be set well in advance and the depth only when reverb is needed. Otherwise the work area must be cleared with SpuClearReverbWorkArea() first.2 The depth runs from -0x8000 to 0x7fff on each side, and a negative depth inverts the phase of the wet sound. Delay time and feedback (0 to 127) apply only to the echo and delay modes.12
The area below the reverb offset address can hold waveform data.2 A program that uses reverb must set the mode to off and call SpuSetReverb(SPU_OFF) before it exits. Otherwise noise may occur the next time a program runs.14
Register Settings
psx-spx lists the register values of each template in the order of 1F801DC0h to 1F801DFEh:13
dAPF1 dAPF2 vIIR vCOMB1 vCOMB2 vCOMB3 vCOMB4 vWALL ; 1F801DC0h
vAPF1 vAPF2 mLSAME mRSAME mLCOMB1 mRCOMB1 mLCOMB2 mRCOMB2 ; 1F801DD0h
dLSAME dRSAME mLDIFF mRDIFF mLCOMB3 mRCOMB3 mLCOMB4 mRCOMB4 ; 1F801DE0h
dLDIFF dRDIFF mLAPF1 mRAPF1 mLAPF2 mRAPF2 vLIN vRIN ; 1F801DF0h
| Template | Size | Values |
|---|---|---|
| Room | 26C0h | 007D 005B 6D80 54B8 BED0 0000 0000 BA80 5800 5300 04D6 0333 03F0 0227 0374 01EF 0334 01B5 0000 0000 0000 0000 0000 0000 0000 0000 01B4 0136 00B8 005C 8000 8000 |
| Studio Small | 1F40h | 0033 0025 70F0 4FA8 BCE0 4410 C0F0 9C00 5280 4EC0 03E4 031B 03A4 02AF 0372 0266 031C 025D 025C 018E 022F 0135 01D2 00B7 018F 00B5 00B4 0080 004C 0026 8000 8000 |
| Studio Medium | 4840h | 00B1 007F 70F0 4FA8 BCE0 4510 BEF0 B4C0 5280 4EC0 0904 076B 0824 065F 07A2 0616 076C 05ED 05EC 042E 050F 0305 0462 02B7 042F 0265 0264 01B2 0100 0080 8000 8000 |
| Studio Large | 6FE0h | 00E3 00A9 6F60 4FA8 BCE0 4510 BEF0 A680 5680 52C0 0DFB 0B58 0D09 0A3C 0BD9 0973 0B59 08DA 08D9 05E9 07EC 04B0 06EF 03D2 05EA 031D 031C 0238 0154 00AA 8000 8000 |
| Hall | ADE0h | 01A5 0139 6000 5000 4C00 B800 BC00 C000 6000 5C00 15BA 11BB 14C2 10BD 11BC 0DC1 11C0 0DC3 0DC0 09C1 0BC4 07C1 0A00 06CD 09C2 05C1 05C0 041A 0274 013A 8000 8000 |
| Half Echo | 3C00h | 0017 0013 70F0 4FA8 BCE0 4510 BEF0 8500 5F80 54C0 0371 02AF 02E5 01DF 02B0 01D7 0358 026A 01D6 011E 012D 00B1 011F 0059 01A0 00E3 0058 0040 0028 0014 8000 8000 |
| Space Echo | F6C0h | 033D 0231 7E00 5000 B400 B000 4C00 B000 6000 5400 1ED6 1A31 1D14 183B 1BC2 16B2 1A32 15EF 15EE 1055 1334 0F2D 11F6 0C5D 1056 0AE1 0AE0 07A2 0464 0232 8000 8000 |
| Chaos Echo | 18040h | 0001 0001 7FFF 7FFF 0000 0000 0000 8100 0000 0000 1FFF 0FFF 1005 0005 0000 0000 1005 0005 0000 0000 0000 0000 0000 0000 0000 0000 1004 1002 0004 0002 8000 8000 |
| Delay | 18040h | 0001 0001 7FFF 7FFF 0000 0000 0000 0000 0000 0000 1FFF 0FFF 1005 0005 0000 0000 1005 0005 0000 0000 0000 0000 0000 0000 0000 0000 1004 1002 0004 0002 8000 8000 |
| Off | 10h | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0001 0001 0001 0001 0001 0000 0000 0001 0001 0001 0001 0001 0001 0000 0000 0001 0001 0001 0001 0000 0000 |
The sizes match the work area sizes in Sony's table. The Chaos Echo and Delay templates have the size of Sony's echo and delay modes, and their settings differ only in vWALL.1311
Before reverb is turned on, EVOLL, EVOLR, EON and ATTR must be set and the work area cleared, so that no old data is heard. RAM_CTRL must also be set, or the reverb stays off.13 The off template uses memory offsets of 0001h rather than 0000h. With zero offsets, clearing the work area does not work reliably.13
References
-
^ Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 4-6.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 16-5.
-
^ psx-spx. Sound Processing Unit (SPU), SPU I/O Port Summary. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ psx-spx. Sound Processing Unit (SPU). https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ a b c d e psx-spx. Sound Processing Unit (SPU), SPU Reverb Registers. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ psx-spx. Sound Processing Unit (SPU), SPU Reverb Formula. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ a b c psx-spx. Sound Processing Unit (SPU), SPU Reverb Formula, Notes. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ psx-spx. Sound Processing Unit (SPU), SPU Reverb Formula, Reverb Buffer Resampling. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ psx-spx. Sound Processing Unit (SPU), SPU Reverb Formula, Bug. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ psx-spx. Sound Processing Unit (SPU), SPU Reverb Formula, Reverb Disable. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 15-101, Table 15-5.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 15-102.
-
^ a b c d e psx-spx. Sound Processing Unit (SPU), SPU Reverb Examples. https://psx-spx.consoledev.net/soundprocessingunitspu/
-
^ Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 16-6.