Skip to content

Raise a descriptive error when unscaled integer audio is passed (fixes #407) - #491

Open
deekshaNVIDIA wants to merge 1 commit into
spotify:masterfrom
deekshaNVIDIA:raise-error-on-unscaled-integer-input
Open

Raise a descriptive error when unscaled integer audio is passed (fixes #407)#491
deekshaNVIDIA wants to merge 1 commit into
spotify:masterfrom
deekshaNVIDIA:raise-error-on-unscaled-integer-input

Conversation

@deekshaNVIDIA

Copy link
Copy Markdown

Summary

Fixes #407.

In several reported cases (#406, #390, #369), users passed integer PCM data (e.g. int16) that had been converted to float32/float64 without rescaling it into the [-1.0, 1.0] range that Pedalboard expects. Scale-invariant plugins (Reverb, Delay) appear to work, while others (Compressor, Limiter, PitchShift) fail in confusing ways.

This adds a small check in the shared C++ process() entry point in pedalboard/process.h — the single code path used by pedalboard.process(...), Plugin.process(...)/Plugin.__call__, and Pedalboard.__call__ (via Chain). If every sample is an exact integer and the peak magnitude exceeds 1.0, it raises a ValueError explaining the likely cause and the fix.

Behavior

  • Raises a descriptive ValueError for buffers that look like unscaled integer PCM data (e.g. (audio * 32767).astype(np.int16).astype(np.float32)).
  • Does not affect legitimate float audio. The check returns on the first fractional or non-finite sample, so for real-world audio it adds only a handful of instructions and never allocates.
  • In-range integer-valued buffers (digital silence, a full-scale ±1.0 square wave, DC at 1.0) are still accepted, since those are valid audio.

Why this location

process() in process.h is the single chokepoint that all Python-facing processing entry points route through, so the validation covers every case (Pedalboard, individual plugins, and the module-level process function) with one implementation. The check runs while the GIL is still held, before the heavy processing begins.

Notes on testing

I validated the detection heuristic numerically against the released pedalboard wheel across many signal types (sine waves, random noise, silence, full-scale DC/square waves, hot non-integer signals, empty and stereo buffers): zero false positives, and the documented int16-as-float32 case is caught (its peak of ~29490 otherwise reaches the Limiter).

tests/test_integer_input_validation.py is added to cover:

  • int16-as-float32 and -as-float64 raising ValueError via Pedalboard, a single Plugin, and pedalboard.process.
  • Correctly-rescaled integer data being accepted.
  • A range of legitimate float signals not being flagged.

I was unable to compile the native extension locally (no C++ toolchain on my machine), so I have not run the compiled test suite end-to-end — CI will build and run the new tests. ruff, black (line length 100), and flake8 all pass on the new test file.

Fixes spotify#407.

Users have repeatedly (spotify#406, spotify#390, spotify#369) passed integer PCM data (e.g.
int16) that was converted to float32/float64 without rescaling into the
[-1.0, 1.0] range Pedalboard expects. Scale-invariant plugins (Reverb,
Delay) appear to work while others (Compressor, Limiter, PitchShift) fail
confusingly.

This adds a fast check in the shared process() entry point (used by
Pedalboard, individual plugins, and pedalboard.process) that raises a
ValueError explaining the likely cause and fix when every sample is an
exact integer and the peak magnitude exceeds 1.0. The check bails out on
the first fractional or non-finite sample, so it is effectively free for
real audio.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Passing integer-valued samples out of range should raise a descriptive error.

1 participant