2025, Nov 27 21:00

resample_poly returns zeros on Raspberry Pi? Convert integer PCM to float64 before downsampling

Troubleshooting SciPy resample_poly on Raspberry Pi: zero output with integer PCM. Learn why dtype causes it and fix by casting audio buffers to float64.

When down-sampling audio with resample_poly to reduce CPU usage, you might run into an odd platform-specific failure: a snippet that behaves correctly on a PC returns an array of zeros on a Raspberry Pi 3B. The discrepancy can be especially confusing when NumPy and SciPy versions appear consistent. Below is a minimal example that captures the issue and a simple fix that avoids it without changing the signal processing logic.

Reproducing the problem

The following code downsamples a short integer buffer from 16 kHz to 4 kHz. On a PC it produces sensible values, while on a Raspberry Pi the result may be all zeros.

import numpy as np
from scipy.signal import resample_poly as rs_poly
buf = np.array([43, 58, 67, 88, 89, 99, 121, 113, 88, 69])
target_hz = 4000
source_hz = 16000
print(f"pre: {buf}")
buf = rs_poly(buf, target_hz, source_hz)
print(f"post: {buf}")

On PC: After [28.66957128 103.77145182 80.49835032]
On Pi: After [0. 0. 0.]

This behavior has been reported and aligns with a known issue in SciPy. In short, integer inputs can trigger an unexpected path that produces zeros on certain environments.

Why it happens

The core of the problem is the input dtype. Feeding an integer array into resample_poly can lead to an all-zero output on the Raspberry Pi in the affected versions. The same code on a PC processes the integers correctly, which makes the issue look like a platform discrepancy rather than a data-type pitfall. The mismatch disappears when the data is converted to floating point before calling resample_poly.

Fix: cast to floating point before resampling

If upgrading SciPy is not an option, ensure the data is floating point at the point of resampling. The signal processing result remains the same; only the input dtype changes.

Option 1: create the array as float64 from the start.

import numpy as np
from scipy.signal import resample_poly as rs_poly
buf = np.array([43, 58, 67, 88, 89, 99, 121, 113, 88, 69], dtype=np.float64)
target_hz = 4000
source_hz = 16000
print(f"pre: {buf}")
buf = rs_poly(buf, target_hz, source_hz)
print(f"post: {buf}")

Option 2: keep the original array as is and cast only at the call site.

import numpy as np
from scipy.signal import resample_poly as rs_poly
buf = np.array([43, 58, 67, 88, 89, 99, 121, 113, 88, 69])
target_hz = 4000
source_hz = 16000
print(f"pre: {buf}")
buf = rs_poly(buf.astype(np.float64), target_hz, source_hz)
print(f"post: {buf}")

Both approaches preserve the DSP logic and sampling parameters while avoiding the all-zero output on the Raspberry Pi.

Why this matters

Audio pipelines often originate as integer PCM, especially when you read from files or devices. If a function implicitly depends on floating-point arithmetic in your environment, passing integers can silently break the chain, giving zeros without errors. Ensuring the dtype matches the expected computation path keeps results consistent across machines and avoids hidden platform-specific gotchas.

Takeaways

If resample_poly returns zeros on a Raspberry Pi while working on a PC, check the dtype first. Converting the buffer to float64 before resampling is a minimal, robust workaround when upgrading SciPy isn’t feasible. Keep the rest of your pipeline unchanged, but make the dtype explicit at the resampling boundary to get consistent, non-zero results.