* pcm_meter: give the s16 scope a level for DSD streams
[not found] <alsa-project/alsa-lib/pr/517@alsa-project.org>
@ 2026-07-21 22:27 ` GitHub pull_request - opened
2026-07-27 7:43 ` GitHub pull_request - edited
1 sibling, 0 replies; 2+ messages in thread
From: GitHub pull_request - opened @ 2026-07-21 22:27 UTC (permalink / raw)
To: alsa-devel
alsa-project/alsa-lib pull request #517 was opened from Gjuju:
> **Depends on #516** (`pcm_meter: let the s16 scope degrade instead of killing the
> caller`) — both touch the same `switch`, so this is stacked on it to avoid a textual
> conflict. Only the second commit belongs to this PR.
## The problem
The s16 scope has no conversion for DSD, so `s16_enable()` rejects it and scopes see
nothing: needles sit still on a format that is increasingly common on USB DACs. (Before
the parent PR, they did worse than sit still — the application aborted.)
## The approach
DSD carries no sample values, only a **bit density**: over a short window the proportion
of ones *is* the amplitude, one half being silence. One S16 sample per frame can be
recovered by counting the bits of that frame and smoothing the result — which is what a
scope needs, a level rather than a reconstruction. No filter design, no resampling, no
new dependency.
Counting bits is invariant to their order, so the LE and BE variants share one code path
and only the width of a frame matters.
Two parameters set the quality, and both follow the format's own definition rather than
being tuning choices:
- **the smoothing** — a bit count is noisy (32 bits give σ = 0.5/√32), so each channel
keeps an exponential average whose time constant is derived from the rate. It is
therefore a *duration*, and behaves identically from DSD64 to DSD512;
- **the scale** — 0 dBFS in DSD is a 50% modulation index, so a full-scale signal swings
the density between 25% and 75% only. Referring to the whole 0–100% range would read
6 dB low.
## Testing
x86-64, Debian 13, DSD-capable USB DAC, playing the **same master in both formats**:
| source | min | max | mean |
|---|---|---|---|
| native DSD64 (`DSD_U32_BE` @ 88200) | 2 | 21 | 7.1 |
| FLAC 96/24 (`S32_LE` @ 96000) | 2 | 22 | 7.6 |
The needle reads the same level on both — the point being that the scale is right, not
merely that the value moves. The DAC keeps receiving `DSD_U32_BE` bit-perfect throughout;
`type meter` is a passive tap and this patch only feeds the scope.
Request URL : https://github.com/alsa-project/alsa-lib/pull/517
Patch URL : https://github.com/alsa-project/alsa-lib/pull/517.patch
Repository URL: https://github.com/alsa-project/alsa-lib
^ permalink raw reply [flat|nested] 2+ messages in thread* pcm_meter: give the s16 scope a level for DSD streams
[not found] <alsa-project/alsa-lib/pr/517@alsa-project.org>
2026-07-21 22:27 ` pcm_meter: give the s16 scope a level for DSD streams GitHub pull_request - opened
@ 2026-07-27 7:43 ` GitHub pull_request - edited
1 sibling, 0 replies; 2+ messages in thread
From: GitHub pull_request - edited @ 2026-07-27 7:43 UTC (permalink / raw)
To: alsa-devel
alsa-project/alsa-lib pull request #517 was edited from Gjuju:
> **Depends on #516** (`pcm_meter: let the s16 scope degrade instead of killing the
> caller`) — both touch the same `switch`, so this is stacked on it to avoid a textual
> conflict. Only the second commit belongs to this PR.
## The problem
The s16 scope has no conversion for DSD, so `s16_enable()` rejects it and the s16 buffer
carries nothing for a format that is increasingly common on USB DACs. (Before the parent
PR the outcome was worse than an empty buffer — the application aborted.)
## The approach
DSD carries no sample values, only a **bit density**: over a short window the proportion
of ones *is* the amplitude, one half being silence. One S16 sample per frame can be
recovered by counting the bits of that frame and smoothing the result — which is what a
scope needs, a level rather than a reconstruction. No filter design, no resampling, no
new dependency.
Counting bits is invariant to their order, so the LE and BE variants share one code path
and only the width of a frame matters.
Two parameters set the quality, and both follow the format's own definition rather than
being tuning choices:
- **the smoothing** — a bit count is noisy (32 bits give σ = 0.5/√32), so each channel
keeps an exponential average whose time constant is derived from the rate. It is
therefore a *duration*, and behaves identically from DSD64 to DSD512;
- **the scale** — 0 dBFS in DSD is a 50% modulation index, so a full-scale signal swings
the density between 25% and 75% only. Referring to the whole 0–100% range would read
6 dB low.
## Testing
x86-64, Debian 13, DSD-capable USB DAC, playing the **same master in both formats** and
sampling the level exposed on the s16 buffer:
| source | min | max | mean |
|---|---|---|---|
| native DSD64 (`DSD_U32_BE` @ 88200) | 2 | 21 | 7.1 |
| FLAC 96/24 (`S32_LE` @ 96000) | 2 | 22 | 7.6 |
The same master reads the same level in either format — the point being that the scale is
right, not merely that the value moves. The DAC keeps receiving `DSD_U32_BE` bit-perfect
throughout; `type meter` is a passive tap and this patch only feeds the scope.
Request URL : https://github.com/alsa-project/alsa-lib/pull/517
Patch URL : https://github.com/alsa-project/alsa-lib/pull/517.patch
Repository URL: https://github.com/alsa-project/alsa-lib
^ permalink raw reply [flat|nested] 2+ messages in thread