Basic Sound Library (libspu)
Provides functions for controlling the SPU (sound processing unit).
| Library | libspu.lib |
|---|---|
| Header File | libspu.h |
This is an old revision of this page, as edited by RemmyLee at 02:58, 23 October 2026. Edit this revision | Latest revision
Overview
The Basic Sound Library (libspu) controls the SPU directly. It forms the lower level of the Extended Sound Library (libsnd) and also provides functions for operations such as transferring data other than music to the sound buffer. libspu has no time control functions, which are provided by libapi. Calls that set the same function must be separated by at least one SPU processing unit of 1/44100 second.1
A program that uses libspu links with libspu.lib and includes libspu.h.1
VAG Format
A VAG is compressed audio data arranged in 16-byte blocks. AIFF2VAG on the PC writes little-endian files and AIFF2VAG on the Mac big-endian files. Every VAG has a 48-byte header, which is removed for playback but must remain while VAGs are converted to VABs. The header has the following fields:1
| Field | Size | Contents |
|---|---|---|
| ID | 4 bytes | 'VAGp' |
| Version | 4 bytes | Version of AIFF2VAG that created the file |
| System reserved | 4 bytes | |
| Data size | 4 bytes | Size of the data in bytes |
| Sampling frequency | 4 bytes | Sampling frequency of the AIFF, from which the pitch can be found |
| System reserved | 12 bytes | |
| Name | 16 bytes | File name, used by Sound Delicatessen |
Every VAG starts with a lead-in of 16 bytes of zero data, which initializes the SPU and prevents clipping noise. AIFF2VAG compresses the body about 3.5 to 1, and the compression method is Sony proprietary information.1
A one-shot VAG ends with an extra 16-byte block that prevents unnecessary SPU interrupts and SPU free-run, while a looping VAG has no such block. The block matters only to SpuGetIRQ(), SpuGetIRQAddr(), SpuSetIRQ(), SpuSetIRQAddr(), SpuSetIRQCallback() and the SpuSt streaming functions. A program that uses none of them may therefore remove the block, which saves up to 4 KB of SPU RAM in one VAB. The data size in the VAG header must then be corrected before the VAB is built.2
Voices
libspu sets the following attributes independently for each of the 24 ADPCM voices: the volume, with left and right set separately, the pitch, the address of the waveform data in the sound buffer, the envelope (ADSR) and the loop point. Key on and key off are also set for each voice. The attributes may be changed while key on is in effect and the voice sounds. It is therefore possible to vary the pitch during a note, and to repeat a sound while its loop point changes.2
Noise
The SPU has one noise generator, which any voice may play in place of waveform data in the sound buffer. SpuSetNoiseVoice() selects the voices that play the noise generator, and SpuGetNoiseVoice() returns them. The noise has an envelope like other voices, and SpuSetNoiseClock() changes the noise clock while the sound plays to vary the noise tone.2
Pitch LFO
SpuSetPitchLFOVoice() makes two adjoining voices produce a low frequency oscillator (LFO) effect on pitch. Because the volume of one voice modulates the pitch of the next, two voices make one tone. The final pitch is NewPitch(n) = (1 + V(n-1)) x Pitch(n), where V(n-1) is the volume of voice n-1 as it changes with time and Pitch(n) is the pitch originally set for voice n.23
Reverb
Reverb is provided as templates whose parameters can be adjusted, and only one type of reverb is active at a time. SpuSetReverbVoice() turns reverb on or off for each voice, and SpuSetCommonAttr() applies it to the CD input and the external digital input.3
Reverb uses the sound buffer as its work area, from an offset address that depends on the reverb mode. The area below the offset may hold waveform data. The work area must be cleared before the reverb depth is raised, or noise is produced, and setting the mode sets the depth to 0. The mode is therefore set well in advance with SpuSetReverb() and SpuSetReverbModeParam(), and SpuSetReverbDepth() sets the depth when reverb is needed.3
The size of the work area changes only when SpuSetReverbModeParam() sets a new mode. SpuReserveReverbWorkArea() keeps the work area out of the sound buffer memory management. In that case SpuMalloc() allocates from 0x1010 up to 0x7ffff minus the work area. Without a reserved area SpuMalloc() may use the whole range 0x1010 to 0x7ffff, but SpuSetReverb(SPU_ON) then fails if the needed area is already allocated. A program that uses reverb must set the mode SPU_REV_MODE_OFF with SpuSetReverbModeParam() and call SpuSetReverb(SPU_OFF) when it exits. Otherwise noise may occur the next time a program runs.34
Sound Buffer Transfer
SpuWrite() transfers waveform data from main memory to the sound buffer and SpuRead() transfers it back. SpuSetTransferStartAddr() sets the sound buffer address before each transfer. There are two transfer modes:4
| Mode | Contents |
|---|---|
| DMA transfer | Write and read. The DMA controller transfers asynchronously and the CPU continues other processing. |
| I/O transfer | Write only. The CPU performs the transfer and other processing waits. |
DMA transfer is the default, and SpuSetTransferMode() changes the mode. After a DMA transfer the program calls SpuIsTransferCompleted(). An I/O transfer blocks the CPU, so SpuIsTransferCompleted() always returns 1 for it. DMA transfer is required while playback continues, and it is always used from the sound buffer to main memory. The main memory address must then lie in a large global area or in the heap. A stack area or an automatic variable cannot be used. If CdInit() is not called before SpuInit(), the completion of a waveform transfer may fail.4
SpuWrite0() clears an area of SPU RAM, and SpuWritePartly() transfers in steps. The sound buffer has no active memory management. Data transferred to the following areas cannot be used as waveform data:5
| Address | Contents |
|---|---|
| 0x00000 to 0x00fff | SPU decoded data transfer region |
| 0x01000 to 0x0100f | System reserved region |
| From the reverb work area offset | Reverb work area |
Sound Buffer Interrupt
The SPU reads the sound buffer at any time while it decodes. It can therefore generate a hardware interrupt request when a specific address is accessed. SpuSetIRQAddr() sets the address, SpuSetIRQ() enables or disables the interrupt and SpuSetIRQCallback() sets the function called on it. SpuGetIRQ() and SpuGetIRQAddr() return the current settings.5
Memory Management
Sound buffer memory management is limited. It keeps a table of occupied memory and reports only that information. SpuInitMalloc() sets up the table, SpuMalloc() allocates an area of SPU RAM, SpuMallocWithStartAddr() allocates an area at a given start address and SpuFree() deletes an area from the table.56
External Input
The SPU has two external inputs, the CD input and the external digital input. Both sample at 44.1 kHz, and the SPU mixes them digitally with its own output and may send them to reverb. SpuInit() resets the CD volume to zero. The program therefore calls CdInit() first and SpuInit() second, and sets the CD volume after both.6
Decoded Data
The SPU writes the first 0x1000 bytes of the sound buffer 16 bits at a time at each 44.1 kHz clock. It writes the CD input after volume processing and voices 1 and 3 after envelope processing. Each of these buffers is 0x400 bytes in two halves. By reading the half that is not being written, a program can take up to 100 samples (100 / 44100 = 0.0022 seconds) at a time, and SpuReadDecodedData() performs the transfer.6
SPU Streaming
The SPU plays only waveform data that fits in SPU RAM, which holds at most 512 KB. The SPU streaming functions play longer waveforms by transferring sections of the data to a stream buffer in SPU RAM while it plays. They are part of libspu and are separate from the streaming functions of libcd.7
The data is a VB file holding one VAG without its 48-byte header. A stream buffer is allocated in SPU RAM for each voice, up to 24, and all stream buffers have the same size and pitch. Main memory must always hold at least half a stream buffer of data for each stream. During a transfer the library marks the waveform in main memory and destroys it in units of half the stream buffer. A section used twice is therefore reloaded from the CD before its second transfer.7
Streaming has four states. In the idle state no stream is processed and the library puts no load on the CPU. In the preparation state the first half of each stream buffer is filled, so that playback starts without delay. In the transfer state the voices sound and each half of the stream buffer is refilled in turn. In the termination state all streams end and no new requests are accepted. Processing then returns to idle.78
Three callbacks report the progress, and their arguments name the streams concerned. The preparation finished callback is called when the initial transfer ends. The transfer finished callback is called each time half a stream buffer has been transferred, and it must set the attributes of the next transfer. The stream finished callback is called when a terminated stream has finished playing.8
All streams fill the same half of their buffers at the same time. A stream that is prepared or started during the transfer state therefore waits until the other streams reach the right half, and a larger stream buffer gives a longer lag. A smaller buffer, however, spends more time in callbacks for the SPU DMA and the SPU IRQ.91011
SpuStInit() initializes the streaming and returns an SpuStEnv structure, whose size member sets the stream buffer size of all streams. Its low_priority member, when SPU_ON, gives the streaming a lower priority than graphics processing. SpuStTransfer(SPU_ST_PREPARE, voices) prepares the streams and SpuStTransfer(SPU_ST_PLAY, voices) starts them with key on.101112
To end a stream, the transfer finished callback sets voice[].status to SPU_ST_STOP and voice[].last_size to the size of the remaining data. Key off is not automatic and must be performed by the program after the stream ends. The manual recommends setting the volume of the voice to 0 instead, since a key off may lag. SpuStQuit() ends the streaming when all streams are idle.1012
Use With libsnd
SsInit() of libsnd calls SpuInit() and SpuInitMalloc() itself. The memory table then allows 32 areas, and each open VAB uses one, so a program that needs more areas calls SpuInitMalloc() again after SsInit(). libsnd controls all 24 voices dynamically. SsSetReservedVoice() with a value below 24 therefore leaves the remaining voices to libspu.13
libspu can transfer VAB data, but the header and attribute information is not kept, so VABs are transferred with libsnd. libsnd cannot use the libspu transfer completion callback, which must be NULL before SsVabTransBody(), and SsVabTransCompleted() reports the end of the transfer instead. libspu has no functions for SEQ and SEP data, so a sequence driver written with libspu uses the root counter and event functions of libapi for timing.13
Structures
In the tables below, Introduced is the run-time library version that added the item.14
libspu has the following structures:14
| Structure | Introduced | Purpose |
|---|---|---|
SpuCommonAttr |
2.x | Common attributes. |
SpuDecodeData |
2.x | Decoded data from SPU. |
SpuEnv |
2.x | SPU environment attributes. |
SpuExtAttr |
2.x | External input attributes. |
SpuLVoiceAttr |
4.4 | Voice attributes. |
SpuReverbAttr |
3.0 | Reverb attributes. |
SpuStEnv |
2.x | SPU streaming environment attributes. |
SpuStVoiceAttr |
3.0 | SPU streaming voice attributes. |
SpuVoiceAttr |
3.0 | Voice attributes. |
SpuVolume |
2.x | Volume. |
Functions
libspu has the following functions:15
| Function | Introduced | Purpose |
|---|---|---|
SpuClearReverbWorkArea |
3.0 | Clear reverb work area. |
SpuFlush |
3.6 | Flush queued events. |
SpuFree |
3.0 | Release area allocated in sound buffer. |
SpuGetAllKeysStatus |
3.0 | Determine key on/off for all voices. |
SpuGetCommonAttr |
3.0 | Check sound system attributes. |
SpuGetCommonCDMix |
3.7 | Get CD input on/off status. |
SpuGetCommonCDReverb |
3.7 | Get CD input reverb on/off status. |
SpuGetCommonCDVolume |
3.7 | Get CD input volume. |
SpuGetCommonMasterVolume |
3.7 | Get master volume. |
SpuGetCommonMasterVolumeAttr |
3.7 | Get master volume/master volume mode. |
SpuGetCommonMasterVolumeX |
3.7 | Get current master volume. |
SpuGetIRQ |
3.0 | Check status of interrupt request. |
SpuGetIRQAddr |
3.0 | Check interrupt request address. |
SpuGetKeyStatus |
3.0 | Check key on/key off status for a voice. |
SpuGetMute |
3.0 | Check sound muting status. |
SpuGetNoiseClock |
3.0 | Check noise source clock. |
SpuGetNoiseVoice |
3.0 | Check noise source ON/OFF for each voice. |
SpuGetPitchLFOVoice |
3.0 | Check pitch LFO ON/OFF for each voice. |
SpuGetReverb |
3.0 | Check reverb status. |
SpuGetReverbModeDelayTime |
3.7 | Get reverb mode delay time. |
SpuGetReverbModeDepth |
3.7 | Get reverb mode depth. |
SpuGetReverbModeFeedback |
3.7 | Get reverb mode feedback. |
SpuGetReverbModeParam |
3.0 | Check reverb mode and parameters. |
SpuGetReverbModeType |
3.7 | Get reverb mode type. |
SpuGetReverbVoice |
3.0 | Check reverb ON/OFF for each voice. |
SpuGetTransferMode |
3.0 | Get sound buffer transfer mode. |
SpuGetTransferStartAddr |
3.0 | Get sound buffer transfer start address. |
SpuGetVoiceADSR |
3.6 | Get ADSR. |
SpuGetVoiceADSRAttr |
3.6 | Get ADSR rates and modes. |
SpuGetVoiceAR |
3.6 | Get ADSR attack rate. |
SpuGetVoiceARAttr |
3.6 | Get ADSR attack rate / attack rate mode. |
SpuGetVoiceAttr |
3.0 | Get voice attributes. |
SpuGetVoiceDR |
3.6 | Get ADSR decay rate. |
SpuGetVoiceEnvelope |
3.6 | Get current envelope value. |
SpuGetVoiceEnvelopeAttr |
3.6 | Get current envelope value and key ON/OFF status. |
SpuGetVoiceLoopStartAddr |
3.6 | Get loop start address of waveform data in the sound buffer. |
SpuGetVoiceNote |
3.6 | Get interval (note specification). |
SpuGetVoicePitch |
3.6 | Get interval (pitch specification). |
SpuGetVoiceRR |
3.6 | Get ADSR release rate. |
SpuGetVoiceRRAttr |
3.6 | Get ADSR release rate / release rate mode. |
SpuGetVoiceSampleNote |
3.6 | Get waveform data sample note. |
SpuGetVoiceSL |
3.6 | Get ADSR sustain level. |
SpuGetVoiceSR |
3.6 | Get ADSR sustain rate. |
SpuGetVoiceSRAttr |
3.6 | Get ADSR sustain rate and sustain rate mode. |
SpuGetVoiceStartAddr |
3.6 | Get address of waveform data in the sound buffer. |
SpuGetVoiceVolume |
3.6 | Get voice volume. |
SpuGetVoiceVolumeAttr |
3.6 | Get volume/volume mode. |
SpuGetVoiceVolumeX |
3.6 | Get current volume. |
SpuInit |
3.1 | Initialize SPU. |
SpuInitHot |
3.1 | Initializate SPU (hot reset); preserves sound buffer status. |
SpuInitMalloc |
3.0 | Initialize sound buffer memory management mechanism. |
SpuIsReverbWorkAreaReserved |
3.0 | Check if reverb work area is / can be reserved. |
SpuIsTransferCompleted |
3.0 | Check completion of transfer to the sound buffer. |
SpuLSetVoiceAttr |
4.4 | Sets attributes for multiple voices. |
SpuMalloc |
3.0 | Allocate an area in the sound buffer. |
SpuMallocWithStartAddr |
3.0 | Allocate an area from an address in sound buffer. |
SpuNGetVoiceAttr |
3.6 | Get voice attributes. |
SpuNSetVoiceAttr |
3.6 | Set attributes for a voice. |
SpuQuit |
3.0 | Terminate SPU processing. |
SpuRead |
3.0 | Transfer data from sound buffer to main memory. |
SpuReadDecodedData |
3.0 | Transfer sound data decoded by SPU from sound buffer to main memory. |
SpuReserveReverbWorkArea |
3.0 | Reserve/release reverb work area. |
SpuRGetAllKeysStatus |
3.1 | Check key on/key off for a range of voices. |
SpuRSetVoiceAttr |
3.1 | Set attributes of a range of voices. |
SpuSetCommonAttr |
3.0 | Set sound system attributes. |
SpuSetCommonCDMix |
3.7 | Set CD input ON/OFF. |
SpuSetCommonCDReverb |
3.7 | Set CD input reverb ON/OFF. |
SpuSetCommonCDVolume |
3.7 | Set CD input volume. |
SpuSetCommonMasterVolume |
3.7 | Set master volume. |
SpuSetCommonMasterVolumeAttr |
3.7 | Set master volume/master volume mode. |
SpuSetEnv |
3.6 | Set basic sound library environment. |
SpuSetIRQ |
3.0 | Turn interrupt request ON/OFF. |
SpuSetIRQAddr |
3.0 | Set interrupt request address. |
SpuSetIRQCallback |
3.0 | Set callback for interrupt request. |
SpuSetKey |
3.0 | Set key on/key off for each voice. |
SpuSetKeyOnWithAttr |
3.0 | Set key on with attributes. |
SpuSetMute |
3.0 | Turn sound muting ON/OFF. |
SpuSetNoiseClock |
3.0 | Set noise source clock. |
SpuSetNoiseVoice |
3.0 | Turn noise source ON/OFF for each voice. |
SpuSetPitchLFOVoice |
3.0 | Set pitch LFO ON/OFF for each voice. |
SpuSetReverb |
3.0 | Turn reverb ON/OFF. |
SpuSetReverbDepth |
3.0 | Set the reverb depth parameter. |
SpuSetReverbModeDelayTime |
3.7 | Set reverb delay time. |
SpuSetReverbModeDepth |
3.7 | Set reverb mode depth. |
SpuSetReverbModeFeedback |
3.7 | Set reverb feedback. |
SpuSetReverbModeParam |
3.0 | Set reverb mode and attributes. |
SpuSetReverbModeType |
3.7 | Set reverb mode. |
SpuSetReverbVoice |
3.0 | Set reverb ON/OFF for each voice. |
SpuSetTransferCallback |
3.1 | Set callback function for completion of DMA transfer. |
SpuSetTransferMode |
3.0 | Set sound buffer transfer mode. |
SpuSetTransferStartAddr |
3.0 | Set sound buffer transfer start address. |
SpuSetVoiceADSR |
3.6 | Set ADSR values. |
SpuSetVoiceADSRAttr |
3.6 | Set ADSR and ADSR modes. |
SpuSetVoiceAR |
3.6 | Set ADSR attack rate. |
SpuSetVoiceARAttr |
3.6 | Set ADSR attack rate / attack rate mode. |
SpuSetVoiceAttr |
3.0 | Set attributes for each voice. |
SpuSetVoiceDR |
3.6 | Set ADSR decay rate. |
SpuSetVoiceLoopStartAddr |
3.6 | Set loop start address of waveform data in sound buffer. |
SpuSetVoiceNote |
3.6 | Set interval (note specification). |
SpuSetVoicePitch |
3.6 | Set interval (pitch specification). |
SpuSetVoiceRR |
3.6 | Set ADSR release rate. |
SpuSetVoiceRRAttr |
3.6 | Set ADSR release rate / release rate mode. |
SpuSetVoiceSampleNote |
3.6 | Set waveform data sample note. |
SpuSetVoiceSL |
3.6 | Set ADSR sustain level. |
SpuSetVoiceSR |
3.6 | Set ADSR sustain rate. |
SpuSetVoiceSRAttr |
3.6 | Set ADSR sustain rate / sustain rate mode. |
SpuSetVoiceStartAddr |
3.6 | Set start address of waveform data in sound buffer. |
SpuSetVoiceVolume |
3.6 | Set voice volume. |
SpuSetVoiceVolumeAttr |
3.6 | Set voice volume/volume mode. |
SpuStart |
3.0 | Start SPU processing. |
SpuStGetStatus |
3.2 | Get SPU streaming status. |
SpuStGetVoiceStatus |
3.2 | Determine voices used for SPU streaming. |
SpuStInit |
3.2 | Initialize SPU streaming. |
SpuStQuit |
3.2 | Complete SPU streaming. |
SpuStSetPreparationFinishedCallback |
3.2 | Set function to be called at end of preparation phase of SPU streaming. |
SpuStSetStreamFinishedCallback |
3.2 | Set function to be called at completion of each stream in SPU streaming. |
SpuStSetTransferFinishedCallback |
3.2 | Set function to be called at completion of one transfer to the stream buffer for all streams. |
SpuStTransfer |
3.2 | Prepare for a stream and provide instructions for starting it. |
SpuWrite |
3.0 | Transfer data from main memory to the sound buffer. |
SpuWrite0 |
3.0 | Clear sound buffer. |
SpuWritePartly |
3.0 | Transfer data from main memory to sound buffer (assuming the transfer is divided into sections). |
References
-
^ a b c d Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-3.
-
^ a b c d Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-4.
-
^ a b c d Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-5.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-6.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-7.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-8.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-9.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-10.
-
^ Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-11.
-
^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-12.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-13.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-14.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. Run-Time Library 4.4. January 1999. Page 16-15.
-
^ a b Sony Computer Entertainment Inc. Run-Time Library Reference. Run-Time Library 4.4. January 1999. Pages 15-5 to 15-14.
-
^ Sony Computer Entertainment Inc. Run-Time Library Reference. Run-Time Library 4.4. January 1999. Pages 15-15 to 15-140.