fix(ios): stop rendering audio a preset with its own sound never plays - #290
Merged
Merged
Conversation
`parse()` rendered a synthesized waveform through AudioSimulator for every pattern, but `play()` only uses that buffer when the preset has no sound of its own. For a preset carrying real audio the render was pure waste, and it ran on the main thread: 1.81 s for a five-second preset in a debug build, which froze the UI on first play and on every seek.
Member
Author
|
Closing alongside #289 while the audio-sync investigation restarts from scratch. The measurement here stands on its own (1.81 s of discarded main-thread render for a preset whose buffer play() never reads), so this will be raised again separately once the primary bug is understood. |
Member
Author
|
Reopening: independent of the replay bug and the evidence stands on its own — 1.81 s of main-thread render, measured, for a buffer that play() never reads when the preset has its own audio. The replay fix is now #291. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
PatternComposer.parse()finished by rendering a synthesized waveform throughAudioSimulator.parsePattern, unconditionally. Butplay()only reaches for that buffer when the preset has no sound of its own:So for any preset carrying real audio — every
.pulsarbundle preset with an attached track — the whole render was discarded, and it ran synchronously on the main thread.Cost
Measured on the PulsarApp fanfare preset (5187 ms, 38 discrete points): 1.81 s for 114,594 frames in a debug build. It is a per-sample loop with ~117 oscillator evaluations per frame.
That is a 1.8 s main-thread freeze on the first play of a bundle preset, and again on every scrubber seek, since seeking re-parses. Visible in the Audio Sync demo as the progress bar jumping from 0 to 2 s: the JS clock is
Date.now()-based so it kept counting while the UI could not repaint.The render is skipped entirely when
AudioSimulator.playSoundis false, which is the default outsideDEBUG— but that default does not save a real app.playSoundis also flipped bySettings.enableSound(...), and PulsarApp callsSettings.enableSound(true)on mount (app/(tabs)/index.tsx), so the render runs in release builds too. A release build compiles the loop optimised and is far quicker than the 1.81 s measured above, but the work is still wasted and still on the main thread.Change
One line: skip the render when an audio event is present.
playAudioOnly()still gets its buffer — it is only reachable fromPlayer(audioOnly:), which parses without sound.Tests
Pulsar-Package: 63 tests / 11 suites pass.Independent of #291, which fixes replay silence in the same demo. The two touch
parse()at opposite ends and merge cleanly in either order.