Skip to content

v0.15.0 — migrate AudioScapeMusicPlayer to new Roblox Audio API - #13

Merged
this-fifo merged 2 commits into
masterfrom
feat/audioplayer-migration
May 22, 2026
Merged

v0.15.0 — migrate AudioScapeMusicPlayer to new Roblox Audio API#13
this-fifo merged 2 commits into
masterfrom
feat/audioplayer-migration

Conversation

@svarah

@svarah svarah commented May 22, 2026

Copy link
Copy Markdown
Contributor

cc @fifo

Summary

  • Migrates AudioScapeMusicPlayer off legacy Sound to AudioPlayer + AudioDeviceOutput + Wire. Public method surface unchanged.
  • Adds player:getAudioPlayer() accessor (unblocks the MusicMCP crossfade skill that drives Volume via TweenService).
  • Adds PlayerOptions.output so spatial setups can feed an AudioEmitter instead of the auto-created AudioDeviceOutput.
  • Bumps to v0.15.0 (wally.toml, README install snippet, CHANGELOG).

Driven by the handoff at MusicMCP/docs/handoff-sdk-audioplayer-migration-2026-05-21.md. Open design questions in section 3 of that doc resolved via the recommended defaults (auto-output with override, add accessor, AudioPlayer-only no fallback, minor version bump).

What changed

  • src/AudioScapeMusicPlayer.luau — new audio backbone, getAudioPlayer(), PlayerOptions.output, BindToClose wrapped in pcall so module-load outside a server context (Studio command bar, plugins) does not error.
  • tests/musicPlayer.spec.luau — new spec, 7 lifecycle scenarios with a fake analytics client.
  • tests/_harness/mockGame.luau + tests/_harness/loadSdk.luau — Instance shim now provides Play/Stop/Destroy methods, an Ended signal with a test _fire hook, and records created instances on Instance.__created.
  • tests/openCloud/smokeScript.luaucreatePlayer step extended from a 4-line existence check to a full real-engine lifecycle check (Asset, IsPlaying, TimePosition advance, Wire wiring, setVolume propagation, stop/destroy teardown).

Test plan

  • Lune unit suite — 17/17 pass
  • stylua, selene, luau-lsp analyze — clean
  • Roblox Studio MCP smoke (real engine, state inspection): Asset = "rbxassetid://..." accepted, IsPlaying = true, TimePosition advances, Wire routes AudioPlayer → AudioDeviceOutput, setVolume propagates to live AudioPlayer, stop() + destroy() tear down cleanly
  • Live ear-test in Studio: two-track queue, audio audible, second track starts automatically when first ends (confirms AudioPlayer.Ended semantics match Sound.Ended for our purposes)
  • openCloud smoke job — pending CI run on this PR

Replaces legacy `Sound` playback with `AudioPlayer` + `AudioDeviceOutput`
+ `Wire`. Public method surface unchanged (queue/setQueue/clearQueue/play/
stop/skip/setVolume/setPlayerId/playTrack/destroy + OnTrackChanged /
OnQueueFinished callbacks + NowPlaying/IsPlaying/Queue fields).

New:
- player:getAudioPlayer() returns the live AudioPlayer Instance (or nil)
  for TweenService-driven volume animation and custom effect-chain wiring.
- PlayerOptions.output accepts a caller-provided AudioDeviceOutput or
  AudioEmitter for spatial / custom-routing setups; auto-created
  AudioDeviceOutput remains the default.

Tests:
- tests/musicPlayer.spec.luau — 7 lifecycle scenarios with a fake
  analytics client and extended mock Instance (Play/Stop/Destroy +
  Ended signal + created-instance recorder).
- tests/openCloud/smokeScript.luau — createPlayer step extended from a
  4-line existence check to a full real-engine lifecycle check
  (Asset, IsPlaying, TimePosition advance, Wire wiring, setVolume
  propagation, stop/destroy teardown).

Confirmed working: Lune 17/17, stylua, selene, luau-lsp analyze all
clean; Roblox Studio MCP smoke confirms TimePosition advances and
Wire routes AudioPlayer -> AudioDeviceOutput; live ear-test confirms
audible playback and natural Ended -> next-track advancement.

Sean (OffGridDude)
Was: assert ap.Volume == 0.4 / 0.7 after setting volume = 0.4 then
setVolume(0.7). Those values aren't exactly representable in float32,
so AudioPlayer.Volume (engine-side float32) round-trips back to the
Lua double as 0.4000000059604645 / 0.699999988079071 and the equality
asserts fail.

Picked 0.5 and 0.25 — both exactly representable in float32 — so the
round-trip is exact and the asserts work without a tolerance check.

Sean (OffGridDude)
@svarah
svarah temporarily deployed to openCloud-smoke May 22, 2026 16:20 — with GitHub Actions Inactive
@this-fifo
this-fifo merged commit acb7511 into master May 22, 2026
2 checks passed
@this-fifo
this-fifo deleted the feat/audioplayer-migration branch May 22, 2026 16:25
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