DEV Community

mikkergimenez
mikkergimenez

Posted on

mobx and application properties

I'm building a web application to make music, a 'Modular Audio Workstation' (More Info: https://maw.earthytonez.com/) and there are two types of data being stored in this application.

The first is "application data". This is the synthesizers and sequencers users can create to make music. The second are all of the parameters you can tweak for each of the modules, or components. The synthesizers and sequencers are built using a TOML formatted config, and loaded from static code in the application, so when loading a users workspace the only thing we need to know about them is the name or slug of the synthesizer and sequencer and what track they're on. I store this data in a Track Store, and I store it as a nested JSON. The model I use for this is based on this gist. I just autosave the contexts of the stores. Nested JSON makes sense here, since it's a relatively simple confiugration.

[{"id":0,"slug":"track-0","sequencer":{"name":"Four on the Floor","slug":"four_on_the_floor","type":"step"},"synthesizer":{"name":"Kick","slug":"kick"}},{"id":1,"slug":"track-1","sequencer":{"name":"Simple Arpeggiator","slug":"simple_arpeggiator","type":"arpeggiator"},"synthesizer":{"name":"Bell","slug":"bell"}},
Enter fullscreen mode Exit fullscreen mode

Inside the stores are dozens, which will likely become hundreds of deeply nested classes to manage the code for increasingly complex sequencers and synthesizers that a user can use in their music. Each of these classes likely has parameters that can be configured by the user.

At first, I was storing these parameters as properties on the class itself. But this became very difficult to Marshall the JSON when saving to local storage. For one, if I changed the schema, it would break the song, in ways that may require guards against undefined values everywhere to figure out. Additionally, I wanted each property to have some shared characteristics. For instance, some properties pend their changes until the end of a measure or segment of the music. Other properties I want to be able to add an LFO or other modulation to, in fact almost every parameter I wanted to be able to do this with.

Creating a Parameter class to subclass was an easy way to make every parameter modulatable, but I still needed a way to easily save the parameter. I ended up storing them with hierarchical names in a flat key-value store. (Just a javascript map as a top level Mobx store). The data is still hierarchical. We need to know which track or synth the parameter applies to. So now each parameter is stored in that flat Map with a key like:

track.1.synthesizer.cutoff_frequency
or
global.bpm

I could have saved each parameter as a different key in local storage, but storing them in one location will make it easier to keep track of to allow for offline saving down the road.

Top comments (0)