AROS Vision
Modern and free Amiga-Compatible Experience on Amiga and PC
1. What AHI is
AHI is the retargetable audio system for Amiga-like operating systems, written by Martin Blom. The name is never expanded officially; the author asks that it be called “AHI audio system” or just “AHI”, not “Audio Hardware Interface”. aminet
It does for sound what RTG (CyberGraphX/P96) does for graphics. Applications talk to a hardware-independent API, and a driver translates that to whatever sound hardware exists: Paula, a Zorro sound card, or a file renderer. The current and final release is AHI 6.0, which is licensed under (L)GPL and added support for AROS/ix86, among other platforms. Because the source is open, AROS carries AHI in its own source tree and builds it for its targets, including m68k. aminet
Important for m68k: version 6.0 supports the 68020, 68030, 68040 and 68060. The 68000 is no longer supported, and 68000 owners have to use version 4.
2. Architecture
Files on the system
Path DEVS:ahi.device Purpose The core: device and library in one
Path DEVS:AHI/<name>.audio Purpose The hardware drivers (library-based)
Path DEVS:AudioModes/<NAME> Purpose Mode description files that populate the audio-mode database
Path DEVS:DOSDrivers/AUDIO Purpose Mountlist for the AUDIO: handler
Path C:AddAudioModes Purpose Loads the mode files into the database (usually run at startup)
Path ENV:Sys/ahi.prefs Purpose Settings written by the AHI prefs editor
The AHI user archive maps its files to these locations: ahi.device to DEVS:, drivers to DEVS:AHI/, mode files to DEVS:AudioModes/, and the AUDIO mountlist to DEVS:DosDrivers/.
Drivers
Each supported sound card is controlled by a library-based audio driver. For a “dumb” card a new driver can be written in a few hours, and for a “smart” card an on-board DSP can be used to maximise performance and quality. Classic drivers include Paula (8/14/14c bit), Prelude, Toccata, Melody, Wavetools, and an 8SVX/AIFF sample renderer. On AROS m68k, the driver that really matters is paula.audio. Zorro-card drivers exist as 68k binaries, but whether a given one works under AROS m68k has to be tested case by case.
3. The audio-mode database (Audio IDs)
AHI uses ID codes, much like screenmode IDs, to select the many parameters that can be set, and the database access functions are similar to those in graphics.library. There is also a requester to let the user pick an ID.
An Audio ID is a 32-bit value that identifies driver plus mode, for example “Paula: HiFi 14 bit stereo++”. Each mode carries attributes you can query:
bits (8/14/16), stereo or panning capability
min/max mixing frequency and the list of supported frequencies
max number of channels
whether recording, full-duplex and so on are supported
Relevant library functions:
AHI_NextAudioID() – iterate over all modes
AHI_GetAudioAttrsA() – query a mode (AHIDB_Name, AHIDB_Bits, AHIDB_MaxChannels, AHIDB_Frequencies, …)
AHI_BestAudioIDA() – find the best mode for given requirements
AHI_AllocAudioRequestA() / AHI_AudioRequestA() – mode requester
4. The AHI preferences and units
The AHI prefs editor configures units 0–3 plus a “Music unit”. For each unit you set:
the audio mode (driver/ID)
mixing frequency
number of channels the unit mixes (how many apps/streams can play at once)
output volume, monitor volume, gain, input/output selection
Applications using the device API open a unit (normally AHI_DEFAULT_UNIT = 0), so the user decides which hardware and quality is used, not the program.
Global options include “Disable Echo”, “Fast Echo”, “Surround” and “Clip master volume”, plus a CPU-limit setting that keeps the mixer from starving the system.
5. The two programming interfaces
By acting both like a device and a library, AHI lets the programmer choose between full control and simplicity. The device API lets several programs use the audio hardware at the same time.
5a. High-level: the device API (ahi.device units)
You send standard Exec I/O requests (struct AHIRequest, which extends IOStdReq):
Field ahir_Std.io_Command Meaning CMD_WRITE (play), CMD_READ (record), CMD_FLUSH, CMD_STOP, CMD_START
Field ahir_Std.io_Data/io_Length Meaning sample buffer and length in bytes
Field ahir_Std.io_Offset Meaning must be 0 for the first write
Field ahir_Type Meaning sample format, e.g. AHIST_M8S, AHIST_S16Sahir_Frequencysample rate of your data in Hz
Field ahir_Volume Meaning Fixed 16.16, 0x10000 = full
Field ahir_Position Meaning pan, Fixed, 0x8000 = centre
Field ahir_Link Meaning pointer to the previous request → gapless chaining
Gapless streaming: you keep two (or more) requests in flight. Each new CMD_WRITE sets ahir_Link to the request that is still playing, so AHI starts it seamlessly when the previous one ends. This is the classic double-buffering pattern for players.
Pros: shared hardware, AHI converts your sample rate to the unit’s mixing rate, user controls output.
Cons: more latency (the mixing/buffer layer), and you can’t control effects or individual channels.
Minimal C sketch:
5b. Low-level: the library API (AHI_NO_UNIT)
You open the device with unit AHI_NO_UNIT (255) and use io_Device as AHIBase. You then get a tracker-style engine with N virtual channels:
AHI_AllocAudioA() with tags such as AHIA_AudioID, AHIA_MixFreq, AHIA_Channels, AHIA_Sounds, AHIA_SoundFunc (hook called when a sound starts on a channel), AHIA_PlayerFunc + AHIA_PlayerFreq (a timer hook, perfect for a tracker replayer tick).
AHI_LoadSound() registers samples. AHIST_SAMPLE is a static sample. AHIST_DYNAMICSAMPLE is a buffer you refill yourself, which is the basis for streaming.
AHI_ControlAudio(..., AHIC_Play, TRUE, ...) starts playback.
Per channel: AHI_SetSound(), AHI_SetFreq(), AHI_SetVol() (with pan), each with AHISF_IMM for immediate change or queued until the current sound loops.
AHI_SetEffect() for master volume, echo/DSP, channel info and so on.
AHI_FreeAudio() when done.
Pros: low latency, sample-accurate control, per-channel frequency/volume/pan, which is ideal for MOD/XM players and games.
Cons: traditionally exclusive to the hardware. AHI 6 adds a device.audio driver that makes low-level applications that normally open AHI exclusively behave as if they used the high-level API, so several programs can share the hardware. That driver does not work with applications that need less than 20 ms latency.
Sample formats (AHIST_*)
AHIST_M8S, AHIST_S8S, AHIST_M16S, AHIST_S16S, and in v6 also the 32-bit AHIST_M32S/AHIST_S32S. Stereo data is interleaved (L, R). Data is signed and big-endian. Watch for this when decoding formats that store little-endian PCM, like WAV: you have to byte-swap.
6. The AUDIO: DOS device
The AUDIO: dos-device driver makes playing and recording sound very simple for both the programmer and user. You write raw PCM to a filename that encodes the parameters, for example:
Copy sound.raw TO "AUDIO:BITS/16/CHANNELS/2/FREQUENCY/44100"
Reading from AUDIO: records. Supported keywords include BITS, CHANNELS, FREQUENCY, VOLUME, POSITION, UNIT, BUFFER and so on (see the AHI user docs for the full list). It’s handy for testing and for shell scripts, but it’s not something to build a real player on.
7. paula.audio in detail (the part that matters on real hardware)
Paula offers four 8-bit DMA channels: two left, two right, with 6-bit volume. paula.audio exposes several mode families:
8 bit – one Paula channel per side. Cheapest, but the quietest, coarsest output.
14 bit – two Paula channels per side are combined. One plays the high byte at volume 64, the other plays the low bits at volume 1, which gives about 14-bit resolution. That uses up all four hardware channels.
14 bit calibrated (“14c”) – same, but uses a per-machine calibration table (made with a calibration tool) to correct DAC non-linearity. Best quality.
“++” / HiFi variants – use AHI’s HiFi mixing, which has linear interpolation and 32-bit internal output, at higher CPU cost.
Maximum sample rate is limited by Paula DMA timing, which is tied to the display scan rate. With a 15 kHz PAL/NTSC screen you get roughly 28 kHz. With a 31 kHz (productivity/DblPAL/DblNTSC) screen mode, Paula can be driven to about 56 kHz. So the Workbench screenmode can affect your maximum audio rate.
Everything is mixed by the CPU. Paula has no hardware mixer for AHI’s purposes. The mixer combines all virtual channels into one stream (or two for stereo), and the driver feeds that to Paula. Practical consequences on a 68020/030:
Use the “Fast” mixing routines, not HiFi.
Keep the mix frequency modest (e.g. 22–28 kHz).
Use few channels.
14-bit modes cost noticeably more than 8-bit.
A 68060 handles HiFi at high rates comfortably.
The Amiga’s native audio.device still exists. paula.audio and audio.device compete for the same four channels, so a program using audio.device directly and AHI on Paula can’t both sound at once.
8. Recording
Drivers that support input (Paula itself can’t record, but sampler-capable drivers can) let you use CMD_READ on the device or set AHIA_RecordFunc in the library API. AHI_ControlAudio(..., AHIC_Record, TRUE) starts capture.
9. Practical advice for a media player on AROS m68k
For streamed PCM (decoded video soundtracks): use the device API with two or three linked CMD_WRITE requests (ahir_Link), each buffer about 50–100 ms. Submit with SendIO() and wait on the reply port together with your other signals (timer, IDCMP) via Wait(). That fits naturally into an event loop.
A/V sync: derive your audio clock from the number of bytes AHI has finished playing (reply count × buffer size), not from when you submitted them. Video then follows the audio clock.
For tracker modules: the library API is the natural fit. Use one AHI channel per module channel, AHIA_PlayerFunc at the song’s tick rate (50 Hz × speed/tempo factor), and AHI_SetSound/SetFreq/SetVol per note. AHI does the resampling and mixing, so you don’t need your own mixer.
Endianness and signedness: convert decoder output to signed big-endian before handing it to AHI.
Let the user choose: offer AHI_AudioRequestA() or simply use AHI_DEFAULT_UNIT so the AHI prefs settings apply.
Budget CPU: on a 68030, the AHI mixer, your decoder and the C2P/AGA output all compete for cycles. Prefer 8-bit or 14-bit Fast modes and a 22 kHz output in the default settings.