Skip to content

fix(asr): pad random_segment with an integer sample count - #16105

Open
udsy19 wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
udsy19:fix/random-segment-pad-int
Open

fix(asr): pad random_segment with an integer sample count#16105
udsy19 wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
udsy19:fix/random-segment-pad-int

Conversation

@udsy19

@udsy19 udsy19 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

What does this PR do ?

Fixes RandomSegmentPerturbation (random_segment augmentation) crashing with
TypeError: pad_width must be of integral type. whenever it has to pad a short utterance, and
corrects the SSL configuration doc that documents the padding behaviour but omits the flag that
enables it.

Collection: ASR

Changelog

  • nemo/collections/asr/parts/preprocessing/perturb.py: compute pad_size as an integer number
    of samples with math.ceil, so AudioSegment.pad -> numpy.pad receives an integral
    pad_width. Previously duration_sec * sample_rate - num_samples was a float whenever
    duration_sec was a float — including the constructor default 32.0 — and every short
    utterance raised TypeError. math.ceil rather than round/truncation is deliberate: the
    next statement is subsegment(0.0, duration_sec), which raises ValueError if the segment
    ends up shorter than duration_sec, so the padded length must not round down. subsegment
    then trims to exactly round(duration_sec * sample_rate) samples, matching the non-padding
    branch.
  • docs/source/asr/ssl/configs.rst: add pad_to_duration: true to the random_segment snippet.
    The surrounding text says "samples below the provided segment length will be padded", but the
    snippet omitted the flag and it defaults to False, so the documented recipe silently did not
    pad — which defeats its stated purpose of keeping durations uniform inside an SSL batch.
  • tests/collections/asr/test_preprocessing_segment.py: add TestRandomSegmentPerturbation
    covering int and float duration_sec, the zero-fill placement, sample rates where
    duration_sec * sample_rate is not a whole number (22050 Hz), the pad_to_duration=False
    default, and the non-padding branch. There was previously no test for this perturbation.

Usage

import numpy as np
from nemo.collections.asr.parts.preprocessing.perturb import RandomSegmentPerturbation
from nemo.collections.asr.parts.preprocessing.segment import AudioSegment

seg = AudioSegment(np.zeros(16000 * 5, dtype=np.float32), 16000)      # 5 s
RandomSegmentPerturbation(duration_sec=32.0, pad_to_duration=True).perturb(seg)
len(seg.samples)   # before: TypeError    after: 512000

Equivalently, from a training config:

model:
  train_ds:
    augmentor:
      random_segment:
        prob: 1.0
        duration_sec: 16.0
        pad_to_duration: true

GitHub Actions CI

Checks run locally (macOS, CPU, Python 3.10.18, torch 2.12.0, numpy 2.2.6):

  • pre-commit run --from-ref main --to-ref HEAD — all hooks pass (isort, black 24.10.0,
    check-case-conflict, detect-private-key, check-added-large-files).
  • pytest tests/collections/asr/test_preprocessing_segment.py -m "not pleasefixme" — 73 passed.
  • pytest tests/collections/asr -m "not pleasefixme" — 1402 passed, 402 skipped, 26 failed,
    12 errors. All 38 failures/errors are pre-existing on main and environmental on a CPU-only
    macOS box (*_gpu parametrisations, ONNX/TorchScript export, model-download errors); none is
    in preprocessing or perturbation code. Verified by re-running the 7 affected files with
    perturb.py reverted to main: the failure sets are byte-identical, so this change
    introduces no new failures.
  • Regression check: with perturb.py reverted to main and the new tests in place, 6 of the 10
    new cases fail (TypeError: pad_width must be of integral type.); the 4 that pass are the
    int-duration_sec, pad_to_duration=False and long-audio controls. All 10 pass with the fix.
  • git diff --check — clean.
  • Not run: the Sphinx docs build. The doc change is one line inside an existing
    .. code-block:: yaml and adds no directive, role or reference; the snippet was parsed with
    yaml.safe_load to confirm it is still valid.

Before your PR is "Ready for review"

Pre checks:

  • Make sure you read and followed Contributor guidelines
  • Did you write any new necessary tests?
  • Did you add or update any necessary documentation?
  • Does the PR affect components that are optional to install? (Ex: Numba, Pynini, Apex etc)
    • No. math is stdlib; no new dependency and no optional import.

PR Type:

  • New Feature
  • Bugfix
  • Documentation

Additional Information

`RandomSegmentPerturbation.perturb` computed `pad_size` as
`duration_sec * sample_rate - num_samples`. `duration_sec` is a float
(the constructor default is `32.0`), so `pad_size` was a float and
`AudioSegment.pad` forwarded it to `numpy.pad`, which rejects a
non-integral `pad_width`:

    TypeError: `pad_width` must be of integral type.

Every utterance shorter than `duration_sec` therefore crashed training
whenever `pad_to_duration` was enabled, unless `duration_sec` happened to
be written as an integer in the YAML config.

Round up rather than to nearest: `perturb` immediately calls
`subsegment(0.0, duration_sec)`, and `subsegment` raises `ValueError` when
`end_time` exceeds the segment duration. Rounding to nearest can leave the
padded segment marginally shorter than `duration_sec` (for example
`duration_sec=0.35` at 22050 Hz), which would swap the `TypeError` for a
`ValueError`. `math.ceil` keeps the segment at least `duration_sec` long;
`subsegment` then trims it to exactly `round(duration_sec * sample_rate)`
samples, matching the non-padding branch.

Also add `pad_to_duration` to the `random_segment` snippet in the SSL
configuration docs. The surrounding text states that "samples below the
provided segment length will be padded", but the snippet omitted the flag
and it defaults to `False`, so the documented recipe silently did not pad.

Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the ASR label Aug 18, 2026
@svcnvidia-nemo-ci svcnvidia-nemo-ci added the waiting-on-maintainers Waiting on maintainers to respond label Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ASR community-request waiting-on-maintainers Waiting on maintainers to respond

Projects

None yet

Development

Successfully merging this pull request may close these issues.

random_segment augmentation raises TypeError: pad_width must be of integral type whenever it has to pad

2 participants