psx.wiki

SPU ADPCM

16-byte compressed sample blocks played by the SPU voices.

Overview

The SPU plays only ADPCM sample data. Sony calls the format VAG: compressed audio arranged in 16-byte blocks, about 3.5 to 1 smaller than the 16-bit source, and Sony treats the compression method as proprietary.1 psx-spx describes it as an extension of the SNES bit rate reduction (BRR) format that uses 16-byte blocks in place of 9-byte blocks and five filters in place of four.2 Uncompressed samples are not supported.3

A VAG file adds a 48-byte header to the blocks. The header must be removed before the data is played, and the first block of every VAG is 16 bytes of zero data. Sony calls this the lead-in and explains that it initializes the SPU so that the sample starts without a click.1

Block Format

Each block holds 28 samples in 16 bytes. The first two bytes are the block header and the other fourteen bytes each hold two 4-bit samples. The layout is shown below.3

Table 1: ADPCM block
Offset Contents
00h Shift and filter
01h Flag bits
02h Samples 1 (low nibble) and 2 (high nibble)
03h Samples 3 and 4
04h to 0Fh Samples 5 to 28, two per byte

The 28 samples of a 16-byte block therefore take 4.57 bits per sample (16 x 8 / 28), where PCM takes 16 bits. The shift and filter byte is reported to have the same layout as in XA-ADPCM, where bits 0 to 3 hold the shift and the bits above hold the filter.34

Flag Bits

The flag byte controls looping and the end of the sample.3

Table 2: ADPCM flag bits
Bit Name Set means
0 Loop End Set the ENDX bit and jump to LSAX after this block
1 Loop Repeat Keep playing at the loop. When clear with bit 0 set, the voice goes to release with the envelope at zero.
2 Loop Start Copy the current address to LSAX
3 to 7 Unknown Usually 0

Bits 0 and 1 together give four codes. Code 0 continues at the next block and code 2 acts the same. Code 3 jumps to the loop address and sets ENDX, and code 1 does the same but also forces release with the envelope at zero.3

The flags allow the whole sample or only its last blocks to repeat. There is no flag that stops output. A one-shot sample therefore ends in a block with Loop Start and Loop End both set and all samples zero, which repeats forever without sound.3

Sony's tools add this block to every one-shot VAG and call it the SPU IRQ clear block. It reads "00077777 77777777 77777777 77777777" or "00070000 00000000 00000000 00000000", and looping VAGs do not have it.5 The block keeps the voice from running on through the sound buffer and raising stray SPU interrupts. Sony allows the block to be removed when no SPU IRQ function is used. However, SpuGetIRQ(), SpuGetIRQAddr(), SpuSetIRQ(), SpuSetIRQAddr(), SpuSetIRQCallback() and the SpuSt streaming functions all use the SPU IRQ.5

Decoding

The hardware expands each 4-bit sample to 16 bits, shifts it right by the shift value and adds a prediction from the two previous output samples. The filter selects the prediction weights, and the result is clamped to -8000h to +7FFFh.6 The weights are the same as for XA-ADPCM, but the SPU accepts filter 4, which XA does not.7

Table 3: ADPCM filter coefficients
Filter Weight of old sample Weight of older sample
0 0 0
1 +60 0
2 +115 -52
3 +98 -55
4 +122 -60

The decoding of one sample is as follows. The weights are in 64ths, so the prediction is divided by 64 with rounding.6

f0 = pos_table[filter]
f1 = neg_table[filter]
t = signed 4-bit sample
s = (t << 12) >> shift
s = s + ((old * f0 + older * f1 + 32) / 64)
s = clamp(s, -8000h, +7FFFh)
older = old
old = s

SPU-ADPCM and XA-ADPCM

The PlayStation has two ADPCM formats. The decoder algorithm is the same for both. However, XA-ADPCM is decoded by the CD-ROM controller and goes to the SPU mixer directly. It uses neither the sound buffer nor a voice.8

The two formats also differ in layout. XA arranges its nibbles in a different order and holds 2 x 28 nibbles per block. It can be mono or stereo, has only two sample rates and has no looping.8 The XA audio page describes the XA side.

Interpolation

Each voice interpolates between samples with a 4-point Gaussian filter. The four most recent samples are weighted by entries of a 512-entry table, and bits 4 to 11 of the pitch counter give the 8-bit index i into it.9

out =       (gauss[0FFh - i] * oldest) >> 15
out = out + (gauss[1FFh - i] * older)  >> 15
out = out + (gauss[100h + i] * old)    >> 15
out = out + (gauss[000h + i] * new)    >> 15

In theory each set of four weights sums to 8000h. In practice the sums are 7F7Fh to 7F81h, which keeps the result within range.9 The table is as follows (eight entries per line):9

-001h,-001h,-001h,-001h,-001h,-001h,-001h,-001h ; 000h
-001h,-001h,-001h,-001h,-001h,-001h,-001h,-001h
0000h,0000h,0000h,0000h,0000h,0000h,0000h,0001h
0001h,0001h,0001h,0002h,0002h,0002h,0003h,0003h
0003h,0004h,0004h,0005h,0005h,0006h,0007h,0007h
0008h,0009h,0009h,000Ah,000Bh,000Ch,000Dh,000Eh
000Fh,0010h,0011h,0012h,0013h,0015h,0016h,0018h
0019h,001Bh,001Ch,001Eh,0020h,0021h,0023h,0025h
0027h,0029h,002Ch,002Eh,0030h,0033h,0035h,0038h
003Ah,003Dh,0040h,0043h,0046h,0049h,004Dh,0050h
0054h,0057h,005Bh,005Fh,0063h,0067h,006Bh,006Fh
0074h,0078h,007Dh,0082h,0087h,008Ch,0091h,0096h
009Ch,00A1h,00A7h,00ADh,00B3h,00BAh,00C0h,00C7h
00CDh,00D4h,00DBh,00E3h,00EAh,00F2h,00FAh,0101h
010Ah,0112h,011Bh,0123h,012Ch,0135h,013Fh,0148h
0152h,015Ch,0166h,0171h,017Bh,0186h,0191h,019Ch
01A8h,01B4h,01C0h,01CCh,01D9h,01E5h,01F2h,0200h ; 080h
020Dh,021Bh,0229h,0237h,0246h,0255h,0264h,0273h
0283h,0293h,02A3h,02B4h,02C4h,02D6h,02E7h,02F9h
030Bh,031Dh,0330h,0343h,0356h,036Ah,037Eh,0392h
03A7h,03BCh,03D1h,03E7h,03FCh,0413h,042Ah,0441h
0458h,0470h,0488h,04A0h,04B9h,04D2h,04ECh,0506h
0520h,053Bh,0556h,0572h,058Eh,05AAh,05C7h,05E4h
0601h,061Fh,063Eh,065Ch,067Ch,069Bh,06BBh,06DCh
06FDh,071Eh,0740h,0762h,0784h,07A7h,07CBh,07EFh
0813h,0838h,085Dh,0883h,08A9h,08D0h,08F7h,091Eh
0946h,096Fh,0998h,09C1h,09EBh,0A16h,0A40h,0A6Ch
0A98h,0AC4h,0AF1h,0B1Eh,0B4Ch,0B7Ah,0BA9h,0BD8h
0C07h,0C38h,0C68h,0C99h,0CCBh,0CFDh,0D30h,0D63h
0D97h,0DCBh,0E00h,0E35h,0E6Bh,0EA1h,0ED7h,0F0Fh
0F46h,0F7Fh,0FB7h,0FF1h,102Ah,1065h,109Fh,10DBh
1116h,1153h,118Fh,11CDh,120Bh,1249h,1288h,12C7h
1307h,1347h,1388h,13C9h,140Bh,144Dh,1490h,14D4h ; 100h
1517h,155Ch,15A0h,15E6h,162Ch,1672h,16B9h,1700h
1747h,1790h,17D8h,1821h,186Bh,18B5h,1900h,194Bh
1996h,19E2h,1A2Eh,1A7Bh,1AC8h,1B16h,1B64h,1BB3h
1C02h,1C51h,1CA1h,1CF1h,1D42h,1D93h,1DE5h,1E37h
1E89h,1EDCh,1F2Fh,1F82h,1FD6h,202Ah,207Fh,20D4h
2129h,217Fh,21D5h,222Ch,2282h,22DAh,2331h,2389h
23E1h,2439h,2492h,24EBh,2545h,259Eh,25F8h,2653h
26ADh,2708h,2763h,27BEh,281Ah,2876h,28D2h,292Eh
298Bh,29E7h,2A44h,2AA1h,2AFFh,2B5Ch,2BBAh,2C18h
2C76h,2CD4h,2D33h,2D91h,2DF0h,2E4Fh,2EAEh,2F0Dh
2F6Ch,2FCCh,302Bh,308Bh,30EAh,314Ah,31AAh,3209h
3269h,32C9h,3329h,3389h,33E9h,3449h,34A9h,3509h
3569h,35C9h,3629h,3689h,36E8h,3748h,37A8h,3807h
3867h,38C6h,3926h,3985h,39E4h,3A43h,3AA2h,3B00h
3B5Fh,3BBDh,3C1Bh,3C79h,3CD7h,3D35h,3D92h,3DEFh
3E4Ch,3EA9h,3F05h,3F62h,3FBDh,4019h,4074h,40D0h ; 180h
412Ah,4185h,41DFh,4239h,4292h,42EBh,4344h,439Ch
43F4h,444Ch,44A3h,44FAh,4550h,45A6h,45FCh,4651h
46A6h,46FAh,474Eh,47A1h,47F4h,4846h,4898h,48E9h
493Ah,498Ah,49D9h,4A29h,4A77h,4AC5h,4B13h,4B5Fh
4BACh,4BF7h,4C42h,4C8Dh,4CD7h,4D20h,4D68h,4DB0h
4DF7h,4E3Eh,4E84h,4EC9h,4F0Eh,4F52h,4F95h,4FD7h
5019h,505Ah,509Ah,50DAh,5118h,5156h,5194h,51D0h
520Ch,5247h,5281h,52BAh,52F3h,532Ah,5361h,5397h
53CCh,5401h,5434h,5467h,5499h,54CAh,54FAh,5529h
5558h,5585h,55B2h,55DEh,5609h,5632h,565Bh,5684h
56ABh,56D1h,56F6h,571Bh,573Eh,5761h,5782h,57A3h
57C3h,57E2h,57FFh,581Ch,5838h,5853h,586Dh,5886h
589Eh,58B5h,58CBh,58E0h,58F4h,5907h,5919h,592Ah
593Ah,5949h,5958h,5965h,5971h,597Ch,5986h,598Fh
5997h,599Eh,59A4h,59A9h,59ADh,59B0h,59B2h,59B3h

References


  1. ^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 16-3.

  2. ^ psx-spx. Sound Processing Unit (SPU). https://psx-spx.consoledev.net/soundprocessingunitspu/

  3. ^ a b c d e f psx-spx. Sound Processing Unit (SPU), SPU ADPCM Samples. https://psx-spx.consoledev.net/soundprocessingunitspu/

  4. ^ psx-spx. CDROM Format, CDROM XA Audio ADPCM Compression, XA-ADPCM Header Bytes. https://psx-spx.consoledev.net/cdromformat/

  5. ^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 16-4.

  6. ^ a b psx-spx. CDROM Format, CDROM XA Audio ADPCM Compression, decode_28_nibbles. https://psx-spx.consoledev.net/cdromformat/

  7. ^ psx-spx. CDROM Format, CDROM XA Audio ADPCM Compression, Pos/neg Tables. https://psx-spx.consoledev.net/cdromformat/

  8. ^ a b psx-spx. Sound Processing Unit (SPU), SPU-ADPCM vs XA-ADPCM. https://psx-spx.consoledev.net/soundprocessingunitspu/

  9. ^ a b c psx-spx. Sound Processing Unit (SPU), 4-Point Gaussian Interpolation. https://psx-spx.consoledev.net/soundprocessingunitspu/

Categories: Hardware · File formats