Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Make APU tick aware ✨ #705

Merged
merged 1 commit into from
Apr 18, 2024
Merged

Conversation

JerwuQu
Copy link
Contributor

@JerwuQu JerwuQu commented Apr 16, 2024

What

It has always been an issue that if you try to continously play tone each frame, you will get gaps due to frame timing issues. This has made doing live-playback or creating very fancy sounds difficult.
The previous workaround has been to extend each tone so that the next one will override it, but this has several drawbacks when working with pitch-bends.

What is done here is make the APU aware of WASM-4 ticks. This enables us to keep playing the active tone past its expiration as long as the next tick hasn't rolled in yet, thus avoiding gaps in playback.

Demo

Here is a video demonstration of the fix: demo

This also shows that it only affects continously calling tone with sustain and doesn't affect intentional skipping or envelopes (which is correct.)
Has been tested on both web and native, on Windows and Linux.

Example

Here's the cart I used to test this and the Zig code for it: cart.wasm

const w4 = @import("wasm4.zig");

export fn start() void {}

var ticks: usize = 0;
export fn update() void {
    w4.DRAW_COLORS.* = 0x14;
    w4.text("\x80:continous", 5, 5);
    w4.text("\x81:skip 1", 5, 15);
    w4.text("\x84:skip 2", 5, 25);
    w4.text("\x86:continous release", 5, 35);
    w4.text("\x85:skip 1 release", 5, 45);

    w4.DRAW_COLORS.* = 0x13;
    if (w4.GAMEPAD1.* & w4.BUTTON_1 > 0) {
        w4.text("continous", 5, 80);
        w4.tone(500, 1, 50, 0);
    } else if (w4.GAMEPAD1.* & w4.BUTTON_2 > 0) {
        if ((ticks % 2) == 0) {
            w4.text("skip 1", 5, 80);
            w4.tone(500, 1, 50, 0);
        }
    } else if (w4.GAMEPAD1.* & w4.BUTTON_LEFT > 0) {
        if ((ticks % 3) == 0) {
            w4.text("skip 2", 5, 80);
            w4.tone(500, 1, 50, 0);
        }
    } else if (w4.GAMEPAD1.* & w4.BUTTON_UP > 0) {
        w4.text("continous release", 5, 80);
        w4.tone(500, 1 << 8, 50, 0);
    } else if (w4.GAMEPAD1.* & w4.BUTTON_RIGHT > 0) {
        if ((ticks % 2) == 0) {
            w4.text("skip 1 release", 5, 80);
            w4.tone(500, 1 << 8, 50, 0);
        }
    }
    ticks += 1;
}

I also tested some code doing continous frequency sweeps and the difference is night and day, even when doing workarounds with the old version.

@aduros
Copy link
Owner

aduros commented Apr 18, 2024

Looks great, thanks!

@aduros aduros merged commit f86cdac into aduros:main Apr 18, 2024
5 checks passed
@JerwuQu JerwuQu deleted the jwq_tick-aware-apu branch April 18, 2024 17:07
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