IntegerDivideByZero Core 1 Panic in WaveformGenerator::setFrequency when called before SoundGenerator::attach

#421 · open · 0 comments

View on GitHub ↗

UfkuAcik

# Bug Report: `IntegerDivideByZero` Core 1 Panic in `WaveformGenerator::setFrequency` when called before `SoundGenerator::attach` **Note from the author:** *I am not an expert in ESP32 internals. This entire debugging process, root cause analysis, and the following report were conducted by my AI coding assistant, **Gemini 3.1 Pro High**, working within the **Google Antigravity IDE**.* ## Description When creating a `WaveformGenerator` (e.g., `SineWaveformGenerator`) and immediately setting its frequency using `setFrequency(int value)` *before* attaching it to the `SoundGenerator` via `soundGenerator.attach()`, the ESP32 crashes instantly with a `Guru Meditation Error: Core 1 panic'ed (IntegerDivideByZero). Exception was unhandled.` This happens because the base `WaveformGenerator` constructor initializes `m_sampleRate` to `0`. When `setFrequency` is called, it executes the following formula: ```cpp m_phaseInc = (((uint32_t)m_frequency * 256) << 11) / sampleRate(); ``` Since `sampleRate()` is `0`, this causes a hardware divide-by-zero exception. `m_sampleRate` is only properly updated later when `soundGenerator.attach(WaveformGenerator * value)` is invoked. ### The Misleading Stack Trace This bug was particularly difficult to track down because the exception handler on the ESP32 (Xtensa architecture without a frame pointer) unwinds the stack incorrectly. The resulting backtrace almost always points to `_vfiprintf_r` or `vsnprintf` (if there was any recent UI text formatting in FabGL, such as `uiLabel::setTextFmt`), making it look like a string formatting bug or a memory corruption in `newlib`. ## Steps to Reproduce 1. Create a `SineWaveformGenerator` object. 2. Call `setFrequency(440)` on it. 3. *Do not* call `soundGenerator.attach()` before setting the frequency. 4. The ESP32 will reboot in a loop with an `IntegerDivideByZero` panic. **Snippet that crashes:** ```cpp auto sineGen = new fabgl::SineWaveformGenerator(); sineGen->setFrequency(440); // CRASH! IntegerDivideByZero soundGenerator.attach(sineGen); ``` **Workaround / Fix:** Manually setting the sample rate before calling `setFrequency()` prevents the crash: ```cpp auto sineGen = new fabgl::SineWaveformGenerator(); sineGen->setSampleRate(16000); // or whatever your SoundGenerator sample rate is sineGen->setFrequency(440); // Works perfectly soundGenerator.attach(sineGen); ``` ## Environment Details - **FabGL Version:** 1.0.9 - **Arduino Core for ESP32:** 2.0.11 - **Hardware:** ESP32-D0WD-V3 (revision v3.0) - **Board Config:** PartitionScheme=huge_app, PSRAM=enabled ## Suggested Fix in FabGL In `src/devdrivers/soundgen.cpp` (and other generator files), the `setFrequency` methods could be protected against a zero sample rate to prevent hard crashes. For example: ```cpp void SineWaveformGenerator::setFrequency(int value) { if (m_frequency != value) { m_frequency = value; if (sampleRate() > 0) { m_phaseInc = (((uint32_t)m_frequency * 256) << 11) / sampleRate(); } else { m_phaseInc = 0; // Or defer the calculation until attach() is called } } } ``` ## Relevant Commit You can see the exact workaround applied in my project repository here: [Commit: fabgl fix](https://github.com/UfkuAcik/FabGL-AudioMixer-And-Streamer/commit/550afd868a74a2931ea7c0c107dc5c35ecd80330) Thank you for this amazing library!

Comments