🔊 Overhauling tat for v0.5

The tabletop audio tool gets a new coat of paint! And a new engine. And some other new stuff. It's out now!

🔊 Overhauling tat for v0.5
💡
This has been updated since it was first posted -- I've released a fix/feature update, v0.5.5, and included the changes in the log below.

I've been hard at work on this update to tat, the audio-mixing-for-RPGs software I made as a bonus for my Kickstarters for Warped Beyond Recognition & The Blades of Gixa, and I figured it was time I revisited it, fixed some issues, and added some features. I wound up doing quite a bit more than that, though.

💡
Paradiso Expert & Companion members also get access to tat while it's in development! Just go to your account page to claim it :)

First, here's a video showcasing (a lot of) tat 0.5's new features! (I did miss a few). Then I'll get into some of the behind-the-scenes of building it.

About Building tat

This wound up being a pretty big challenge! I'm not a professional programmer but I've certainly tinkered around with code over the years, and I've found a certain pattern emerge when working on projects: usually there's two general ways to build something:

  • Use pre-built tools to get it up and running quickly and relatively painlessly.
  • Code everything yourself to gain and maintain deep understanding and control of what you're building.

I've worked with professional programmers who are advocates of each of these methods. The "pre-built tools" folks are generally goal-oriented: they want to get the thing they're building operational as soon as possible, even if that means it might be a bit buggy or ugly. As they encounter problems, they'll look for other people who've solved those problems—or similar problems—in the past, and graft their solutions into the project instead of coding something bespoke from scratch.

Meanwhile, the "code everything yourself" folks are much more process-oriented: they want to do things the right way, which usually means painstakingly constructing everything themselves and anticipating every potential issue before it arises. They build "architectures" and "frameworks" before writing the code that actually does whatever the project is supposed to do.

The former tend to be good at prototyping and getting things running quickly and cheaply, while the latter are better at constructing airtight, reliable systems. I've seen these types butt heads a lot, but in my experience, they each have their place.

I've found that when first taking on a programming project, it can be very helpful to be a "pre-built tools" person: I know what I want to build, but I often don't really have the details pinned down, or a clear idea of how it should be built, and instead of getting bogged down asking how to build something, it's usually better to just start building: getting things up and running quickly with off-the-shelf solutions is a great way to build excitement and momentum behind a project: you quickly get to that magic moment where something is happening on-screen, and that gives you the encouragement to keep going.

An earlier version of TAT.

Early tat

So it was with tat in the very early days. I knew generally what I wanted to build: a tool for people running tabletop RPGs where they could import images and sounds, and lay them out on a "canvas," so that sounds overlaid images as shapes. There would also be a "listener": a little doodad you could drag around on the canvas, and as it touched the sound shapes, the corresponding sounds would become audible. You could then use this tool to import maps from RPG modules and soundtrack audio and create projects where you lay soundtracks on various parts of the maps. When running an RPG session, you could drag the listener around the maps to represent the position of the players' party, and they would hear the sounds for that area. A way to set up and run immersive ambient sound for an RPG night!

I had some experience with web tech from making websites (like the design of paradiso.zone) so I looked to ways of building an application using tech I already understood. I found tools like Electron and Tauri that can produce apps that run natively on people's computers, but basically function as web browser windows, so the actual interface of the app is built like a website. I wound up going with Tauri because I liked the sound of a more lightweight app, and I used its Vite and SvelteKit integrations to get an interface up and running quickly.

Leaflet.

I had no idea how to build the canvas that you drop stuff into, but I found a tool that could do something analogous: Leaflet, an open-source interactive map tool. The map is kinda like a big canvas surface you can pan around on, zoom in and out, etc., and a lot of people had made extensions to Leaflet for drawing shapes on top of maps that I could repurpose as sound shapes, collision detection tools, etc.

There were a lot of hiccups along the way: Leaflet's default coordinate system didn't work for my purposes, and a lot of the extensions didn't quite work the way I needed them to, but ultimately it was worth it because I didn't have to make the core engine that would drive the visual side of the app, and with Leaflet, I got something up and running quickly.

I also used an audio tool, Howler, to manage the actual sound controls, as I'd never worked with web audio before. I pulled various icon sets from Iconify for the buttons, and got the basic systems up and running quite quickly. From there, I just had to build the interface (the part I actually knew how to do) and interact with the user's filesystem (which Tauri provided nice tools for).

All of this went into tat's initial release to Kickstarter backers, and has formed the backbone of tat in its subsequent updates—until this one.

Rebuilding tat

When you're building stuff with other people's pre-built tools, you eventually hit a point where those tools start getting in the way. Leaflet and the rest worked wonders for making a usable, workable app quickly, but I had to tack on all kinds of weird modifications to get it and the extensions I stuck on top of it to work the way I wanted. And there were still issues I couldn't get around: limitations in how the shapes and handles to modify them were drawn, limitations to the ways I could use and manipulate audio, limitations to how I could draw things on the map. And I started running into issues with many of the extensions I was using behaving in ways I didn't really understand.

I put tat aside for a while and focused on my many other projects.

But while I was laid up with COVID recently, I started looking at tat again and thinking about the things left undone. I started investigating changing my methods: the "pre-built tools" approach had served me well thus far, but I had to face the fact that under the hood, my app had become a bunch of different systems, built by other people for other purposes, that I'd creatively duct-taped together. This was not a good foundation for future development.

So I started ripping parts out, and replacing them with my own. Using the "pre-built tools" approach had gotten me to a pretty good understanding of what tat is and how it should work, and so I could start picking off pieces to replace with a more "code everything yourself" approach, to make things work just how I want them to, and in a way I actually understand.

A lot of the changes in tat 0.5.* are architectural, under-the-hood changes whose effects might be a bit subtle, but which enabled a lot of the flashier new features! These changes also should form a much better foundation to build upon and make future feature development a lot nicer to work on.

New load-bearing code

This process also involved deciding on what I would keep: I'm not interested in venturing too far outside tat's core features and into the underlying frameworks, so tat still runs on Tauri, Vite, and SvelteKit, but they all got major version upgrades that necessitated some rewrites.

The big things I jettisoned were Howler and Leaflet, and all the additional extensions I had plugged into them.

  • To replace Leaflet & co., I found a number of tutorials about programming infinite canvases using JavaScript and HTML <canvas> elements, and started building my own. I also found lots of information about drawing 2D shapes and how to do collision detection to determine if the listener was inside a given shape, and started building those systems as well.
  • To replace Howler, I learned about the Web Audio API standard and used it to manage and route audio. This actually took a few tries, as using <audio> elements, the recommended—and easier—way of handling audio, does not allow for seamless looping, which is essential for a project like tat.

These changes enabled a lot of things that I'd wanted to do earlier but had been struggling to: better audio controls, and much more control over the canvas visuals, including theming! And it will continue to make future development easier.

tat 0.5.2 in the Dark theme.

Finally, the tat 0.5.x changelog

Update: Thanks to the amazing QA help of user ReEvolve on itch, I've just released a new update, v0.5.5, with the following additional changes:

  • Audio playback state and position now save & load properly.
  • Fixed Area sound volume not working properly when first created.
  • Added "Jump listener to here" option on context menus. You can use this to move the listener to a specific location instantly, without having to worry about dragging it thru unwanted intervening sounds.

Here are the big changes in v0.5.4:

  • Rewrite of the audio system.
    • Removed all audio libraries/dependencies (Howler and others).
    • Re-implemented audio system with native WebAudio API, allowing for much more control over audio + seamless looping.
  • Rewrite of the canvas system.
    • Removed all canvas libraries/dependencies (Leaflet and add-ons).
    • Re-implemented an infinite canvas with a native <canvas> element and re-implemented shape drawing, shape controls, & collision detection, allowing for much more control over canvas manipulation and visuals.
  • Upgraded to Svelte 5 and Sveltekit 2.
  • Sound triggers. Each sound now has a trigger type, which determines when the sound plays, pauses, and/or restarts.
    • Manual: Play/pause by clicking a button. (default).
    • Play On Enter: Plays when the listener touches the emitter. Reverts to manual when triggered. Only available if the listener is not currently touching the trigger. Not available for Global sounds.
    • Restart On Enter: Plays from beginning when the listener touches the emitter. Reverts to manual when triggered. Only available if the listener is not currently touching the trigger. Not available for Global sounds.
    • Play Inside: Plays only while the listener is touching the emitter. Not available for Global sounds.
    • Restart Inside: Plays from beginning when the listener touches the emitter, and plays only while the listener is touching the emitter. Not available for Global sounds.
    • Timer: Set a timer, from 00:00:01 – 99:59:59. Plays when the timer reaches 00:00:00, then the timer resets.
  • Looping Toggle: Toggle whether the sound loops infinitely or plays once. Note: In Timer trigger mode, this instead loops the timer, not the audio directly.
  • Better image scaling, now with the ability to flip images on X and Y axes and use proportional scaling on flipped images.
  • Adaptive canvas grid changes based on zoom level, with coordinate numbers on grid lines.
  • Improved canvas object ordering. Clicking a canvas object still selects the object, but no longer automatically raises it to the top of the order. You can instead right-click the image and select "bring to front" or "send to back", or drag and drop the object in its list on the media panel to reorder.
  • Themes. Switch between themes in the Settings menu.
    • Currently there are 3 built-in themes (more to come):
      • Dark (default)
      • Light
      • Warped Beyond Recognition
  • Context menus. Right-click on the canvas to get a context menu:
    • Canvas menu: Shows the coordinates at the clicked point.
    • Listener menu: Click the name to center the view on the listener. Shows the coordinates of the listener, and if they are not at the origin, you can re-center the listener and the view on the origin.
    • Object menu: Click the object name to select/deselect the object. Click "Bring to front" to raise the object to the top of the order, or "Send to back" to lower it to the bottom.
  • Localization support. There are no languages besides English yet, but the app can now support them. Check out the "Translation" section below if you'd be interested in doing a translation!
  • Projects now save and load listener and view positions.
  • Global image opacity control to match the global audio volume control.
  • Improved Settings menu layout & design.
  • About menu fixes. Updated some links, and the app version is now fetched properly.
  • Signed macOS builds: Your computer will no longer claim they're broken!
  • Native OS menus (File, etc.) only show up on macOS, so they don't mess up the app window.
  • UI Scrolling for volume, etc. should now be more consistent across platforms (you can still adjust sensitivity in the Settings menu).
  • Much more help text across the app.
  • Removed overscroll bounce affecting entire app.
  • Added capital letters.
  • Now only using Tabler icons for a more consistent visual look. (A few are modified slightly.)
  • Basic debug display: Show/hide with backtick `. Shows some debug information and draws some extra widgets.

How do I get tat 0.5?

tat is not publicly available yet (that'll be 1.0), but if you backed at a physical tier on either of my Kickstarters, you have an Itch tat key already—check your email!

Otherwise, you can get tat and support its development by becoming a Paradiso Expert or Companion member!

And if you already are a member at one of those tiers, thank you! Check your account page for the link.

What's next?

I'll be focusing my efforts on The Blades of Gixa for the foreseeable future—I've been working on that during all this too, but tat has been at the forefront for the last month.

I will however be looking at any bug reports on the tat Itch page and taking some time to try and address them, and if anyone is interested in providing some translations (see below), I can add those too. I may also whip up a few themes.

If anyone is interested in helping translate tat into another language, I'd greatly appreciate your help. Email me at paradiso@paradiso.zone and let's chat!