preset_file.h
Presets as FILES, in the format the rest of the world uses.
#include <sonore/preset_file.h>- 1type
- 7other declarations
- Guides: Getting started, Parameters and state, Presets
On this page
Design notes
A plugin's factory presets live inside it, and the hosting API can already list and load them. That is not where most presets are. People have folders of .vstpreset files: bought, downloaded, swapped, saved from another host years ago. A host that cannot open one is a host that starts empty however much the user already owns.
The container is documented and small. A header naming the plugin, one or more chunks, and a list at the end saying where each chunk is:
"VST3" | version | class id, 32 hex chars | int64 offset of the list
...chunk data...
"List" | int32 count | entries of { id[4], int64 offset, int64 size }
Everything is little-endian, which is worth stating because the format is Steinberg's and AIFF-style big-endian would be the other reasonable guess.
The chunk that matters is "Comp", the component state: the same bytes getState() hands over. "Cont" is the controller's own copy and "Info" is an XML blurb; both are optional, and this writes Comp only. A preset that carries a controller chunk is read and its Comp used, because the component state is what actually decides the sound.
Types 1
What came out of a .vstpreset: which plugin it is for, and its state.
Functions 6
- fn
inline void putU32(std::vector<uint8_t>& out, uint32_t v)Appendpresetfile::putU32 · preset_file.h:56vas four little-endian bytes. - fn
inline void putU64(std::vector<uint8_t>& out, uint64_t v)Appendpresetfile::putU64 · preset_file.h:64vas eight little-endian bytes. - fn
inline uint32_t getU32(const uint8_t* p)Four little-endian bytes atpresetfile::getU32 · preset_file.h:69p. Not bounds-checked: the caller has. - fn
inline uint64_t getU64(const uint8_t* p)Eight little-endian bytes atpresetfile::getU64 · preset_file.h:75p. Not bounds-checked: the caller has. - fn
inline bool writeVstPreset(const char* path, const std::string& classId, const std::vector<uint8_t>& componentState)Write a .vstpreset holding one plugin's component state.preset_file.h:91More
classIdmust be the 32 hex characters that identify the plugin, because that is the only thing in the file that says what it is for: a host opening it has no other way to know, and applying a preset for the wrong plugin is how a delay ends up with a filter's numbers in it. - fn
inline bool readVstPreset(const char* path, Vst3PresetFile* out, uint64_t maxBytes = kMaxVstPresetBytes)Read a .vstpreset.preset_file.h:141More
Refuses anything it cannot make sense of rather than returning a partial answer: a chunk whose offset points past the end of the file, a list whose count does not fit, a header that is not a preset at all. A preset half applied is worse than one not applied, because the user cannot tell which half.
Constants 1
- const
constexpr uint64_t kMaxVstPresetBytes = 256ull * 1024ull * 1024ullThe largest .vstpreset readVstPreset reads: the same 256 MB a preset of the SDK's own format may be.preset_file.h:130