Skip to content

Add experimental PreSonus FireStudio Project support at 44.1/48 kHz - #105

Open
seeward wants to merge 10 commits into
mrmidi:mainfrom
seeward:pr/presonus-firestudio-project
Open

Add experimental PreSonus FireStudio Project support at 44.1/48 kHz#105
seeward wants to merge 10 commits into
mrmidi:mainfrom
seeward:pr/presonus-firestudio-project

Conversation

@seeward

@seeward seeward commented Sep 7, 2026

Copy link
Copy Markdown

Adds experimental support for the exact PreSonus FireStudio Project (0x000a92:0x00000b), using captured one-stream-per-direction geometry: ten PCM channels plus one MIDI slot, at 44.1 or 48 kHz. The 48 kHz default remains.

Raw-PCM hardware validation is complete within the tested scope. Local build 9 passed short silent tests and rate switching at 44.1/48 kHz, clear S/PDIF tones with quiet gaps through a Roland VM-3100 at 44.1 kHz, and subsequent GarageBand playback and clean shutdown. Earlier labelled-AM824 results are identified separately.

Known issue: reconnecting the whole Thunderbolt adapter while the FireStudio remains powered can leave the Mac as bus root with local cycle-master disabled and no observed remote timing. The device still appears in Core Audio. This reconnect issue remains unfixed; no additional bus-role policy change is included in this PR.

Changes addressing review

  • Keep discovery topology and labels immutable until quiesced shutdown. Runtime prepare/confirm/clock failures preserve the cache; successful operations update only atomic live rate/ISO values. A short initial-publication lock prevents concurrent or late discovery from rewriting published arrays. ResetRuntimeCaps() is called only from Shutdown().
  • Restore ordinary DICE publication fallback after absent/failed runtime discovery. Strict geometry-dependent first publication is scoped to the exact Project identity; existing nubs are not removed by this path.
  • Use the existing raw sign-extended 24-in-32 playback codec for the Project, based on the maintainer's vendor-KEXT findings. Restore ordinary zero-filled unwritten payload behavior and remove the extra 0x40000000 PCM-label traversal. Capture decoding, MIDI defaults and CIP/NO-DATA framing remain unchanged.
  • Retain only README.md and dice-report.txt under captures/presonus-firestudio-project/. The README links historical evidence at immutable commit 458673e2 and now records the later bounded hardware results and reconnect limitation. New raw logs remain outside the repository.
  • Correct both stale profile comments that said raw-PCM hardware validation was pending.

The exact profile/rate support and the existing interrupt-acknowledgment, watchdog/DMA shutdown and failed-cleanup reservation fixes remain. Unsupported rate/geometry requests are rejected, and failed clock requests do not become the next StartIO selection. No mixer/router UI, flash initialization, local installation build-number increment or new reconnect-policy implementation is included. Reference code was not copied.

Validation

The tested runtime code passed 247 host tests across 15 executables, all 38 tests in DICETcatProtocolTests under ThreadSanitizer, and a Release build. Signatures, entitlements and arm64e were verified. The latest follow-up changes documentation/comments only; no runtime code or installed driver was changed for this update.

The running build 9 driver was verified against SHA-256:
cccfb901044ab6fc31e951fc79914c6e9111a78abeb6223f2e1ab9fb2fa83443.

Hardware: one FireStudio Project on an M1 Pro MacBookPro18,3, macOS 26.6.2, via the Apple Thunderbolt adapter chain.

  • Initial silent/rate tests: five three-second runs at 48, 44.1, 44.1, 48 and 44.1 kHz passed client lifecycle and independent driver-log checks, including continuous output timestamps, interrupt progress, zero TX underruns and clean resource release.
  • S/PDIF tones: one -36 dBFS, 24-second 440/880 Hz sequence at 44.1 kHz completed all 1,058,400 frames over 2,069 continuous callbacks. Logs recorded 193,158 assembled packets, 31,516 IT interrupts, zero TX underruns and successful shutdown. The Roland was reported locked; asked about both pitches, quiet gaps and clicks/buzz/distortion/dropouts, the contributor answered “Both clear; gaps quiet.”
  • Power-cycle recovery checks: two additional three-second silent 48 kHz runs passed with the FireStudio as root/IRM and remote timing observed. They produced 283/284 callbacks and 4,066/4,081 IT interrupts, with continuous timestamps, zero underruns and clean stops. After recovery, user-selected 44.1 kHz held and the driver committed the rate successfully.
  • GarageBand playback and shutdown at 44.1 kHz: the contributor reported “played over 2 mins no issues.” The complete driver session lasted 411.647 seconds (about 6 minutes 52 seconds, including any silence while GarageBand held the stream). Final counters showed 3,292,813 assembled packets, 548,004 IT interrupts and zero TX underruns. Stop completed in 44 ms, reached Idle and released TX resources. No watchdog/fatal, async timeout or payload anomaly appeared in the captured session.

The saved routing/mixer was unchanged. The retained full device report remains the build 9 export from 09:13:36 UTC; newer structured readbacks and detailed logs are kept locally. Historical build 5/8 headphone/input1-2/GarageBand-recording results used labelled AM824 and do not establish equivalent recording/analogue validation on build 9.

Retained report, provenance, results and limits.

Reconnect findings and remaining limits

An earlier audio start after full adapter reconnect had no transmit interrupts, then a watchdog stop, an initial hardware-timestamp timeout and failed device cleanup. Later 44.1 kHz requests correctly encountered the reserved failed-cleanup state and returned busy.

A controlled repeat recreated the Mac-root/no-cycle-master state while Core Audio discovery and the device's 48 kHz audio clock still worked. That repeat stopped at preflight without starting another audio stream. Power-cycling only the FireStudio with the adapter retained produced a device-origin reset, restored FireStudio-root timing, and allowed the successful silent/GarageBand checks above. This strongly implicates generic root/cycle-timing setup; the exact fix is not implemented or proven.

The power cycle created a new TCAT protocol/cache and included a transient boot/discovery transaction failure and device-removal IPC teardown error before successful rediscovery. It does not establish recovery with the same protocol/cache instance or an error-free power transition. A fresh initial geometry failure can still defer this specific Project until a later update/reconnect; ordinary DICE models retain fallback.

The shared DICE changes still need maintainer review. Cross-device hardware validation, independent digital stereo routing, digital input capture, bit-perfect transfer, calibrated silence/quality, all physical jacks, higher rates, sleep/wake, latency and long-duration endurance remain unvalidated. The vendor-binary finding is attributed to the owner's review; no vendor binary/version or raw wire trace was independently examined here. Full asynchronous stop cancellation is not redesigned, and final discovery-cache reset retains the existing quiesced-shutdown requirement.

@mrmidi

mrmidi commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Hi. Thanks a lot for contributing! :)

There are a few notes after reviewing the changes locally:

  1. runtimeCapsValid_ and ResetRuntimeCaps():
    In main, runtimeCapsValid_ was designed as a write-once cache during initial discovery, cleared only on Shutdown(). Introducing runtime calls to ResetRuntimeCaps() on PrepareDuplex, ConfirmDuplexStart, and ApplyClockConfig turns this into a live race condition (torn reads of non-atomic stream/label arrays) and wipes static topology on transient transport glitches. This also prevents recovery after bus reset. Please drop the runtime ResetRuntimeCaps() calls and keep the discovery cache intact.
  2. Global fail-closed publication in DiceAudioBackend:
    The changes in DiceAudioBackend::EnsureNubForGuid cause publication to fail closed if runtime geometry read fails. Because there is no retry loop, a transient read timeout right after bus reset causes the device to disappear indefinitely. This is a potential regression for all DICE devices. Please revert this to the previous behavior (or keep strict checks scoped to the specific profile).
  3. AMDTP PCM silence / 0x40 labels:
    I've checked the original vendor driver binary KEXT: PreSonus actually transmits raw sign-extended 24-in-32 PCM with zero-based silence (0x00000000), and zeroes unwritten payloads directly with memset(..., 0, ...). Furthermore, clearPayloadBeforeExposure already zeroes unwritten buffers in ASFW. The extra hot-path traversal to write 0x40000000 shouldn't be needed and adds overhead. Worth testing with standard zeroed silence on the hardware.
  4. Captures cleanup:
    13 files under captures/presonus-firestudio-project/ is a bit noisy for the repository tree. We want to keep README.md and the dice-report.txt (which are very useful provenance), but the raw meter dumps and small markdown summaries are better kept in PR comments or external gist/attachments.

If you could simplify the shared DICE protocol changes and validate on hardware, the profile itself looks great!

Preserve captured wire geometry while allowing 44.1/48 kHz and keeping failed
clock requests from becoming the next start rate. Acknowledge fresh isochronous
events once, retain faulted DMA resources until quiesced, and distinguish running
streams from failed cleanup reservations. Add targeted regressions for these
paths and all ten AM824 PCM lanes.
Record build 8 clock lock, six silent lifecycle trials and two audible S/PDIF
tone runs into the Roland VM-3100. Preserve earlier evidence and make the
remaining stereo-routing, quality and endurance limits explicit.
@seeward seeward changed the title Add experimental PreSonus FireStudio Project support at 48 kHz Add experimental PreSonus FireStudio Project support at 44.1/48 kHz Sep 8, 2026
@seeward

seeward commented Sep 8, 2026

Copy link
Copy Markdown
Author

/i just saw your notes and will make the further updates today.

Preserve the discovery cache across runtime failures and validate operational
results separately. Publish non-atomic topology and label arrays once; use
atomic live clock/ISO fields. Restore ordinary DICE publication fallback and
retain strict geometry-dependent publication only for FireStudio Project.
Follow the maintainer-reported vendor KEXT playback format using the existing
sign-extended 24-in-32 codec. Remove the added PCM-label initialization pass
and retain capture, MIDI and CIP framing policies. Hardware validation of this
raw-format candidate remains pending.
Retain only README.md and the latest unchanged dice-report.txt. Link prior
raw dumps, screenshots and summaries through their immutable commit, and
separate historical labelled-AM824 hardware results from the raw candidate.
@mrmidi

mrmidi commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Thanks for validating raw 24 logic.

Please split your PRs: new changes is not related to PreSonus and changing behavior to whole firewire stack and blast radius is high enough to break other devices. For this one please focus on FireStudio profile/geometry.

Also I invite you to join Discord it's useful to discuss breaking (probably) changes there before committing them to main. Also there is two branches that may be already fixing the problems you're solving with new changes:

they are experimental :)

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.

2 participants