amiga-bootcamp/01_hardware/ocs_a500/paula_audio.md

136 lines
4.4 KiB
Markdown
Raw Normal View History

[← Home](../../README.md) · [Hardware](../README.md) · [OCS](README.md)
# Paula — Audio DMA
## Overview
**Paula** (MOS 8364) provides four independent audio DMA channels (03), corresponding to the four hardware voice outputs:
| Channel | Stereo Output |
|---|---|
| 0 | Left |
| 1 | Right |
| 2 | Right |
| 3 | Left |
Each channel has its own DMA pointer, length, period (pitch), and volume registers. Paula fetches sample data from **Chip RAM** automatically at the rate set by the period register.
## Audio Registers Per Channel
Channel `n` (n = 03) registers at `$DFF0A0 + n×$10`:
| Offset | Name | Description |
|---|---|---|
| +$00/$01 | AUDnLCH/AUDnLCL | Sample pointer high/low (Chip RAM address) |
| +$04 | AUDnLEN | Sample length in words (not bytes) |
| +$06 | AUDnPER | Period — clock divider for playback rate |
| +$08 | AUDnVOL | Volume: 064 (0 = silent, 64 = full) |
| +$0A | AUDnDAT | Current sample word (direct, for non-DMA mode) |
## Sample Playback Rate
Paula derives playback rate from the system clock divided by the period register:
```
Sample rate (Hz) = System clock / Period
```
| System | Clock | Period for 8363 Hz | Period for 22050 Hz |
|---|---|---|---|
| PAL | 3,546,895 Hz | 428 | ~161 |
| NTSC | 3,579,545 Hz | 428 | ~162 |
> **8363 Hz** is the standard MOD tracker reference — period 428 on PAL plays middle-A at exactly 8363 Hz.
Period range: 12465535 (minimum period = maximum frequency ≈ 28 kHz PAL).
## Starting Audio DMA
```asm
; Load channel 0 with sample at SampleData, length 256 words
move.l #SampleData, d0
move.w d0, AUD0LCL+custom
swap d0
move.w d0, AUD0LCH+custom
move.w #256, AUD0LEN+custom ; 256 words = 512 bytes
move.w #428, AUD0PER+custom ; period 428 = 8287 Hz PAL
move.w #64, AUD0VOL+custom ; full volume
; Enable audio DMA for channel 0
move.w #$8201, DMACON+custom ; SET + MASTER + AUD0EN
; Enable audio interrupt (optional)
move.w #$A080, INTENA+custom ; SET + INTEN + AUD0
```
## ADKCON — Audio/Disk Control
| Bit | Name | Description |
|---|---|---|
| 15 | SET/CLR | Write: 1=set, 0=clear bits |
| 11 | PRECOMP1 | Disk precompensation |
| 10 | PRECOMP0 | Disk precompensation |
| 9 | MFMPREC | MFM precompensation |
| 7 | MSBSYNC | Audio sync from MSB |
| 6 | WORDSYNC | Disk word sync enable |
| 4 | ATPER | Channel 3 period from channel 2 data |
| 3 | ATVOL | Channel 3 volume from channel 2 data |
| 2 | ATPER2 | Channel 1 period from channel 0 data |
| 1 | ATVOL2 | Channel 1 volume from channel 0 data |
| 0 | (unused) | |
`ATPER`/`ATVOL` bits enable **audio modulation** — channel N's period/volume is modulated by the sample data of channel N-1. Used for AM synthesis effects (e.g., in many MOD players for 8-channel soft mixing).
## Interrupt Handling
Audio channels raise interrupts when their DMA pointer wraps to the beginning of the next buffer:
```
INTENA/INTREQ bits:
AUD0 = bit 7 (IPL 4)
AUD1 = bit 8 (IPL 4)
AUD2 = bit 9 (IPL 4)
AUD3 = bit 10 (IPL 4)
```
The interrupt fires when the channel has consumed its buffer and reloaded the pointer from the DMA registers. At this point, software can update AUDnLCH/L and AUDnLEN with the next buffer.
## Double-Buffering Pattern
```c
/* In interrupt handler (IPL 4 server for AUD0): */
void audio_interrupt(void)
{
/* Swap buffers */
UWORD *next = (active_buf == buf_a) ? buf_b : buf_a;
active_buf = next;
/* Load next buffer address */
custom.aud[0].ac_ptr = (UWORD *)next;
custom.aud[0].ac_len = BUF_WORDS;
}
```
## Direct (Non-DMA) Audio
For simple sound effects without DMA overhead, write directly to `AUDnDAT`:
```asm
move.w #$0080, AUD0VOL+custom ; volume 64 (approx)
move.w #$7FFF, AUD0DAT+custom ; max positive sample
```
This only produces a single sample word — not practical for continuous audio but useful for one-shot clicks/beeps.
## audio.device
AmigaOS provides `audio.device` for arbitrated, multi-application audio access:
- Allocates channels (bitmask: `{1,2,4,8}`)
- Creates `IOAudio` request, uses standard device I/O (`BeginIO`/`WaitIO`)
- Handles period, volume, sample pointer, cycle count
- See [10_devices/audio_device.md](../../10_devices/audio_device.md) for full API reference
## References
- ADCD 2.1 Hardware Manual — Paula audio chapter
- NDK39: `hardware/custom.h` (struct AudChannel), `devices/audio.h`
- Autodocs: audio.device — http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node0081.html