first commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# `<MasterMeter>`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`<MasterMeter>` is a RAF-sampled master-output level meter. It
|
||||
subscribes to a named sidechain bus through the foundation `useBus`
|
||||
hook (`"master"` by default) and continuously reads the bus's
|
||||
block-aligned PCM into a scratch buffer at the configured interval,
|
||||
deriving per-channel peak and RMS levels in dB and a slow-decaying
|
||||
peak-hold envelope. When no publisher exists for the bus, every
|
||||
channel shows silence (`-∞` dB) so consumers always see something.
|
||||
|
||||
The meter is intentionally side-effect-free with respect to the audio
|
||||
graph: it only reads. Nothing inside `<MasterMeter>` ever writes to the
|
||||
bus or mutates engine state, which keeps it safe to drop into any
|
||||
layout that already has a publisher upstream.
|
||||
|
||||
## Features
|
||||
|
||||
- Subscribes to any named bus via `useBus(busName)`.
|
||||
- Per-channel peak + RMS in dB, plus a peak-hold envelope.
|
||||
- Configurable channel count, sample-tick rate, and hold time.
|
||||
- Reads up to `Math.min(meterChannels, busChannels)` per tick so
|
||||
publisher-wider and meter-wider mismatches do not blow up.
|
||||
- `role="meter"` + `aria-label` for screen readers.
|
||||
- `data-bus` and `data-channel` attributes for theming hooks.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```tsx
|
||||
import { AudioProvider, MasterMeter } from "@suaveplan/react-audio";
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<AudioProvider>
|
||||
<MasterMeter />
|
||||
</AudioProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```tsx
|
||||
import { AudioProvider, MasterMeter } from "@suaveplan/react-audio";
|
||||
|
||||
export function AuxMeter() {
|
||||
return (
|
||||
<AudioProvider>
|
||||
<MasterMeter
|
||||
busName="auxA"
|
||||
channels={1}
|
||||
sampleRateHz={120}
|
||||
peakHoldMs={2000}
|
||||
className="aux-meter"
|
||||
/>
|
||||
</AudioProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Prop | Type | Default | Notes |
|
||||
| -------------- | ------------------- | ----------- | ------------------------------------------------------ |
|
||||
| `className` | `string \| undef` | — | Forwarded to the outer `<div>`. |
|
||||
| `busName` | `string \| undef` | `"master"` | Name of the bus to subscribe to. |
|
||||
| `channels` | `number \| undef` | `2` | Number of channel rows to render. |
|
||||
| `sampleRateHz` | `number \| undef` | `60` | UI sample tick rate. Clamped to `>= 1`. |
|
||||
| `peakHoldMs` | `number \| undef` | `1000` | Peak-hold decay time in milliseconds. |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The component allocates one persistent scratch `Float32Array[]` per
|
||||
mount sized to `channelCount × 128` so the per-tick read does not
|
||||
allocate. Bus channel mismatches are handled by reading only the
|
||||
narrower side: if the publisher is wider than the meter, only the
|
||||
leading channels are read; if the meter is wider than the publisher,
|
||||
the trailing channels keep their zero-fill from the scratch buffer's
|
||||
last write (which corresponds to silence on next dB conversion). The
|
||||
peak-hold envelope uses one mutable record per channel keeping the
|
||||
current hold value and its expiry timestamp; the value is replaced
|
||||
either when a louder peak arrives or when the hold window expires,
|
||||
which gives the visually slow decay typical of professional meters.
|
||||
Reference in New Issue
Block a user