On this page
Write the audio contract before opening samples
The source dates shown in this guide identify documentation checks on 22 October 2026, not original publication dates. Follow each citation for the documentation edition being discussed.
Record the artifact reference, digest or controlled identifier, container, codec, duration, sample rate, channel count, channel layout, sample format, and whether the object is an original or a derivative. A channel count is not the same as a channel layout: two channels may be left and right, dual mono, or an application-specific pair. Treat an unknown layout as unknown instead of guessing from the count.
The python-soundfile, (opens in a new tab) documentation describes a SoundFile as having a sample rate, data format, and number of channels, and its frame index represents one time-step containing one sample per channel. PyAV exposes analogous AudioFrame properties such as sample_rate, layout, samples, and format PyAV, (opens in a new tab). These are observations about a decoded representation, not evidence of recording intent or listening quality.
| Contract item | Record before signal review | Open question |
|---|---|---|
| Artifact | Controlled identifier, digest, and original or derivative state | Is this the exact object under review? |
| Rate | Declared sample rate and unit | Does decoding software expose the same rate? |
| Channels | Count and named layout, or unknown | Is two-channel content stereo or dual mono? |
| Samples | Format and inspected frame window | Which threshold representation applies? |
| Timing | Frame timestamps and samples per channel | Are discontinuities or rate changes visible? |
| Disposition | Issue class, evidence reference, and owner decision | Who decides whether a derivative is allowed? |
Compare metadata with decoded frame observations
Metadata is a declaration to compare, not an independent proof. For a bounded review, collect a small summary per decoded audio frame: frame index, timestamp if present, sample rate, layout, sample count per channel, and a stable issue class. FFmpeg’s ashowinfo reports per-frame timestamps, sample format, channel layout, rate, and samples per channel FFmpeg, (opens in a new tab).
Selected stream fields
ffprobe -v error -select_streams a:0 \
-show_entries stream=index,codec_name,sample_rate,channels,channel_layout,sample_fmt,duration \
-of json MEDIA_REFERENCEThe FFmpeg, (opens in a new tab) documentation supports selecting audio streams, stream fields, and machine-readable output. Keep MEDIA_REFERENCE as a controlled identifier in a report. Do not include a private path, a recording title, tags, or raw packet data in a public diagnostic.
Synthetic decoded summary
{
"declared": {"sample_rate_hz": 48000, "channels": 2, "layout": "stereo", "sample_format": "fltp"},
"decoded_frames": [
{"index": 0, "sample_rate_hz": 48000, "channels": 2, "samples_per_channel": 1024},
{"index": 1, "sample_rate_hz": 48000, "channels": 2, "samples_per_channel": 1024}
]
}The values are invented for the worksheet. A mismatch such as two declared channels and one decoded channel is a stream-contract finding. It does not explain why the change occurred or whether a listener would prefer one representation. Record the first and last affected frame, not the raw samples.
Define clipping as an observation with a policy
Clipping is easiest to misuse when it is turned into a universal threshold. First document the decoded sample representation and the policy. For a synthetic normalized float fixture, one local policy might count a sample at or beyond full scale as a potential clipped sample.
Bounded synthetic sample check
from collections.abc import Iterable
def clipping_summary(samples: Iterable[float], limit: float = 1.0, max_samples: int = 100_000):
inspected = 0
clipped = 0
peak = 0.0
limited = False
for value in samples:
if inspected >= max_samples:
limited = True
break
magnitude = abs(value)
inspected += 1
clipped += magnitude >= limit
peak = max(peak, magnitude)
return {"sample_count": inspected, "potential_clipped_samples": clipped, "absolute_peak": peak, "sample_limit_reached": limited}
synthetic_channel = [0.10, -0.35, 0.99, 1.0, -1.02]
print(clipping_summary(synthetic_channel))This function is deliberately bounded by max_samples and does not log values. The synthetic result would report two potential clipped samples under this policy. On real data, define whether the threshold is inclusive or exclusive, whether the check is per channel, and how floating-point rounding is handled. An encoded integer stream and a normalized float stream need an explicit representation contract before their thresholds are compared.
FFmpeg’s volumedetect can report mean volume, maximum volume per sample, and a histogram. Its documentation also states that the filter works on 16-bit signed integer samples and converts other input as needed FFmpeg, (opens in a new tab). Use that result as a diagnostic in the filter’s representation, not as a complete clipping count or a listening judgment. If per-channel counts are needed, decode into a bounded analysis buffer and report only counts, positions, and policy identifiers.
Use a worksheet and a disposition table
Record one row per check: artifact reference, stream index, declared rate, observed rate set, declared channel layout, observed layout set, sample format, inspected frame range, peak policy, potential clipping count, issue class, evidence reference, owner decision, and unresolved questions.
| Observation | Safe interpretation | Next action |
|---|---|---|
| Declared rate is missing | The stream contract is incomplete | Request a source declaration or classify rate as unknown |
| Decoded frame rate changes | A representation change or decoding-software finding is visible | Preserve frame indexes and investigate the derivative chain |
| Channel count and layout disagree | The channel contract is ambiguous | Ask the producer to state layout or hold the artifact |
| One channel has zero energy in the window | The selected window has no nonzero samples there | Inspect another approved window; do not call the whole track silent |
| Potential clipped samples are counted | The chosen representation crossed the local limit | Preserve policy, sample count, and frame range; do not infer cause |
| No potential clipping in the window | No crossing was observed under this policy and window | Keep the window and policy; do not generalize to all playback |
| All selected checks pass | The selected stream checks have evidence | Continue provenance, privacy, rights, and accuracy review |
Keep “not inspected,” “not available,” and “not observed under this policy” distinct. A short window can miss a transient event, and a decoding-software summary cannot answer whether content is intelligible or pleasant to hear.
Keep diagnostics safe and the next step qualified
The public report can contain a controlled artifact identifier, stream index, frame range, stable issue class, numeric counts, and tool versions. It should not contain raw samples, private paths, recording names, voice labels, or unbounded decoding errors. If a source must be revisited, retain the evidence reference and owner-approved handling boundary rather than copying the audio into a worksheet.
Pair this check with the data provenance log and export guidance. Those resources own source, rights, processing, and broader export questions; this guide owns sample rate, channel, and bounded signal observations.
After the owner has a supported non-health scope, authority to describe the artifact, and a metadata or synthetic review packet, the qualified appraisal request path may be a next preparation step. It does not validate sample rate, accept audio, produce a quote, match a buyer, issue a legal opinion, or grant a license. Keep raw recordings outside this guide and within the owner-approved handling boundary.
Takeaways
- Record sample rate, channels, layout, and sample format as separate contract fields.
- Compare declarations with bounded decoded-frame observations instead of treating metadata as proof.
- Define clipping representation, threshold, window, and channel policy before counting potential crossings.
- Use stable issue classes and counts; keep raw samples and private labels out of shared diagnostics.
- Treat a clean technical check as one input to later provenance, privacy, rights, and accuracy review.