Skip to content

MoonModules Audio driver node#178

Open
netmindz wants to merge 2 commits into
MoonModules:mainfrom
netmindz:MoonModulesAudio
Open

MoonModules Audio driver node#178
netmindz wants to merge 2 commits into
MoonModules:mainfrom
netmindz:MoonModulesAudio

Conversation

@netmindz
Copy link
Copy Markdown
Collaborator

@netmindz netmindz commented Jun 7, 2026

Add a new Node Driver that allows for using MoonModules's Audio Reactive library

Summary by CodeRabbit

  • New Features

    • Added a MoonModules Audio driver that captures local mic/codec audio and publishes FFT bands, volume, peak frequency, and limiter-adjusted levels to shared data.
    • New runtime controls: mic type selection, AGC, squelch, gain, input level, limiter, and read-only lifecycle status.
  • Documentation

    • Added comprehensive spec describing driver behavior, supported hardware, configuration, wiring, and known limitations.

Specifies D_MoonModulesAudio.h — a local I2S audio capture driver that
runs the WLEDMM audio pipeline (AudioFilters/AGC/FFT) and writes to
sharedData.bands/volume/majorPeak/magnitude, as an alternative to the
UDP-based WLEDAudioDriver.

Covers: library integration (OO-split branch), WLED compatibility shim,
build system changes (FT_MOONLIGHT_AUDIO / S3+P4 only), all 11 mic types,
pin management, sharedData mapping, and node registration.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 7, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 732b2db6-a9a2-4424-8974-69b2902a8a9a

📥 Commits

Reviewing files that changed from the base of the PR and between f71c44f and 8cc5747.

📒 Files selected for processing (1)
  • src/MoonLight/Nodes/Drivers/D_MoonModulesAudio.h

Walkthrough

Adds a new implementation spec and a gated-in driver header for FT_MOONLIGHT_AUDIO that define build wiring, WLED compatibility shims, node controls and pin management, mic-type→AudioSource mapping, audio processing pipeline/FFT task, runtime loop/teardown, and integration constraints.

Changes

MoonModules Audio Driver Specification & Header

Layer / File(s) Summary
Driver overview & build integration
misc/specs/D_MoonModulesAudio.md
Driver purpose (local I2S mic/codec capture replacing WLEDAudioDriver stub), external libs (WLED-AudioReactive-Usermod, arduinoFFT), PlatformIO [moonlight-audio] config and ESP32-S3/P4 wiring.
Compatibility shims & node registration
misc/specs/D_MoonModulesAudio.md
WLED compatibility shim requirements for audio_source.h (debug macros, PinManager stub, i2c_sda/i2c_scl) and MoonLight integration points (src/MoonBase/Nodes.h, src/MoonLight/Modules/ModuleDrivers.h).
Node controls & pin management
misc/specs/D_MoonModulesAudio.md
Node identity and UI controls (micType, soundAgc, squelch, gain, inputLevel, limiter, status), I2S pin vars, ModuleIO update handler, and readPins() restart logic including I2C codec readiness.
Microphone types & audio pipeline configuration
misc/specs/D_MoonModulesAudio.md
micTypeAudioSource mapping (I2C notes, SCK auto-detect), sample/block constants, filter/AGC/processor setup, and FFT FreeRTOS task start parameters.
Runtime execution & state management
misc/specs/D_MoonModulesAudio.md
Per-frame loop publishes 16-band FFT into sharedData, computes volume/volumeRaw/majorPeak/magnitude, defines stopService() teardown, and onUpdate() restart vs reconfigure rules.
Integration constraints & known limitations
misc/specs/D_MoonModulesAudio.md
Interaction notes with WLEDAudioDriver and FastLEDAudioDriver (shared I2S constraint) and listed limitations/future work.
Driver header: banner, gating, constants
src/MoonLight/Nodes/Drivers/D_MoonModulesAudio.h
Adds header banner, #pragma once, FT_MOONLIGHT_AUDIO gating, MMA_SAMPLE_RATE, MMA_BLOCK_SIZE, and pin sentinel helper.
Driver header: class, setup, readPins
src/MoonLight/Nodes/Drivers/D_MoonModulesAudio.h
Introduces MoonModulesAudioDriver class, metadata, control members, setup() wiring, IO update handler registration, and readPins() behavior.
Driver header: startService & pipeline init
src/MoonLight/Nodes/Drivers/D_MoonModulesAudio.h
Implements startService() with pin conversion, micType resolution, optional I2C pin reads, createAudioSource(cfg), pipeline configuration, FFT/task start, and status/log updates.
Driver header: configure/reconfigure pipeline
src/MoonLight/Nodes/Drivers/D_MoonModulesAudio.h
configurePipeline() and reconfigurePipeline() wire AudioFilters, AGCController, and AudioProcessor parameters; supports in-place AGC/filter updates without FFT restart.
Driver header: stop, loop, onUpdate, destructor
src/MoonLight/Nodes/Drivers/D_MoonModulesAudio.h
stopService() stops FFT task and deletes AudioSource; loop() copies FFT bands and publishes volume/peaks; onUpdate() restarts on micType changes; destructor unregisters handler.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • WLED Audio Driver support #56: Same MoonLight audio driver node objectives (node lifecycle, sharedData audio outputs, driver registration) are addressed by this spec and header.

Possibly related PRs

  • MoonModules/MoonLight#165: Related work adding/propagating SharedData.magnitude and other FFT-derived fields that this driver writes into sharedData.

Poem

🐇 I hopped where I2S lines hum,
FFT bands danced, the night was young,
MoonLight listens, bits take flight,
Bunny grins — audio's just right! 🎧

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'MoonModules Audio driver node' clearly and concisely describes the main change: adding a new audio driver node implementation for MoonModules integration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@misc/specs/D_MoonModulesAudio.md`:
- Around line 142-147: The fenced code block containing the lines with name(),
dim(), tags(), and category() lacks a language identifier; update the markdown
fence to include a language tag (for example "text") so the block reads ```text
... ``` to satisfy markdownlint MD040 and keep the docs-lint clean.
- Around line 201-211: The documentation mismatches the implementation: either
include an explicit check for the I2C readiness flag or remove the claim that
"first checks that I2CReady is true." Update the snippet around moduleIO->read
and initialize() to explicitly read the I2CReady flag from ModuleState (e.g.,
state.data["I2CReady"].as<bool>() or similar) and guard the path by returning
with updateControl("status", "Error: I2C not configured") if I2CReady is false,
or alternatively remove the phrase mentioning I2CReady so the text matches the
current sda/scl negative-value check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95a391dd-41c8-436d-a83a-39036b90b154

📥 Commits

Reviewing files that changed from the base of the PR and between 6586921 and f71c44f.

📒 Files selected for processing (1)
  • misc/specs/D_MoonModulesAudio.md

Comment on lines +142 to +147
```
name() → "MoonModules Audio"
dim() → _NoD
tags() → "☸️♫"
category() → "Driver"
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language identifier to this fenced code block.

This fence currently has no language tag (markdownlint MD040). Use a language (e.g., text) to keep docs-lint clean.

Proposed fix
-```
+```text
 name()     → "MoonModules Audio"
 dim()      → _NoD
 tags()     → "☸️♫"
 category() → "Driver"

</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 142-142: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@misc/specs/D_MoonModulesAudio.md` around lines 142 - 147, The fenced code
block containing the lines with name(), dim(), tags(), and category() lacks a
language identifier; update the markdown fence to include a language tag (for
example "text") so the block reads ```text ... ``` to satisfy markdownlint MD040
and keep the docs-lint clean.

Source: Linters/SAST tools

Comment on lines +201 to +211
**I2C codec pins:** For mic types that need I2C (ES7243=2, ES8388=6, WM8978=7, AC101=8, ES8311=9), the driver reads the global I2C SDA/SCL from ModuleIO state before calling `initialize()`. It first checks that `I2CReady` is true (same pattern as `D_IMU.h`):
```cpp
moduleIO->read([&](ModuleState& state) {
i2c_sda = (int8_t)state.data["sdaPin"].as<int>();
i2c_scl = (int8_t)state.data["sclPin"].as<int>();
}, name());
if (i2c_sda < 0 || i2c_scl < 0) {
updateControl("status", "Error: I2C not configured");
return;
}
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

I2C readiness contract is inconsistent in this section.

Line 201 says initialization “first checks that I2CReady is true,” but the provided snippet only reads sdaPin/sclPin and checks for negative values. Please either add the explicit I2CReady check to the documented flow/snippet or remove the claim, otherwise implementers may ship a mismatched guard path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@misc/specs/D_MoonModulesAudio.md` around lines 201 - 211, The documentation
mismatches the implementation: either include an explicit check for the I2C
readiness flag or remove the claim that "first checks that I2CReady is true."
Update the snippet around moduleIO->read and initialize() to explicitly read the
I2CReady flag from ModuleState (e.g., state.data["I2CReady"].as<bool>() or
similar) and guard the path by returning with updateControl("status", "Error:
I2C not configured") if I2CReady is false, or alternatively remove the phrase
mentioning I2CReady so the text matches the current sda/scl negative-value
check.

… switch

Replace the inline switch(micType) in startService() with an
AudioSourceConfig fill + createAudioSource() call from audio_source_factory.h.
The manual PDM auto-detect block is replaced by normalizeDmType().

All 10 mic types continue to work identically; the factory handles
the dmType-10 alias for legacy PDM internally.
@netmindz
Copy link
Copy Markdown
Collaborator Author

netmindz commented Jun 7, 2026

Currently crashing due to IS2 legacy issue, need to dig out the IDF V5 fix for that

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.

1 participant