- Benchmarks
Synthetic audio versus real speech in regression tests
Audit speech-fixture lineage, permissions and missing cohorts without confusing synthetic regression coverage with real performance.
- Author
Udit Goenka- Editorial date
- Reading time
- 28 min

TL;DR: Synthetic speech is useful for controlled software fixtures, but it does not replace evidence from appropriately obtained real speech. Track source and speaker lineage, dataset releases, permission admission and missing task-channel slices before interpreting regression coverage as empirical robustness.
A speech regression suite passes every generated utterance, yet callers still fail on corrections, overlapping speech and telephone noise. The suite may be working exactly as designed: it checks controlled generated inputs, while the release claim refers to a different population.
Begin with a coverage manifest that keeps synthetic and recorded sources separate. Retain stable privacy-safe speaker and source lineage, transformation parentage, dataset release, collection conditions and explicit permission-admission evidence. Report missing real-speech slices rather than filling them with generated substitutes.
The runnable artifact below audits declared metadata only. It detects declared train-test overlap, retains excluded fixtures, deduplicates identical content within a split and emits a source-separated coverage plan. It does not load waveforms, establish legal permission or measure recognition accuracy.
For an application such as 60db Agent, software regression and real-task evaluation are complementary evidence. The critical-field audit shows why even an authentic transcript metric still needs separate task-outcome measurements.
Table of contents
- Choose the claim before the fixture
- Separate synthetic and recorded evidence
- Preserve speaker and source lineage
- Admit fixtures under an explicit permission policy
- Run the fixture coverage audit
- Read the printed coverage gaps
- Prevent augmentation leakage
- Keep missing metadata visible
- Pin public dataset releases
- Make acceptance criteria explicit
- Design task and channel cohorts
- Use synthetic boundary cases deliberately
- Measure real speech under its actual scope
- Keep waveform and hardware claims separate
- Maintain the evidence collection
- Frequently asked questions
- Start with one missing slice
Choose the claim before the fixture
A fixture is useful when it exercises a declared behavior. A generated clip can verify that a decoder accepts an intended format, that a literal identifier survives a pipeline or that cancellation invalidates queued audio. Those are bounded software questions.
A claim about real callers requires different evidence. Human speech includes task context, hesitations, repairs, channel effects and variation that a particular generator may not reproduce. Passing a generated corpus cannot establish how often an application succeeds on a real deployment population.
OpenAI's evaluation best practices emphasize evaluations tied to the actual task and continued evaluation as systems change. A voice fixture plan should state whether it tests a software invariant, a transcript property, an interaction behavior or an external outcome.
Write the expected observation before selecting a source. If the question concerns clipped consonants at stream boundaries, a controlled waveform can isolate the boundary. If the question concerns caller repair behavior, recordings of the relevant interaction provide evidence that a clean read sentence does not.
The audio-boundary guide and spoken-repair guide illustrate these different test boundaries. Combining their fixtures into one unlabeled total would conceal what each source can support.
Avoid treating realism as a single scalar. A generated clip can sound natural while omitting the channel behavior or task ambiguity that matters. Declare the dimensions needed for the release decision and report which ones remain unobserved.
Give every fixture an intended failure detector. A clip added because it sounds convincing may have no clear expected observation and little regression value. By contrast, a small controlled fixture with a precise literal, frame boundary or cancellation event can expose a meaningful software defect. The test description should explain what would fail and which downstream claim remains outside its scope even when the expected observation passes.
Separate synthetic and recorded evidence
Keep source type as explicit metadata. Generated speech, recorded human speech and transformed versions of either have different provenance. A shared file extension or sample rate does not make them interchangeable evidence about the same population.
Synthetic fixtures are especially useful when the exact content and intended perturbation must be controlled. They can help reproduce a bug without retaining private recordings. Their value comes from that control, not from an unsupported claim that the generated speaker represents a regional caller population.
Recorded speech can expose behaviors absent from a generator, but it also needs scope and provenance. Read speech, spontaneous conversations and telephone interactions support different claims. A large collection of one type does not automatically cover another.
LibriSpeech's resource page describes a read-English corpus and its published license and splits. That provenance makes it useful to reason about its intended scope; it does not turn read speech into evidence for every real-time telephone task.
The FLEURS dataset card provides multilingual dataset information and release artifacts. Language coverage in a card is valuable metadata, but it does not by itself establish the application's dialect, task or channel coverage.
The manifest audit emits separate recorded and synthetic test counts. It never pools them into a real-speech denominator or converts a missing recorded cohort into a covered cohort because generated clips exist with a similar language tag.
Separate source type from the task's eventual output as well. A generated input can be passed through a real recognizer, and a recorded input can be processed by a stub in a software test. Those experiments observe different systems. Retain execution provenance with any later result so the manifest's recorded-source label cannot be misread as proof that the full production workflow was exercised.

Preserve speaker and source lineage
A cohort label is not a speaker identity. Two clips labeled with the same language may have different speakers; two clips with different channel labels may come from the same person and original recording. Disjointness requires explicit lineage evidence.
Use stable privacy-safe speaker identifiers for the evaluation's permitted scope. Keep source-recording lineage separate from speaker identity, and keep both separate from demographic or task labels. The local tool trusts these opaque identifiers; it cannot recover identities from audio.
A transformed recording retains its original lineage even when its content hash changes. Noise addition, resampling or codec conversion can create different bytes without creating a new speaker or independent source. Record the transformation parent rather than inventing a new independent origin.
The accent-cohort guide explains why evaluation groups should be defined carefully and without stereotypes. A metadata category should describe the study boundary, not claim to infer a person's identity or capability.
The artifact rejects declared train-test overlap on recorded speaker identity and on source lineage. It also rejects identical content crossing those splits. These checks operate on admitted metadata and cannot detect overlap that the collection process failed to identify truthfully.
Unknown speaker or source lineage does not become proof of independence. The report marks recorded disjointness unverified when required admitted metadata is missing. The engineering response is either to obtain appropriate lineage evidence or narrow the claim, not to assign each unknown item an invented unique speaker.
Opaque identifiers still need a declared namespace. The collection process must know whether two speaker references from different datasets can be compared, and it must not infer a cross-dataset identity from a similar filename. The local tool trusts globally consistent values for its admitted manifest. If linkage is unavailable or impermissible, retain that limitation instead of asserting a broader speaker-disjoint result than the evidence supports.
Admit fixtures under an explicit permission policy
Available audio is not automatically admitted audio. A fixture collection needs a documented policy for permitted use, retention, transformation, review and publication. The local program accepts a trusted admission decision and an evidence reference; it does not make a legal determination.
Permission metadata should be explicit for recorded and generated fixtures. A generator may have interface or usage requirements, and a recording collection may have source-specific terms. Preserve the relevant policy decision without copying personal consent records into public reports.
OpenAI's text-to-speech guide documents its speech interface and disclosure requirement for generated voice. That provider contract is distinct from recording consent and from a legal conclusion about a particular dataset or jurisdiction.
The recording-consent guide addresses a live interaction boundary. A caller's permitted recording state can change during a call. The fixture admission process must respect the actual permitted source and retention scope rather than assuming an entire call is reusable.
Missing permission or release evidence excludes a record from coverage in this example, with reasons retained in the ledger. A string that names a license is a reference for review, not proof that every intended transformation or publication is allowed.
Use the smallest evidence reference that supports the internal audit. Public examples should contain synthetic metadata, no raw recordings and no customer identifiers. Privacy-safe lineage still requires governance because combinations of metadata can expose small identifiable groups.
Separate permission decisions from collection convenience. An engineer finding a useful failure recording does not automatically authorize adding it to a shared regression repository. Admission should identify the allowed purpose and retention boundary through the owning policy. If the recording cannot be reused, a synthetic reproduction may still test the software mechanism, provided its report does not imply that the original recording entered the public suite.
Run the fixture coverage audit
Save the complete fence as speech-fixture-coverage.py and run it with Python 3.11 or newer. It validates immutable metadata records, checks declared leakage boundaries, executes negative fixtures and prints a reusable coverage report using only the standard library.
The supported split contract is train versus test. The tool checks declared source and recorded-speaker disjointness across those splits. A real collection with development or selection partitions must define their roles explicitly rather than silently mapping them to whichever split makes leakage disappear.
from dataclasses import dataclass, replace
from hashlib import sha256
import json
def text(value):
if type(value) is not str or not value.strip():
raise ValueError("nonempty text required")
def optional_text(value):
if value is not None:
text(value)
def digest(value):
return sha256(value.encode("utf-8")).hexdigest()
@dataclass(frozen=True)
class Item:
fixture_id: str
content_hash: str
source: str
speaker_id: str | None
lineage_id: str | None
parent_id: str | None
split: str
language: str
channel: str
noise: str
codec: str
dataset: str | None
release: str | None
generator: str | None
generator_version: str | None
permitted: bool | None
permission_ref: str | None
def __post_init__(self):
for value in (self.fixture_id, self.content_hash, self.language,
self.channel, self.noise, self.codec):
text(value)
if len(self.content_hash) != 64 or any(c not in "0123456789abcdef" for c in self.content_hash):
raise ValueError("lowercase SHA-256 required")
if type(self.source) is not str or self.source not in {"synthetic", "recorded"}:
raise ValueError("typed source required")
if type(self.split) is not str or self.split not in {"train", "test"}:
raise ValueError("typed split required")
for value in (self.speaker_id, self.lineage_id, self.parent_id, self.dataset,
self.release, self.generator, self.generator_version, self.permission_ref):
optional_text(value)
if self.permitted is not None and type(self.permitted) is not bool:
raise ValueError("permission must be bool or None")
def audit(items, required):
owned = tuple(items)
requirements = tuple(required)
if any(type(item) is not Item for item in owned):
raise ValueError("exact immutable items required")
by_id = {}
for item in owned:
if item.fixture_id in by_id:
raise ValueError("duplicate fixture identity")
by_id[item.fixture_id] = item
for key in requirements:
if type(key) is not tuple or len(key) != 4:
raise ValueError("source/language/channel/noise requirement required")
for value in key:
text(value)
if key[0] not in {"synthetic", "recorded"}:
raise ValueError("unknown required source")
if len(set(requirements)) != len(requirements):
raise ValueError("duplicate requirement")
for item in owned:
if item.parent_id is not None:
parent = by_id.get(item.parent_id)
if parent is None or parent.fixture_id == item.fixture_id:
raise ValueError("missing or self parent")
if item.lineage_id is None or item.lineage_id != parent.lineage_id:
raise ValueError("transformation changed source lineage")
if item.source != parent.source or item.speaker_id != parent.speaker_id:
raise ValueError("transformation changed source or speaker")
# Parent chains must terminate; completed paths are reused across items.
completed = set()
for item in owned:
if item.fixture_id in completed:
continue
active = set()
path = []
current = item
while current.fixture_id not in completed:
if current.fixture_id in active:
raise ValueError("cyclic transformation lineage")
active.add(current.fixture_id)
path.append(current.fixture_id)
if current.parent_id is None:
break
current = by_id[current.parent_id]
completed.update(path)
ledger = []
eligible = []
for item in sorted(owned, key=lambda value: value.fixture_id):
reasons = []
if item.permitted is not True or item.permission_ref is None:
reasons.append("permission_not_admitted")
if item.dataset is None or item.release is None:
reasons.append("missing_dataset_release")
if item.source == "synthetic" and (item.generator is None or item.generator_version is None):
reasons.append("missing_generator_version")
entry = {"fixture_id": item.fixture_id, "source": item.source, "split": item.split,
"speaker_id": item.speaker_id, "lineage_id": item.lineage_id,
"parent_id": item.parent_id, "content_hash": item.content_hash,
"dataset": item.dataset, "release": item.release,
"generator": item.generator, "generator_version": item.generator_version,
"language": item.language, "channel": item.channel, "noise": item.noise,
"codec": item.codec, "permission_ref": item.permission_ref,
"permitted": item.permitted,
"excluded_reasons": reasons, "duplicate_of": None}
ledger.append(entry)
if not reasons:
eligible.append(item)
for attribute, recorded_only in (("lineage_id", False), ("speaker_id", True), ("content_hash", False)):
splits = {}
for item in eligible:
if recorded_only and item.source != "recorded":
continue
value = getattr(item, attribute)
if value is not None:
splits.setdefault(value, set()).add(item.split)
if any(len(value) > 1 for value in splits.values()):
raise ValueError("declared train/test overlap: " + attribute)
representatives = {}
admitted = []
entries = {entry["fixture_id"]: entry for entry in ledger}
for item in eligible:
previous = representatives.get(item.content_hash)
if previous is not None:
if (item.source, item.split, item.language, item.channel, item.noise, item.codec,
item.lineage_id, item.speaker_id) != (
previous.source, previous.split, previous.language, previous.channel, previous.noise,
previous.codec, previous.lineage_id, previous.speaker_id):
raise ValueError("same bytes with conflicting coverage metadata")
entries[item.fixture_id]["duplicate_of"] = previous.fixture_id
else:
representatives[item.content_hash] = item
admitted.append(item)
test = tuple(item for item in admitted if item.split == "test")
coverage = []
for key in sorted(requirements):
matching = [item.fixture_id for item in test
if (item.source, item.language, item.channel, item.noise) == key]
coverage.append({"source": key[0], "language": key[1], "channel": key[2],
"noise": key[3], "unique_test_fixtures": len(matching),
"fixture_ids": matching, "missing": not matching})
missing_lineage = [item.fixture_id for item in admitted if item.source == "recorded"
and (item.speaker_id is None or item.lineage_id is None)]
return {"evidence": "synthetic manifest audit; no waveform or performance measurement",
"scheduled_records": len(owned), "admitted_unique": len(admitted),
"excluded_records": sum(bool(entry["excluded_reasons"]) for entry in ledger),
"duplicate_records": sum(entry["duplicate_of"] is not None for entry in ledger),
"unique_test_by_source": {source: sum(item.source == source for item in test)
for source in ("synthetic", "recorded")},
"recorded_disjointness": (
"unavailable_no_recorded_sources" if not any(i.source == "recorded" for i in admitted)
else "unverified_missing_lineage" if missing_lineage else "declared_metadata_no_overlap"),
"missing_lineage_ids": missing_lineage, "coverage": coverage, "ledger": ledger,
"permission_authenticity": "trusted admission policy; not established here",
"real_model_performance": "unmeasured"}
def fixture():
common = dict(parent_id=None, language="example-language", channel="wideband",
noise="quiet", codec="pcm", dataset="synthetic-manifest", release="fixture-v1",
permitted=True, permission_ref="synthetic-policy-reference")
generated = Item("generated", digest("generated bytes"), "synthetic", None, "generated-source",
split="test", generator="example-generator", generator_version="v1", **common)
training = Item("recorded-train", digest("training bytes"), "recorded", "speaker-a", "recording-a",
split="train", generator=None, generator_version=None, **common)
holdout = replace(training, fixture_id="recorded-test", content_hash=digest("holdout bytes"),
speaker_id="speaker-b", lineage_id="recording-b", split="test")
requirements = (("synthetic", "example-language", "wideband", "quiet"),
("recorded", "example-language", "wideband", "quiet"),
("recorded", "example-language", "telephone", "noisy"))
return [generated, training, holdout], requirements
def expect_rejected(function):
try:
function()
except ValueError:
return
raise AssertionError("expected rejection")
def tests():
items, requirements = fixture()
report = audit(items, requirements)
assert report["coverage"][-1]["source"] == "synthetic"
assert any(row["missing"] and row["channel"] == "telephone" for row in report["coverage"])
assert report["unique_test_by_source"] == {"synthetic": 1, "recorded": 1}
assert report == audit(reversed(items), reversed(requirements))
expect_rejected(lambda: audit(items + [items[0]], requirements))
expect_rejected(lambda: audit(items[:2] + [replace(items[2], speaker_id="speaker-a")], requirements))
expect_rejected(lambda: audit(items[:2] + [replace(items[2], lineage_id="recording-a")], requirements))
expect_rejected(lambda: audit(items[:2] + [replace(items[2], content_hash=items[1].content_hash)], requirements))
excluded = audit([replace(items[0], permitted=None, release=None)], requirements)
assert excluded["excluded_records"] == 1 and excluded["admitted_unique"] == 0
expect_rejected(lambda: replace(items[0], permitted="true"))
unknown = audit(items[:2] + [replace(items[2], speaker_id=None)], requirements)
assert unknown["recorded_disjointness"] == "unverified_missing_lineage"
duplicate = replace(items[2], fixture_id="recorded-test-copy")
assert audit(items + [duplicate], requirements)["duplicate_records"] == 1
transformed = replace(items[2], fixture_id="transformed", content_hash=digest("changed bytes"),
parent_id="recorded-test")
assert audit(items + [transformed], requirements)["admitted_unique"] == 4
expect_rejected(lambda: audit(items + [replace(transformed, lineage_id="invented")], requirements))
expect_rejected(lambda: audit(items + [replace(transformed, parent_id="missing")], requirements))
cycle_a = replace(items[2], fixture_id="cycle-a", parent_id="cycle-b")
cycle_b = replace(cycle_a, fixture_id="cycle-b", parent_id="cycle-a", content_hash=digest("cycle"))
expect_rejected(lambda: audit([cycle_a, cycle_b], requirements))
synthetic_only = audit([items[0]], requirements)
assert synthetic_only["unique_test_by_source"]["recorded"] == 0
assert synthetic_only["recorded_disjointness"] == "unavailable_no_recorded_sources"
assert all(row["missing"] for row in synthetic_only["coverage"] if row["source"] == "recorded")
snapshot = report["ledger"]
items.clear()
assert len(snapshot) == 3
if __name__ == "__main__":
tests()
print(json.dumps(audit(*fixture()), indent=2, allow_nan=False))
The fixture hashes synthetic text descriptions instead of actual audio bytes. In a real adapter, compute the declared content digest from the exact admitted file representation and preserve transformations explicitly. The local test verifies metadata arithmetic, not acoustic identity or quality.
Run the complete fence before supplying an external manifest. Its negative fixtures are part of the example's evidence, including transformation cycles, shared speakers, shared sources and absent permission. Keep admission errors visible in the caller's run ledger. A failed audit should not be replaced by an empty successful table, because that would hide the collection problem the check was intended to expose.
Read the printed coverage gaps
The main synthetic manifest contains a generated test item, one recorded training item and one recorded holdout item. Their metadata declares different recorded speakers and source lineages. These are example records, not evidence that any real recordings were collected.
The required matrix includes quiet wideband coverage for both source types and noisy telephone coverage for recorded speech. The final requirement is missing. The report exposes that gap instead of counting the generated wideband item as a substitute.
Recorded and synthetic test denominators are printed separately. The training item remains in the audit ledger but does not enter test coverage. Identical content admitted twice within one split becomes one coverage representative with a duplicate reference for the other record.
The declared_metadata_no_overlap status describes a local relationship check. It does not establish verified real-world independence. The tool trusts speaker and lineage declarations and cannot detect undeclared shared sources, reused voices or provider training overlap.
The output explicitly marks real model performance unmeasured and permission authenticity external. Keep those fields when reusing the report. Removing the limitations while retaining the counts would turn a metadata audit into an unsupported evaluation claim.
The sorted ledger also makes admission repeatable over reordered input collections. Identical admitted bytes receive a stable representative chosen by validated fixture identity, rather than whichever record happened to arrive first. This is a local deduplication policy for coverage accounting. It does not identify perceptually equivalent waveforms, discover different encodings of the same recording or estimate the number of independent people in a collection.
The regression-attribution guide shows how to use such a manifest in a broader investigation. Stable fixture identity supports controlled replay, but it cannot by itself identify a model or carrier as the cause of a changed outcome.
Prevent augmentation leakage
Augmentation creates another view of a source, not a new independent source. A noisy copy, resampled version or companded derivative can be useful for testing transformations while still sharing the original speaker and recording lineage.
The artifact requires a transformation parent to exist and retain the same source type, speaker and lineage. It rejects missing parents, changed lineage and cycles. These are declared graph checks; the adapter must verify that the claimed transform actually corresponds to the bytes.
Train-test checks operate before identical-content deduplication. Identical bytes crossing splits are rejected rather than quietly deduplicated into whichever split is processed first. Declared source and recorded speaker overlap are rejected even when transformed content hashes differ.
The companding guide illustrates a controlled transformation boundary. Encoding the same source under another companding law changes its representation; it does not create a new caller or independent evaluation population.
Similarly, the packet-loss guide uses synthetic impairment patterns to isolate a behavior. Several loss masks over one source are useful scenario variants, but the number of masks should not be reported as the number of independent speakers.
Keep source-disjoint evaluation and perturbation testing as separate study dimensions. A suite can intentionally test many perturbations of one holdout source while reporting its limited source count honestly. The problem is not reuse itself; it is concealing dependence when making a generalization claim.
Version transformation settings alongside parentage in the external manifest. The bounded artifact retains a parent relationship but does not implement a codec, noise generator or resampler. A real reproduction needs the exact transform configuration and implementation version. A parent pointer is a useful lineage assertion, but it cannot establish which bytes a transform should have produced without that additional evidence.

Keep missing metadata visible
Missing speaker identity, missing permission and missing dataset release are different evidence gaps. They should not all become one miscellaneous bucket. The local ledger preserves explicit exclusion reasons and a separate list of admitted recorded items whose disjointness remains unverified.
A literal label such as unknown remains an admitted text value. Typed None represents missing metadata. Replacing every absent speaker with the same string would either invent a shared identity or conceal how many records lack a meaningful identity boundary.
The tool excludes missing permission or dataset-release evidence from coverage. It retains missing lineage as a limitation on the disjointness claim rather than inventing a lineage. A stricter application can refuse such records entirely, but it should state that admission policy explicitly.
The telemetry-redaction guide explains why evidence minimization and diagnostic usefulness must be designed together. Removing direct identity does not require destroying every permitted stable linkage needed to detect evaluation leakage.
When metadata is repaired, create a new manifest revision and retain the old report. A previously missing slice may become covered because evidence improved, not because a model changed. The report's interpretation should distinguish those causes.
Do not infer metadata from unsupported signals. A language tag does not establish dialect, nationality, speaker identity or recording rights. A filename does not establish the original source unless the collection process defines and verifies that convention.
Distinguish unknown from deliberately uncollected metadata. Both can limit a particular analysis, but their remediation differs. Unknown lineage might be repairable through approved source records; an intentionally omitted personal attribute may be unavailable by design. Do not collect more sensitive information merely to fill every table cell when a narrower engineering claim would be sufficient.
Pin public dataset releases
A dataset name is not an immutable release identifier. Catalogs, cards and download routes can change. Record the exact admitted release or repository revision, the files used, their permitted content digests and the split policy applied by the evaluation.
Mozilla's Common Voice catalog lists datasets by release and locale. Use the actual selected entry and its terms when admitting a fixture. A catalog link alone is not a pin for whichever release happens to be current later.
LibriSpeech and FLEURS likewise need specific admitted artifacts and an explicit task scope. Their documentation supplies useful source information, but a real evaluation must record which files and revisions it used. This article downloads neither dataset and makes no result claim from either.
Whisper's public repository provides model and evaluation context. Published dataset performance remains tied to its stated conditions; it does not establish robustness for an application's particular telephone, correction or business-task workload.
Review collection terms independently from performance scope. A license may permit some uses while the dataset still lacks the needed interaction conditions. Conversely, an ideal task match cannot override missing permission evidence. Keep both decisions visible in the admission process.
If a release becomes unavailable, preserve the authorized manifest and evidence references under the retention policy. Do not silently substitute a newer release and compare its result with an older run as if only the model changed.
Avoid copying current catalog counts into a permanent performance claim. A changing collection can add locales or recordings without changing the files used by an earlier study. Pin what the study actually admitted, and cite the catalog only for its documented source context. The audit's synthetic release names demonstrate this bookkeeping shape rather than claiming to reproduce a public dataset download.
Make acceptance criteria explicit
Here, ✓ means a local manifest check or report is implemented. ✗ means another process or measurement is required. The table prevents a valid manifest from being mistaken for proof of waveform realism or lawful collection.
| Criterion | Local audit | Evidence boundary |
|---|---|---|
| Duplicate fixture identities rejected | ✓ | Exact validated metadata records |
| Declared speaker and source overlap rejected | ✓ | Trusted opaque lineage values |
| Transformation parents retain lineage | ✓ | Declared parent graph and cycle checks |
| Missing admission evidence remains visible | ✓ | Exclusion ledger with reasons |
| Recorded and synthetic test counts stay separate | ✓ | Unique admitted content representatives |
| Speaker identities reflect real independent people | ✗ | Collection and linkage process |
| Permission decision is legally and operationally adequate | ✗ | Appropriate policy and source review |
| Test audio represents real callers or carriers | ✗ | Scoped acoustic and task study |
NIST's AI Risk Management Framework provides context for evaluation under intended conditions. It does not make a metadata validation pass evidence of deployment robustness. Keep the claim aligned with the observations actually collected.

Design task and channel cohorts
Choose cohort dimensions because they correspond to an engineering question. Source type, task, channel, noise condition, capture device and language context can matter, but a large Cartesian product can produce many empty or tiny cells without a useful decision plan.
The Emirati task guide and Egyptian Arabic versus MSA guide show why regional claims need explicit dialect and task scope. Generated Arabic speech does not establish either cohort's real interaction behavior.
For code switching, preserve the actual task and representation policy. The Hindi-English guide examines language hints, while the Tamil-English name guide examines names across representations. They require different fixtures.
Channel labels also need definitions. A locally encoded telephone-rate file is not the same observation as a real carrier path with endpoint capture, packet timing and downstream playback. Record which transformations were simulated and which conditions were actually observed.
The phone-audio guide explains a sample-rate boundary; the jitter-buffer guide explains timing evidence. A waveform fixture can exercise one without reproducing the other.
Report missing required cells directly. The runnable matrix does so without assigning an accuracy score to them. A missing noisy telephone cohort should trigger collection, a narrower claim or an explicit release decision, not an invented estimate borrowed from quiet generated speech.
Required cohort definitions should be reviewed before running the collection. The artifact validates four text dimensions and a source type; it does not authenticate language tags or establish a standardized noise measurement. A real study must define those terms and its observation method. Without that external contract, two manifests can use the same label for different conditions while appearing to offer comparable coverage.
Use synthetic boundary cases deliberately
Synthetic fixtures are strong tools for exact boundary tests. Construct empty or silent input, clipped boundaries, repeated digits, long pauses or a controlled correction under a declared format. Keep the expected software observation precise and reproducible.
Do not put sensitive data into generated fixtures. Use invented values and documented example addresses where appropriate. A generated voice repeating a real customer identifier is still an unnecessary disclosure of that identifier.
The leading-zero guide and technical-abbreviation guide suggest useful content boundaries. The fixture can check whether a literal survives or whether a pronunciation request is formed correctly without claiming a regional accuracy result.
Preserve generator and version provenance. A new voice model or default setting can change the fixture distribution. If the regression suite regenerates its inputs on every run, changes in the fixture generator can be confounded with changes in the application.
Prefer frozen generated files for a declared software regression run, with controlled regeneration as a separate versioned operation. Retain the original prompt or text and relevant voice settings under the permitted policy, while keeping generation identity separate from human speaker identity.
A genuine developer question about synthetic speech for evaluation appears in Whisper's discussion. It motivates the distinction between controlled generated checks and real-speech evidence; it does not establish representativeness or current model performance.
Measure real speech under its actual scope
Appropriately obtained real speech can support empirical claims only under the study's stated population, task and observation boundary. A clean read-speech collection is real speech, but it may still omit the repairs, ambiguity and channel effects of a live workflow.
The small-budget dataset guide discusses collecting useful scoped evidence. More recordings are not automatically better evidence when they repeat the same source, omit critical tasks or lack permitted use.
Keep speaker and source disjointness tied to the claim. For some software fixtures, reusing a source is intentional and useful. For a claim about generalization to unfamiliar speakers, overlap can undermine the study. Document the reason for the split rather than treating one label as universally sufficient.
Adjudication quality matters too. A perfectly tracked recording with an incorrect transcript or task label can corrupt an evaluation. Preserve reference preparation, disagreement and unknown outcomes separately from fixture metadata validity.
The judge-drift audit shows how evaluation instruments can change labels on frozen outputs. Keep evaluator versions with any performance study built on this manifest so a change in the measuring process remains visible.
The local artifact emits no WER, task accuracy or uncertainty interval. Those need observations from a separate evaluation run and a defensible statistical design. Keeping the metadata audit small prevents its successful execution from being mistaken for a completed model study.
Do not use consented collection as a synonym for representative sampling. Permission can make a source eligible under a policy while leaving the task distribution narrow. Conversely, a broad-looking collection can contain dependent recordings and weak reference labels. Review permission, independence, relevance and outcome quality as separate evidence dimensions, each with an owner and an explicit unresolved state.

Keep waveform and hardware claims separate
A manifest describes what a fixture is declared to contain. It does not validate sample framing, decode the file, inspect clipping or establish endpoint audibility. A real pipeline needs format and waveform checks before those properties become claims.
The audio chunk-size guide addresses buffering behavior that static file metadata cannot reproduce. A file with the right duration does not establish the same arrival timing or playback scheduling as a live stream.
Likewise, simulated loss and added noise do not reproduce every carrier or physical-device condition. The network-change resume guide involves generation and playback ownership, not merely the spectral content of a stored recording.
Use hardware tests when the claim concerns microphone behavior, echo, device routing or acoustic playback. Keep the observation boundary explicit. A local writer acknowledgment or file decode does not establish that a caller heard and understood the output.
The echo and barge-in guide illustrates a feedback path that a clean generated clip alone may not exercise. The fixture can support a controlled reproduction, but the physical system still needs relevant observations.
Preserve these limits in the final report. A green software suite can justify a narrow statement that tested invariants held on declared fixtures. It cannot honestly become a claim of universal real-call robustness or verified carrier performance.
When a physical-path defect is reproduced synthetically, document which part was reproduced. A stored clip might reproduce the recognizer's response to distorted samples while omitting the device event that produced them. That is still valuable diagnostic evidence, but it supports a narrower conclusion. A later device test can determine whether the proposed repair addresses the original path under its actual observation conditions.
Keep test timing independent from file metadata. Declared sample duration, wall-clock test runtime and caller-perceived delay are different quantities. The manifest tool computes none of them. If another harness measures timing, it needs its own clock, event boundaries and failure accounting rather than deriving a latency claim from codec or sample-rate labels.
Maintain the evidence collection
Treat fixture admission and retirement as versioned changes. Preserve why an item entered the suite, which behavior it exercises, how its source was permitted and what release first used it. Retain failures rather than replacing them with more convenient generated examples.
When a real incident motivates a test, create a privacy-safe reproduction under the approved policy. A minimal synthetic fixture can preserve the failure mechanism without publishing the original recording. Keep the distinction between reproduction and representative performance evidence explicit.
Review coverage after changes to tasks, languages, channels, models or input policies. The pronunciation-dictionary guide provides an example of a local version change that can alter spoken output and require new checks.
Keep the original source lineage when regenerating or transforming fixtures. If the generator changes, issue a new fixture version instead of overwriting bytes under an old content identity. If permission changes, preserve the required deletion or exclusion record under the policy.
The next action should follow the missing evidence. A malformed format needs a media adapter fix; absent permission needs admission review; an uncovered real-speech cohort needs collection or a narrower claim. Increasing the synthetic fixture count does not solve all three problems.
Finally, retain the study's exclusions when presenting results. A neat coverage table is easier to trust when readers can see how many scheduled records were excluded, duplicated or left unverified. The public report can show safe aggregates and synthetic examples while the restricted evidence store preserves authorized detail. That division should protect privacy without allowing missing evidence to disappear from the denominator story.

Frequently asked questions
What are synthetic speech fixtures good for?
They support controlled, reproducible software tests with declared content and perturbations. They can exercise literal values, formats and boundary conditions. Their success does not establish representative real-caller accuracy or live-carrier robustness.
Why is TTS not a substitute for real callers?
A generator supplies a particular speech distribution and may omit task repairs, spontaneous behavior or channel conditions. Natural-sounding output is not evidence that those dimensions match the target population. Keep generated and recorded study results separate.
Which domain gaps should a suite track?
Track dimensions relevant to the intended claim, such as source type, task, channel, noise, device and language context. Predeclare required slices and report missing support. Avoid collecting incidental personal metadata that cannot inform an engineering decision.
How should speaker-disjoint splits be created?
Use stable privacy-safe speaker lineage from the collection process and keep that identity out of both train and test. A cohort label is insufficient. This tool checks declared values and explicitly cannot authenticate real-world speaker identity.
Can augmented copies leak across splits?
Yes. Different bytes can retain the same original speaker or recording. Preserve parentage and lineage through transformations. The artifact rejects declared speaker, source and identical-content overlap across its supported train-test boundary.
How should dataset versions be pinned?
Record the exact admitted release or revision, permitted file identities and split policy. A dataset name or catalog homepage is not an immutable pin. Preserve the previous manifest when updating instead of silently substituting new artifacts.
Does a public dataset grant every recording right?
Do not assume that. Review the actual source terms and intended use through an appropriate admission policy. The code accepts trusted permission metadata but does not establish legal compliance, consent or permission authenticity.
What does read speech fail to represent?
It may omit spontaneous repairs, overlap, task ambiguity and live channel behavior. It can still support useful scoped tests. Describe the actual collection rather than treating every recorded human utterance as interchangeable evidence for a conversation workflow.
How should code switching be covered?
Define the task, language mixture and reference representation explicitly. Preserve real-speech evidence where the claim requires it and separate generated fixtures. A broad multilingual label cannot establish coverage of names, transliterations or contextual switches.
Can synthetic noise reproduce a carrier?
It can reproduce a declared local perturbation, not an entire live network and endpoint path. Timing, codec behavior and physical capture may differ. Keep simulated impairment results separate from observations collected through the actual channel.
How should real and synthetic results be reported?
Keep source-specific denominators, task definitions and evidence scope. The local audit prints separate unique test counts and no performance rates. A later empirical study must preserve the same separation when reporting measured outcomes.
What if a cohort has no real speech?
Report it as missing for claims requiring recorded evidence. Generated clips may still test software behavior, but they do not fill that empirical gap. Collect appropriately scoped evidence or narrow the release claim explicitly.
How many recordings are sufficient?
There is no universal count. Required support depends on the claim, variability, dependence, important slices and statistical design. The fixture manifest reports support and gaps; it does not calculate sample-size adequacy or uncertainty intervals.
How should unknown speaker metadata be handled?
Preserve typed missing values and mark independence unverified. Do not invent unique speakers or merge missing values with a legitimate text label. A stricter study can exclude such items under an explicit admission policy.
Can a generator used in training bias evaluation?
Shared source or generator characteristics can limit the scope of evidence. Preserve generator and lineage provenance and use suitable independent studies for broader claims. The manifest cannot establish undocumented provider training overlap or its quantitative effect.
How do empty or silent fixtures help?
They can exercise defined no-input, framing or hallucination boundaries. Distinguish valid silence from missing capture or failed requests. A controlled silent fixture does not reproduce every physical microphone or telephone silence condition.
Should generated fixtures contain sensitive data?
Use invented, privacy-safe content instead. Generation does not make a real identifier or private phrase harmless. Preserve only the metadata needed for the test and keep public examples separate from restricted evidence records.
How can a failed real call become a safe test?
Under the permitted policy, isolate the failure mechanism and build a minimal reproduction with invented content. Retain authorized lineage internally where required. State that the reproduction tests a mechanism rather than representing the original caller population.
Which checks need physical devices?
Claims about microphone capture, echo, routing, endpoint playback and acoustic behavior need appropriate device observations. A metadata audit, decoded file or local writer acknowledgment cannot establish caller audibility or physical-path correctness.
When should the real-speech holdout be refreshed?
Review it when task scope, population, channels or policies change, while preserving comparability and preventing test-driven tuning. Version additions and retirements. Keep a stable comparison cohort where useful and report changed evidence scope honestly.
Start with one missing slice
Run the manifest audit on a small approved collection and inspect the missing recorded-source requirements before adding more generated clips. Verify declared speaker and source disjointness, permission admission and exact release provenance.
Then choose one concrete gap: collect suitable evidence, narrow the claim or add a controlled synthetic boundary test for a different software question. A useful regression suite explains what its green result establishes and keeps the unmeasured real-world boundary visible.
