Catalog · How the catalog works
PCMAudio
PCM Audio Backend
- ★ 10 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
PCM audio layer
PCM is a portable PCM audio output layer.
Composition
| Unit | Purpose |
|---|---|
PCM.Audio |
Public facade: TPCMAudio, queue format and status. |
PCM.Audio.Backend |
The IPCMAudioBackend contract and common record types. |
PCM.Audio.Factory |
Selects the backend for the target platform. |
PCM.Audio.Windows.MMSystem |
Windows WaveOut (winmm). |
PCM.Audio.Android.AudioTrack |
Android AudioTrack. |
PCM.Audio.Linux.Alsa |
ALSA. |
PCM.Audio.Apple.AudioQueue |
macOS/iOS Audio Queue. |
PCM.Audio.Null |
Silent backend for unsupported platforms and tests. |
Usage
uses PCM.Audio;
var AudioFormat: TPCMAudioFormat;
AudioFormat.SampleRate := 44100;
AudioFormat.Channels := 1;
AudioFormat.BlockFrames := 1024;
AudioFormat.BlockCount := 4;
var Audio := TPCMAudio.Create(AudioFormat);
try
Audio.Submit(Samples, FrameCount);
var State := Audio.QueueState;
if Audio.Error <> '' then
begin
// Pass Audio.Error to the log or the application status.
end;
finally
Audio.Free;
end;Samples contains signed 16-bit PCM values (SmallInt) in
interleaved order. Count is the number of frames, not the number of values: for
stereo format, the array must contain at least Count * Channels
of elements. The Count must be in the range from 0 to BlockFrames.
Create, use, and destroy TPCMAudio in a single thread. This is especially
important for backends, whose native resources and callbacks are linked to
the owner's thread.
Queue and errors
Submit does not wait for playback: the backend copies the block to its own buffer and
returns control. If the device is full or unavailable, frames
are discarded, which is reflected in DroppedSamples.
QueueState returns a snapshot of the status:
| Field | Value |
|---|---|
SubmittedSamples |
The accumulated number of frames received. |
DroppedSamples |
The accumulated number of dropped frames. |
Clears |
The number of cleanup calls; the counter is 32-bit. |
PlayedSamples |
Playback position, valid only for PositionKnown = True; can be reset after Clear. |
QueuedBlocks |
Estimation of the number of blocks awaiting output. |
DeviceOpen |
The device is successfully opened. |
PositionKnown |
The backend was able to determine the playback position. |
Clear immediately discards pending playback. The cumulative counters
of received and dropped frames are not reset to zero. Errors in the native backend are
available through the Error property; the application must periodically read it and
the queue status, rather than waiting for an exception for every device error.
Choosing a platform
PCM.Audio.Factory selects the implementation at compile time:
| Condition | Backend |
|---|---|
MSWINDOWS |
PCM.Audio.Windows.MMSystem |
ANDROID |
PCM.Audio.Android.AudioTrack |
LINUX (except Android) |
PCM.Audio.Linux.Alsa |
MACOS or IOS |
PCM.Audio.Apple.AudioQueue |
| Other platform | PCM.Audio.Null with the message that there is no implementation |
The definition of PCM_AUDIO_NULL forcibly selects PCM.Audio.Null on any
platform. This is convenient for headless builds and checking portable code without
opening the audio device.
Adding a backend
The new implementation must implement the IPCMAudioBackend and honor the contract:
- Copy the input PCM data before returning from the
Submit. - Do not block the calling thread while waiting for playback.
- Limit the queue to
BlockCountblocks and account for overflow inDroppedSamples. - Cancel the pending playback in
Clear. - Stop native callbacks before releasing buffers.
- Report device failure via
ErrorandQueueState.
After adding the unit, it is connected to the conditional sections of the PCM.Audio.Factory and in uses the project for the corresponding platform.
Optional playback control
TPCMAudio.SetPaused(Boolean) forwards to IPCMAudioPlaybackControl when a
backend supports paused preroll. It returns false for an unsupported capability
without changing the normal Submit contract. Existing clients continue to play
immediately unless they call this method. The Windows backend supports it using
waveOutPause/waveOutRestart; Submit still copies and queues PCM while paused.
Callers can fill a bounded queue before restarting playback. Clear resets the
device position, so device-clock users must rebase their submitted-frame epoch.

