==========================================================================
SPU - Sound Processing Unit. Information & Documentation.
==========================================================================

Disclaimer.
--------------------------------------------------------------------------
This document is a collection of all info on the SPU i could find and my
own notes. Most of this is the result of experiment, so not all info might
be correct. This document is most probably not complete, and not all
capabilities and quirks of the SPU are documented. No responsibility is
taken for anything that might occur using the information in this document.


Introduction.
--------------------------------------------------------------------------
The SPU is the unit responsible for all aural capabilities of the psx. It
handles 24 voices, has a 512kb sound buffer, has ADSR envelope filters for
each voice and lots of other features.


Notations and conventions
When the format of data is given it's shown as a bitwise representation
like this:


bit  |0f|0e 0d 0c 0b 0a|09 08 07 06 05|04 03 02 01 00|
desc.|                                               |

The bit row shows which bits of the data are used, and separators are used
to show where the different elements of the data stop and start. MSB is on
the left, LSB is on the right. Stuff like |0f-08| means bit $0f to bit $08.
The desc. row shows the description of the different elements. With
separators where the element starts and ends.



--------------------------------------------------------------------------
The Sound Buffer
--------------------------------------------------------------------------

The SPU has control over a 512kb sound buffer. Data is stored compressed
into blocks of 16 bytes. Each block contains 14 packed sample bytes and two
header bytes, one for the packing and one for sample end and looping
information. One such block is decoded into 28 sample bytes (= 14 16bit
samples).

In the first 4 kb of the buffer the SPU stores the decoded data of CD audio
after volume processing and the sound data of voice 1 and voice 3 after
envelope processing. The decoded data is stored as 16 bit signed values,
one sample per clock (44.1 khz).

Following this first 4kb are 8 bytes reserved by the system. The memory
beyond that is free to store samples, up to the reverb work area if the
effect processor is used. The size of this work area depends on which
type of effect is being processed. More on that later.

Memory layout:
$00000-$003ff  CD audio left
$00400-$007ff  CD audio right
$00800-$00bff  Voice 1
$00c00-$00fff  Voice 3
$01000-$0100f  System area.
$01008-$xxxxx  Sound data area.
$0xxxx-$7ffff  Reverb work area.

--------------------------------------------------------------------------
Voices.
--------------------------------------------------------------------------
The SPU has 24 hardware voices. These voices can be used to reproduce sample
data, noise or can be used as frequency modulator on the next voice.
Each voice has it's own programmable ADSR envelope filter. The main volume
can be programmed independently for left and right output.

The ADSR envelope filter works as follows:
Ar = Attack rate, which specifies the speed at which the volume increases
     from zero to it's maximum value, as soon as the note on is given. The
     slope can be set to lineair or exponential.
Dr = Decay rate specifies the speed at which the volume decreases to the
     sustain level. Decay is always decreasing exponentially.
Sl = Sustain level, base level from which sustain starts.
Sr = Sustain rate is the rate at which the volume of the sustained note
     increases or decreases. This can be either lineair or exponential.
Rr = Release rate is the rate at which the volume of the note decreases
     as soon as the note off is given.

     lvl |
       ^ |     /\Dr     __
     Sl _| _  / _ \__---  \
         |   /       ---__ \ Rr
         |  /Ar       Sr  \ \
         | /                \\
         |/___________________\________
                                  ->time

The overal volume can also be set to sweep up or down lineairly or
exponentially from it's current value. This can be done seperately
for left and right.


--------------------------------------------------------------------------
SPU Operation
--------------------------------------------------------------------------

The SPU occupies the area $1f801c00-$1f801dff. All registers are 16 bit
wide.

=============================================================
$1f801c00-        Voice data area. For each voice there are 8 16 bit
$1f801d7f         registers structured like this:

(xx = $c0 + voice number)
-------------------------------------------------------------
$1f801xx0         Volume Left
$1f801xx2         Volume Right

Volume mode:
bit  |0f|0e|0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.| 0| S|               VV                        |

VV  $0000-$3fff   Voice volume.
S        0        Phase Normal
         1              Inverted

Sweep mode:
bit  |0f|0e|0d|0c|0b 0a 09 08 07|06 05 04 03 02 01 00|
desc.| 1|Sl|Dr|Ph|              |VV                  |

VV  $0000-$007f   Voice volume.
Sl       0        Lineair slope
         1        Exponential slope
Dr       0        Increase
         1        Decrease
Ph       0        Normal phase
         1        Inverted phase

In sweep mode, the current volume increases to its maximum value,
or decreases to its mimimum value, according to mode. Choose
phase equal to the the phase of the current volume.
-------------------------------------------------------------
$1f801xx4         Pitch
bit  |0f 0e|0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|     |Pt                                       |

Pt  $0000-$3fff   Specifies pitch.

Any value can be set, table shows only octaves:
$0200  - 3 octaves
$0400  - 2
$0800  - 1
$1000  sample pitch
$2000  + 1
$3fff  + 2
-------------------------------------------------------------
$1f801xx6         Startaddress of Sound
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|Addr                                           |

Addr     Startaddress of sound in Sound buffer /8
-------------------------------------------------------------
$1f801xx8         Attack/Decay/Sustain level
bit  |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
desc.|Am|         Ar         |Dr         |Sl         |

Am       0        Attack mode Linear
         1                    Exponential

Ar       0-7f     attack rate
Dr       0-f      decay rate
Sl       0-f      sustain level
-------------------------------------------------------------
$1f801xxa         Sustain rate, Release Rate.
bit  |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
desc.|Sm|Sd| 0|   Sr               |Rm|Rr            |

Sm       0        sustain rate mode linear
         1                          exponential
Sd       0        sustain rate mode increase
         1                          decrease
Sr       0-7f     Sustain Rate
Rm       0        Linear decrease
         1        Exponential decrease
Rr       0-1f     Release Rate

Note: decay mode is always Expontial decrease, and thus cannot
be set.
-------------------------------------------------------------
$1f801xxc         Current ADSR volume
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|ADSRvol                                        |

ADSRvol           Returns the current envelope volume when
                  read.
-------------------------------------------------------------
$1f801xxe         Repeat address.
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|Ra                                             |

Ra  $0000-$ffff   Address sample loops to at end.

Note: Setting this register only has effect after the voice
has started (ie. KeyON), else the loop address gets reset
by the sample.
=============================================================
$1f801d80         Mainvolume left
$1f801d82         Mainvolume right
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|                                               |

Sets Main volume, these work the same as the channel volume
registers. See those for details.
-------------------------------------------------------------
$1f801d84         Reverberation depth left
$1f801d86         Reverberation depth right
bit  |0f|0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|P |Rvd                                         |

Rvd $0000-$7fff   Sets the wet volume for the effect.
P        0        Normal phase
         1        Inverted phase
=============================================================
Following registers have a common layout:

first register:
bit  |0f|0e|0d|0c|0b|0a|09|08|07|06|05|04|03|02|01|00|
desc.|cf|ce|cd|cc|cb|ca|c9|c8|c7|c6|c5|c4|c3|c2|c1|c0|

second register:
bit  |0f           08|07 |06 |05 |04 |03 |02 |01 | 00|
desc.|              0|c17|c16|c15|c14|c13|c12|c11|c10|

c0-c17   0        Mode for channel c?? off
         1        Mode for channel c?? on
-------------------------------------------------------------
$1f801d88         Voice ON  (0-15)
$1f801d8a         Voice ON  (16-23)

Sets the current voice to key on. (ie. start ads)
-------------------------------------------------------------
$1f801d8c         Voice OFF (0-15)
$1f801d8e         Voice OFF (16-23)

Sets the current voice to key off.(ie. release)
-------------------------------------------------------------
$1f801d90         Channel FM (pitch lfo) mode (0-15)
$1f801d92         Channel FM (pitch lfo) mode (16-23)

Sets the channel frequency modulation. Uses the previous channel
as modulator.
-------------------------------------------------------------
$1f801d94         Channel Noise mode (0-15)
$1f801d96         Channel Noise mode (16-23)

Sets the channel to noise.
-------------------------------------------------------------
$1f801d98         Channel Reverb mode (0-15)
$1f801d9a         Channel Reverb mode (16-23)

Sets reverb for the channel. As soon as the sample ends, the
reverb for that channel is turned off.
-------------------------------------------------------------
$1f801d9c         Channel ON/OFF (0-15)                 ?
$1f801d9e         Channel ON/OFF (16-23)                ?

Returns wether the channel is mute or not.              ?
=============================================================
$1f801da2         Reverb work area start
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|Revwa                                          |

Revwa $0000-$ffff Reverb work area start in sound buffer /8
-------------------------------------------------------------
$1f801da4         Sound buffer IRQ address.
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|IRQa                                           |

IRQa  $0000-$ffff IRQ address in sound buffer /8
??
-------------------------------------------------------------
$1f801da6         Sound buffer address
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|Sba                                            |

SBA $0000-$ffff   Address in sound buffer divided by eight.
                  Next transfer to this address.
-------------------------------------------------------------
$1f801da8         SPU data
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|                                               |

Data forwarding reg, for non DMA transfer.
-------------------------------------------------------------
$1f801daa         SPU control                sp0
bit  |0f|0e|0d 0c 0b 0a 09 08|07|06 |05 04|03|02|01|00|
desc.|En|Mu|Noise            |Rv|Irq|DMA  |Er|Cr|Ee|Ce|

En       0        SPU off
         1        SPU on
Mu       0        Mute SPU
         1        Unmute SPU
Noise             Noise clock frequency
Rv       0        Reverb Disabled
         1        Reverb Enabled
Irq      0        Irq disabled
         1        Irq enabled
DMA     00
        01        Non DMA write?  (transfer through data reg)
        10        DMA Write
        11        DMA Read
Er       0        Reverb for external off
         1        Reverb for external on
Cr       0        Reverb for CD off
         1        Reverb for CD on
Ee       0        External audio off
         1        External audio on
Ce       0        CD audio off
         1        CD audio on
-------------------------------------------------------------
$1f801dac         SPU status
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|                                               |

Don't know what this is for, but in SPU init routines this
register get loaded with $4.
-------------------------------------------------------------
$1f801dae         SPU status
bit  |0f 0e 0d 0c|0b|0a|09 08 07 06 05 04 03 02 01 00|
desc.|           |Dh|Rd|                             |

Dh       0        Decoding in first half of buffer
         1        Decoding in second half of buffer
Rd       0        Spu ready to transfer
         1        Spu not ready

Some of bits 9-0 are also ready/not ready states. More on
that later. Functions that wait for the SPU to be ready,
wait for bits a-0 to become 0.
-------------------------------------------------------------
$1f801db0         CD volume left
$1f801db2         CD volume right
bit  |0f|0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|P |CDvol                                       |

CDvol $0000-$7fff Set volume of CD input.
P        0        Normal phase.
         1        Inverted phase.
-------------------------------------------------------------
$1f801db4         Extern volume left
$1f801db6         Extern volume right
bit  |0f|0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
desc.|P |Exvol                                       |

Exvol $0000-$7fff Set volume of External input.
P        0        Normal phase.
         1        Inverted phase.
-------------------------------------------------------------
1dc0-1dff         Reverb configuration area
$1f801dc0         
$1f801dc2
$1f801dc4         Lowpass Filter Frequency. 7fff = max value= no filtering
$1f801dc6         Effect volume 0 - $7fff, bit 15 = phase.
$1f801dc8
$1f801dca
$1f801dcc
$1f801dce         Feedback
$1f801dd0
$1f801dd2
$1f801dd4         Delaytime(see below)
$1f801dd6         Delaytime(see below)
$1f801dd8         Delaytime(see below)
$1f801dda
$1f801ddc
$1f801dde
$1f801de0         Delaytime(see below)
$1f801de2
$1f801de4
$1f801de6
$1f801de8
$1f801dea
$1f801dec
$1f801dee
$1f801df0
$1f801df2
$1f801df4         Delaytime
$1f801df6         Delaytime
$1f801df8
$1f801dfa
$1f801dfc
$1f801dfe

--------------------------------------------------------------------------
Reverb
--------------------------------------------------------------------------
The SPU is equipped with an effect processor for reverb echo and delay type
of effects. This effect processor can do one effect at a time, and for each
voice you can specify wether it should have the effect applied or not.

The effect is setup by initializing the registers $1dc0 to $1ffe to the
desired effect. I do not exactly know how these work, but you can use
the presets below.

The effect processor needs a bit of sound buffer memory to perform it's
calculations. The size of this depends on the effect type. For the presets
the sizes are:

Reverb off        $00000       Hall          $0ade0
Room              $026c0       Space echo    $0f6c0
Studio small      $01f40       Echo          $18040
Studio medium     $04840       Delay         $18040
Studio large      $06fe0       Half echo     $03c00

The location at which the work area is location is set in register $1da2
and it's value is the location in the sound buffer divided by eight. Common
values are as follows:

Reverb off        $FFFE        Hall          $EA44
Room              $FB28        Space echo    $E128
Studio small      $FC18        Echo          $CFF8
Studio medium     $F6F8        Delay         $CFF8
Studio large      $F204        Half echo     $F880

For the delay and echo effects (not space echo or half echo) you can
specify the delay time, and feedback. (range 0-127) Calculations are shown
below.

When you setup up a new reverb effect, take the following steps:

-Turn off the reverb (bit 7 in sp0)
-Set Depth to 0
-First make delay & feedback calculations.
-Copy the preset to the effect registers
-Turn on the reverb
-Set Depth to desired value.

Also make sure there is the reverb work area is cleared, else you might get
some unwanted noise.

To use the effect on a voice, simple turn on the corresponing bit in the
channel reverb registers. Note that these get turned off autmatically when
the sample for the channel ends.


-------------------------------------------------------------
Effect presets: copy these in order to $1dc0-$1dfe

Reverb off:
$0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
$0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
$0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
$0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000

Room:
$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:
$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:
$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:
$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:
$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

Space Echo:
$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

Echo:
$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:

$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

Half Echo:
$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

-------------------------------------------------------------
Delay time calculation:
Choose delay time in range 0-$7f. rXXXX means register $1f80XXXX.

r1dd4 = dt*64.5 - r1dc0
r1dd6 = dt*32.5 - r1dc2

r1dd8 = r1dda + dt*32.5
r1de0 = r1de2 + dt*32.5
r1df4 = r1df8 + dt*32.5
r1df6 = r1dfa + dt*32.5

--------------------------------------------------------------------------
doomed@c64.org <- corrections/additions     latest update -> psx.rules.org
--------------------------------------------------------------------------
 5/jun/1999     First posting. Far from completion.

(thanx to ppl in <>)
--------------------------------------------------------------------------
thanx & hello to the usual.

