Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 0xdevalias/135a18e979ac8e302ebbc700a50a8d74 to your computer and use it in GitHub Desktop.
Save 0xdevalias/135a18e979ac8e302ebbc700a50a8d74 to your computer and use it in GitHub Desktop.
Reverse Engineering Serum Preset Format - Supplementary Notes

Reverse Engineering Serum Preset Format - Supplementary Notes

Table of Contents

The following files are also included in this gist:

And you can see my overview/thoughts/notes about some of them in this comment on the other gist:

Overview

This is just a bit of a scratch pad for extra files/notes that are too big to include in my main notes.. but for most things, what you probably actually want to be looking at is this gist:

Specifically sections like:

As well as the comments on that gist, as there are also some useful/insightful additions/discussion there too:

Serum 1 Preset File Format (.fxp)

The notes/links in the Overview section above are a good starting point for my older notes/etc; and then the additional files 'included in this gist' section of the above Table of Contents also generally relate to my work on exploring the Serum v1 .fxp preset file format.

I also gave a bit of a high level overview on my Twitter / BlueSky thread included below ("2025-04-21 – Revisiting and Expanding on Reverse Engineering the Serum VST Preset Format"), and also gave a bit of a high level overview of my notes/tools/etc in this issue:

As part of uploading my old notes/tools, I made a bit of an overview/context dump from what I could remember of it all, which I am also including here for reference:

Also created a new gist for supplementary notes/files in case I do find anything useful in those notes that I can put up that's too big to make sense to include directly on this gist

Just had a quick skim through the files I had in my old notes and added some to that gist. You can see an overview of them in the Table of Contents:

But as a quick reference, here are the files I just added:

The following files are also included in this gist:

I don't remember exactly which version of the binary / which section/function within it serum-params-in-code.txt were extracted from.

vst_fxp.ksy was my initial attempt at creating a Katai Struct definition for FXP files (and eventually for the Serum preset format itself), but from memory I was finding that it was a bit too painful to try and do exploratory parsing within the limitations of that format (or at least, in my knowledge of how to use it).

So then I think I moved mostly iterating on vst_fxp_extractor.py as a way to explore and map out the preset format more programmatically.

I haven't deeply reviewed the code there recently, but from a quick skim + what I remember, in data_segments you can see where I identified a large section of the parameters that corresponded with the params in SYParameters.txt. I believe the ..snip.. comment was just me being lazy in not wanting to write out all the intermediary values/offsets manually, as I think my plan was to do that in a more programmatic/loop sort of way. The values in serum-params-SYParameters-1-demo.txt only go up to 288 (LFO8 Delay), whereas serum-params-SYParameters-1.334.txt goes up to 298 (FX Hyper Level); so that's probably why I included the second ..snip.. comment in data_segments to signify the end of where that data mapping seemed to get to.

Then the next part of data_segments seems to be parameters/offsets I identified more manually via diffing the values. I think for the diffs, I probably wasn't using Serum's built in 'save preset' functionality; I think I was more likely to have been using Spotify Pedalboard to dump the plugin state/similar, and then diffing based on that. So there is probably some crossover with the code in my poc-audio-pedalboard repo here:

Then from memory, I think I was noticing a seemingly large section of data in the binary that I was trying to figure out what it was for, and I believe my running theory was that it might have been an area reserved for the wavetable/similar; since I think I was noticing changes within that when I was diffing. I can't remember what offset that was unfortunately. But from memory, the changes I was making within the wavetable editor never ended up creating as much data change in the diff as I was expecting. I think one of the theories I wanted to test (but never got around to), was going to be adding/creating a new wavetable from an actual audio file, rather than editing the wavetable within Serum's editor; with the idea being that maybe the editor wavetables weren't storing the full data, if they could be represented by formulae/etc (which might have explained the smaller amount of change I was seeing in the diffs), whereas by creating a new wavetable from audio, I would expect it to fill up the full space available, and therefore show a bigger diff change.

In my test patches/etc folder I can see HackyCrazy.wav and HackyCrazy-notes.txt, which skimming through them, sounds like it relates to my attempts to figure out where the wavetables were stored within the preset data. These are the notes I had there:

The HackyCrazy.wav wavetable seems to have 136bytes of header

Then the first 'slice' of the wavetable appears to be 16384/4 = 4096 little endian floats (4-bytes each)

⇒ python -c "import struct; print(struct.unpack('<f', bytes.fromhex('0000 80bf')))"
(-1.0,)
⇒ python -c "import struct; print(struct.unpack('<f', bytes.fromhex('0000 803f')))"
(1.0,)

This was created using an 8x8 grid within serum's wavetable editor; but that can be sliced into smaller chunks.. which I assume would give a maximum slices number that would divide nicely into the above.

It seems that the grid can go up to 64x64: which gives the 4096 we saw above.


From the manual:

Page 11:

The wavetables in Serum consist of up to 256 sub-tables, or single-cycle waves (referred to hereafter as 'frames'). This is probably best thought of as (up to) 256 discrete waveforms, which are joined together end-to- end in the parent file on disk.

Technically speaking, when Serum loads a wavetable it is using 2048 samples for a sub-table of the wavetable set. This means the maximum file size would be 2048(samples) x 256(sub-tables) x 32(bits) (which is exactly 2 megabytes).

Page 13:

NOTE: Serum will always save the changes you have made to a wavetable data inside a preset (your song) unless it is a Factory wavetable. While this uses hard disk space (how much size depends on how many frames you use in the Wavetables, from 8k to 4 Megabytes) the beneft is that you can exchange presets with others, or open your song in the future, without having to worry about table file management. so there is no need to save wavetables unless you want your wavetable to appear in the Wavetable Menu. This increases the size of both the presets and the projects containing them. There is a setting in Serum.cfg that you can change in order to disable saving the tables as parts of the presets, but that is not advisable.

And then, from memory, all of this offset stuff I was figuring out was on the binary data extracted from Spotify Pedalboard; but then my theory (that I might have briefly tested/checked for a few parameters? Can't remember) was that the same 'binary layout' would almost certainly be used in the preset files themselves (even if the base of the offsets might be slightly different/similar)

Hopefully there is some useful stuff in that to help you out; or if not, at least when future me gets back to looking at this more deeply I'll at least have a better starting point to refresh my memory on what I had already done 😅

Serum 2 Preset File Format (.SerumPreset)

There had been some recent (as of 2025-04-22) discussion in the comments on my gist of notes related to figuring out the Serum preset file format; with a lot of the comments relating to the Serum 2 .SerumPreset file format.

When I shared some podcast notes of Steve Duda talking about how he eventually wants to open the preset format, it inspired KennethWussmann to dive deeper into figuring out the v2 preset format; which as of 2025-04-22, they have basically figured out completely, and created a tool that can pack/unpack v2 presets:

That tool doesn't have support for Serum v1 .fxp preset files (though Serum 2 can convert the legacy presets.. so you could technically access them that way); but this discussion did inspire me to find/share my old notes/tools from when I was digging into the .fxp format previously. While it's not fully figured out, it's definitely a good starting point for anyone interested in looking deeper; and I also made this issue on the v2 tool to summarise the relevant context/resources for the .fxp format:

Tweets

2025-04-21 – Revisiting and Expanding on Reverse Engineering the Serum VST Preset Format

Older / Other Tweets / Threads?

While I don't think there are any older tweet threads about this project (at least based on the following search), in case there are any future ones that I forget to document here, this might help you find them:

See Also

'mastervol',
'a_vol',
'a_pan',
'a_octave',
'a_semi',
'a_fine',
'a_unison',
'a_unidet',
'a_uniblend',
'a_warp',
'a_coarsepit',
'a_wtpos',
'a_randphase',
'a_phase',
'b_vol',
'b_pan',
'b_octave',
'b_semi',
'b_fine',
'b_unison',
'b_unidet',
'b_uniblend',
'b_warp',
'b_coarsepit',
'b_wtpos',
'b_randphase',
'b_phase',
'noise_level',
'noise_pitch',
'noise_fine',
'noise_pan',
'noise_randphase',
'noise_phase',
'sub_osc_level',
'sub_osc_pan',
'env1_atk',
'env1_hold',
'env1_dec',
'env1_sus',
'env1_rel',
'osca_fil',
'oscb_fil',
'oscn_fil',
'oscs_fil',
'fil_type',
'fil_cutoff',
'fil_reso',
'fil_driv',
'fil_var',
'fil_mix',
'fil_stereo',
'env2_atk',
'env2_hld',
'env2_dec',
'env2_sus',
'env2_rel',
'env3_atk',
'env3_hld',
'env3_dec',
'env3_sus',
'env3_rel',
'lfo1rate',
'lfo2rate',
'lfo3rate',
'lfo4rate',
'porttime',
'portcurve',
'chaos1_bpm',
'chaos2_bpm',
'chaos1_rate',
'chaos2_rate',
'a_curve1',
'd_curve1',
'r_curve1',
'a_curve2',
'd_curve2',
'r_curve2',
'a_curve3',
'd_curve3',
'r_curve3',
'verb_wet',
'verbsize',
'verbpdly',
'verbloct',
'verbdamp',
'verbhict',
'verbwdth',
'eq_frql',
'eq_frqh',
'eq_q_l',
'eq_q_h',
'eq_voll',
'eq_volh',
'eq_typl',
'eq_typh',
'dist_wet',
'dist_drv',
'dist_l_b_h',
'dist_mode',
'dist_freq',
'dist_bw',
'dist_prepost',
'flg_wet',
'flg_bpm_sync',
'flg_rate',
'flg_dep',
'flg_feed',
'flg_stereo',
'phs_wet',
'phs_bpm_sync',
'phs_rate',
'phs_dpth',
'phs_frq',
'phs_feed',
'phs_stereo',
'cho_wet',
'cho_bpm_sync',
'cho_rate',
'cho_dly',
'cho_dly2',
'cho_dep',
'cho_feed',
'cho_filt',
'dly_wet',
'dly_freq',
'dly_bw',
'dly_bpm_sync',
'dly_link',
'dly_timl',
'dly_timr',
'dly_mode',
'dly_feed',
'dly_off_l',
'dly_off_r',
'cmp_thr',
'cmp_rat',
'cmp_att',
'cmp_rel',
'cmpgain',
'cmpmbnd',
'fx_fil_wet',
'fx_fil_type',
'fx_fil_freq',
'fx_fil_reso',
'fx_fil_drive',
'fx_fil_var',
'hyp_wet',
'hyp_rate',
'hyp_detune',
'hyp_unison',
'hyp_retrig',
'hypdim_size',
'hypdim_mix',
'dist_enable',
'flg_enable',
'phs_enable',
'cho_enable',
'dly_enable',
'comp_enable',
'rev_enable',
'eq_enable',
'fx_fil_enable',
'hyp_enable',
'oscapitchtrack',
'oscbpitchtrack',
'bend_u',
'bend_d',
'warposca',
'warposcb',
'suboscshape',
'suboscoctave',
'a_uni_lr',
'b_uni_lr',
'a_uni_warp',
'b_uni_warp',
'a_uni_wtpos',
'b_uni_wtpos',
'a_uni_stack',
'b_uni_stack',
'mod_1_amt',
'mod_1_out',
'mod_2_amt',
'mod_2_out',
'mod_3_amt',
'mod_3_out',
'mod_4_amt',
'mod_4_out',
'mod_5_amt',
'mod_5_out',
'mod_6_amt',
'mod_6_out',
'mod_7_amt',
'mod_8_out',
'mod_8_amt',
'mod_9_amt',
'mod_9_out',
'mod10_amt',
'mod10_out',
'mod11_amt',
'mod11_out',
'mod12_amt',
'mod12_out',
'mod13_amt',
'mod13_out',
'mod14_amt',
'mod14_out',
'mod15_amt',
'mod15_out',
'mod16_amt',
'mod16_out',
'osc_a_on',
'osc_b_on',
'osc_n_on',
'osc_s_on',
'filter_on',
'mod_wheel',
'macro_1',
'macro_2',
'macro_3',
'macro_4',
'amp',
'lfo1_smooth',
'lfo2_smooth',
'lfo3_smooth',
'lfo4_smooth',
'pitch_bend',
'mod17_amt',
'mod17_out',
'mod18_amt',
'mod18_out',
'mod19_amt',
'mod19_out',
'mod20_amt',
'mod20_out',
'mod21_amt',
'mod21_out',
'mod22_amt',
'mod22_out',
'mod23_amt',
'mod23_out',
'mod24_amt',
'mod24_out',
'mod25_amt',
'mod25_out',
'mod26_amt',
'mod26_out',
'mod27_amt',
'mod27_out',
'mod28_amt',
'mod28_out',
'mod29_amt',
'mod29_out',
'mod30_amt',
'mod30_out',
'mod31_amt',
'mod31_out',
'mod32_amt',
'mod32_out',
'lfo5rate',
'lfo6rate',
'lfo7rate',
'lfo8rate',
'lfo5_smooth',
'lfo6_smooth',
'lfo7_smooth',
'lfo8_smooth',
'fxfil_pan',
'comp_wet',
'gain_l',
'gain_m',
'gain_h',
'lfo1_rise',
'lfo2_rise',
'lfo3_rise',
'lfo4_rise',
'lfo5_rise',
'lfo6_rise',
'lfo7_rise',
'lfo8_rise',
'lfo1_delay',
'lfo2_delay',
'lfo3_delay',
'lfo4_delay',
'lfo5_delay',
'lfo6_delay',
'lfo7_delay',
'lfo8_delay'
There are 287 params exposed through pedalboard for the Serum VST demo, there are 348 default values in the code for serum (maybe not the demo version..?)
🔖0067d5d0 float defaultValues.7561() = 0.699999988
0067d5d4 float data_67d5d4 = 0.75
0067d5d8 float data_67d5d8 = 0.5
0067d5dc float data_67d5dc = 0.5
0067d5e0 float data_67d5e0 = 0.5
0067d5e4 float data_67d5e4 = 0.5
0067d5e8 float data_67d5e8 = 0
0067d5ec float data_67d5ec = 0.5
0067d5f0 float data_67d5f0 = 0.75
0067d5f4 float data_67d5f4 = 0
0067d5f8 float data_67d5f8 = 0.5
0067d5fc float data_67d5fc = 0
0067d600 float data_67d600 = 1
0067d604 float data_67d604 = 0.5
0067d608 float data_67d608 = 0.75
0067d60c float data_67d60c = 0.5
0067d610 float data_67d610 = 0.5
0067d614 float data_67d614 = 0.5
0067d618 float data_67d618 = 0.5
0067d61c float data_67d61c = 0
0067d620 float data_67d620 = 0.5
0067d624 float data_67d624 = 0.75
0067d628 float data_67d628 = 0
0067d62c float data_67d62c = 0.5
0067d630 float data_67d630 = 0
0067d634 float data_67d634 = 1
0067d638 float data_67d638 = 0.5
0067d63c float data_67d63c = 0.25
0067d640 float data_67d640 = 0.5
0067d644 float data_67d644 = 0.5
0067d648 float data_67d648 = 0.5
0067d64c float data_67d64c = 0
0067d650 float data_67d650 = 0
0067d654 float data_67d654 = 0.75
0067d658 float data_67d658 = 0.5
0067d65c float data_67d65c = 0.109999999
0067d660 float data_67d660 = 0
0067d664 float data_67d664 = 0.5
0067d668 float data_67d668 = 1
0067d66c float data_67d66c = 0.215000004
0067d670 float data_67d670 = 1
0067d674 float data_67d674 = 0
0067d678 float data_67d678 = 0
0067d67c float data_67d67c = 0
0067d680 float data_67d680 = 0.0105263162
0067d684 float data_67d684 = 0.5
0067d688 float data_67d688 = 0.100000001
0067d68c float data_67d68c = 0
0067d690 float data_67d690 = 0
0067d694 float data_67d694 = 1
0067d698 float data_67d698 = 0.5
0067d69c float data_67d69c = 0.109999999
0067d6a0 float data_67d6a0 = 0
0067d6a4 float data_67d6a4 = 0.5
0067d6a8 float data_67d6a8 = 1
0067d6ac float data_67d6ac = 0.215000004
0067d6b0 float data_67d6b0 = 0.109999999
0067d6b4 float data_67d6b4 = 0
0067d6b8 float data_67d6b8 = 0.5
0067d6bc float data_67d6bc = 1
0067d6c0 float data_67d6c0 = 0.215000004
0067d6c4 float data_67d6c4 = 0.5
0067d6c8 float data_67d6c8 = 0.5
0067d6cc float data_67d6cc = 0.5
0067d6d0 float data_67d6d0 = 0.5
0067d6d4 float data_67d6d4 = 0
0067d6d8 float data_67d6d8 = 0.5
0067d6dc float data_67d6dc = 0
0067d6e0 float data_67d6e0 = 0
0067d6e4 float data_67d6e4 = 0.251188993
0067d6e8 float data_67d6e8 = 0.251188993
0067d6ec float data_67d6ec = 0.400000006
0067d6f0 float data_67d6f0 = 0.600000024
0067d6f4 float data_67d6f4 = 0.600000024
0067d6f8 float data_67d6f8 = 0.400000006
0067d6fc float data_67d6fc = 0.600000024
0067d700 float data_67d700 = 0.600000024
0067d704 float data_67d704 = 0.400000006
0067d708 float data_67d708 = 0.600000024
0067d70c float data_67d70c = 0.600000024
0067d710 float data_67d710 = 0.5
0067d714 float data_67d714 = 0.200000003
0067d718 float data_67d718 = 0.349999994
0067d71c float data_67d71c = 0.349999994
0067d720 float data_67d720 = 0
0067d724 float data_67d724 = 0.25
0067d728 float data_67d728 = 0.349999994
0067d72c float data_67d72c = 0.200000003
0067d730 float data_67d730 = 0.333000004
0067d734 float data_67d734 = 0.666000009
0067d738 float data_67d738 = 0.600000024
0067d73c float data_67d73c = 0.600000024
0067d740 float data_67d740 = 0.5
0067d744 float data_67d744 = 0.5
0067d748 float data_67d748 = 0
0067d74c float data_67d74c = 0
0067d750 float data_67d750 = 1
0067d754 float data_67d754 = 0.25
0067d758 float data_67d758 = 0
0067d75c float data_67d75c = 0
0067d760 float data_67d760 = 0.5
0067d764 float data_67d764 = 0.5
0067d768 float data_67d768 = 0
0067d76c float data_67d76c = 1
0067d770 float data_67d770 = 0
0067d774 float data_67d774 = 0.25
0067d778 float data_67d778 = 1
0067d77c float data_67d77c = 0.5
0067d780 float data_67d780 = 0.5
0067d784 float data_67d784 = 1
0067d788 float data_67d788 = 0
0067d78c float data_67d78c = 0.25
0067d790 float data_67d790 = 0.5
0067d794 float data_67d794 = 0.5
0067d798 float data_67d798 = 0.800000012
0067d79c float data_67d79c = 0.5
0067d7a0 float data_67d7a0 = 0.5
0067d7a4 float data_67d7a4 = 0
0067d7a8 float data_67d7a8 = 0.25
0067d7ac float data_67d7ac = 0.5
0067d7b0 float data_67d7b0 = 0
0067d7b4 float data_67d7b4 = 1
0067d7b8 float data_67d7b8 = 0.100000001
0067d7bc float data_67d7bc = 0.5
0067d7c0 float data_67d7c0 = 0.300000012
0067d7c4 float data_67d7c4 = 0.5
0067d7c8 float data_67d7c8 = 0.800000012
0067d7cc float data_67d7cc = 1
0067d7d0 float data_67d7d0 = 0
0067d7d4 float data_67d7d4 = 0.625
0067d7d8 float data_67d7d8 = 0.625
0067d7dc float data_67d7dc = 0
0067d7e0 float data_67d7e0 = 0.400000006
0067d7e4 float data_67d7e4 = 0.5
0067d7e8 float data_67d7e8 = 0.5
0067d7ec float data_67d7ec = 0.5
0067d7f0 float data_67d7f0 = 0.75
0067d7f4 float data_67d7f4 = 0.300000012
0067d7f8 float data_67d7f8 = 0.300000012
0067d7fc float data_67d7fc = 0
0067d800 float data_67d800 = 0
0067d804 float data_67d804 = 1
0067d808 float data_67d808 = 0
0067d80c float data_67d80c = 0.5
0067d810 float data_67d810 = 0
0067d814 float data_67d814 = 0
0067d818 float data_67d818 = 0
0067d81c float data_67d81c = 0.5
0067d820 float data_67d820 = 0.400000006
0067d824 float data_67d824 = 0.25
0067d828 float data_67d828 = 0.5
0067d82c float data_67d82c = 0
0067d830 float data_67d830 = 0.5
0067d834 float data_67d834 = 0
0067d838 float data_67d838 = 0
0067d83c float data_67d83c = 0
0067d840 float data_67d840 = 0
0067d844 float data_67d844 = 0
0067d848 float data_67d848 = 0
0067d84c float data_67d84c = 0
0067d850 float data_67d850 = 0
0067d854 float data_67d854 = 0
0067d858 float data_67d858 = 0
0067d85c float data_67d85c = 0
0067d860 float data_67d860 = 1
0067d864 float data_67d864 = 1
0067d868 float data_67d868 = 0.540799975
0067d86c float data_67d86c = 0.459100008
0067d870 float data_67d870 = 0
0067d874 float data_67d874 = 0
0067d878 float data_67d878 = 0
0067d87c float data_67d87c = 0.5
0067d880 float data_67d880 = 1
0067d884 float data_67d884 = 1
0067d888 float data_67d888 = 0.5
0067d88c float data_67d88c = 0.5
0067d890 float data_67d890 = 0.5
0067d894 float data_67d894 = 0.5
0067d898 float data_67d898 = 0
0067d89c float data_67d89c = 0
0067d8a0 float data_67d8a0 = 0
0067d8a4 float data_67d8a4 = 1
0067d8a8 float data_67d8a8 = 0
0067d8ac float data_67d8ac = 1
0067d8b0 float data_67d8b0 = 0
0067d8b4 float data_67d8b4 = 1
0067d8b8 float data_67d8b8 = 0
0067d8bc float data_67d8bc = 1
0067d8c0 float data_67d8c0 = 0
0067d8c4 float data_67d8c4 = 1
0067d8c8 float data_67d8c8 = 0
0067d8cc float data_67d8cc = 1
0067d8d0 float data_67d8d0 = 0
0067d8d4 float data_67d8d4 = 1
0067d8d8 float data_67d8d8 = 0
0067d8dc float data_67d8dc = 1
0067d8e0 float data_67d8e0 = 0
0067d8e4 float data_67d8e4 = 1
0067d8e8 float data_67d8e8 = 0
0067d8ec float data_67d8ec = 1
0067d8f0 float data_67d8f0 = 0
0067d8f4 float data_67d8f4 = 1
0067d8f8 float data_67d8f8 = 0
0067d8fc float data_67d8fc = 1
0067d900 float data_67d900 = 0
0067d904 float data_67d904 = 1
0067d908 float data_67d908 = 0
0067d90c float data_67d90c = 1
0067d910 float data_67d910 = 0
0067d914 float data_67d914 = 1
0067d918 float data_67d918 = 0
0067d91c float data_67d91c = 1
0067d920 float data_67d920 = 1
0067d924 float data_67d924 = 0
0067d928 float data_67d928 = 0
0067d92c float data_67d92c = 0
0067d930 float data_67d930 = 0
0067d934 float data_67d934 = 0
0067d938 float data_67d938 = 0
0067d93c float data_67d93c = 0
0067d940 float data_67d940 = 0
0067d944 float data_67d944 = 0
0067d948 float data_67d948 = 0.5
0067d94c float data_67d94c = 0
0067d950 float data_67d950 = 0
0067d954 float data_67d954 = 0
0067d958 float data_67d958 = 0
0067d95c float data_67d95c = 0.5
0067d960 float data_67d960 = 0
0067d964 float data_67d964 = 1
0067d968 float data_67d968 = 0
0067d96c float data_67d96c = 1
0067d970 float data_67d970 = 0
0067d974 float data_67d974 = 1
0067d978 float data_67d978 = 0
0067d97c float data_67d97c = 1
0067d980 float data_67d980 = 0
0067d984 float data_67d984 = 1
0067d988 float data_67d988 = 0
0067d98c float data_67d98c = 1
0067d990 float data_67d990 = 0
0067d994 float data_67d994 = 1
0067d998 float data_67d998 = 0
0067d99c float data_67d99c = 1
0067d9a0 float data_67d9a0 = 0
0067d9a4 float data_67d9a4 = 1
0067d9a8 float data_67d9a8 = 0
0067d9ac float data_67d9ac = 1
0067d9b0 float data_67d9b0 = 0
0067d9b4 float data_67d9b4 = 1
0067d9b8 float data_67d9b8 = 0
0067d9bc float data_67d9bc = 1
0067d9c0 float data_67d9c0 = 0
0067d9c4 float data_67d9c4 = 1
0067d9c8 float data_67d9c8 = 0
0067d9cc float data_67d9cc = 1
0067d9d0 float data_67d9d0 = 0
0067d9d4 float data_67d9d4 = 1
0067d9d8 float data_67d9d8 = 0
0067d9dc float data_67d9dc = 1
0067d9e0 float data_67d9e0 = 0.5
0067d9e4 float data_67d9e4 = 0.5
0067d9e8 float data_67d9e8 = 0.5
0067d9ec float data_67d9ec = 0.5
0067d9f0 float data_67d9f0 = 0
0067d9f4 float data_67d9f4 = 0
0067d9f8 float data_67d9f8 = 0
0067d9fc float data_67d9fc = 0
0067da00 float data_67da00 = 0.5
0067da04 float data_67da04 = 1
0067da08 float data_67da08 = 0.5
0067da0c float data_67da0c = 0.5
0067da10 float data_67da10 = 0.5
0067da14 float data_67da14 = 0
0067da18 float data_67da18 = 0
0067da1c float data_67da1c = 0
0067da20 float data_67da20 = 0
0067da24 float data_67da24 = 0
0067da28 float data_67da28 = 0
0067da2c float data_67da2c = 0
0067da30 float data_67da30 = 0
0067da34 float data_67da34 = 0
0067da38 float data_67da38 = 0
0067da3c float data_67da3c = 0
0067da40 float data_67da40 = 0
0067da44 float data_67da44 = 0
0067da48 float data_67da48 = 0
0067da4c float data_67da4c = 0
0067da50 float data_67da50 = 0
0067da54 float data_67da54 = 0.5
0067da58 float data_67da58 = 0.5
0067da5c float data_67da5c = 0.5
0067da60 float data_67da60 = 0.5
0067da64 float data_67da64 = 0.5
0067da68 float data_67da68 = 0.5
0067da6c float data_67da6c = 0.5
0067da70 float data_67da70 = 0.5
0067da74 float data_67da74 = 0.5
0067da78 float data_67da78 = 0.5
0067da7c float data_67da7c = 0.5
0067da80 float data_67da80 = 0.5
0067da84 float data_67da84 = 0.5
0067da88 float data_67da88 = 0.5
0067da8c float data_67da8c = 0.5
0067da90 float data_67da90 = 0.5
0067da94 float data_67da94 = 0.5
0067da98 float data_67da98 = 0.5
0067da9c float data_67da9c = 0.5
0067daa0 float data_67daa0 = 0.5
0067daa4 float data_67daa4 = 0.5
0067daa8 float data_67daa8 = 0.5
0067daac float data_67daac = 0.5
0067dab0 float data_67dab0 = 0.5
0067dab4 float data_67dab4 = 0.5
0067dab8 float data_67dab8 = 0.5
0067dabc float data_67dabc = 0
0067dac0 float data_67dac0 = 0
0067dac4 float data_67dac4 = 0.5
0067dac8 float data_67dac8 = 0
0067dacc float data_67dacc = 0
0067dad0 float data_67dad0 = 0
0067dad4 float data_67dad4 = 0
0067dad8 float data_67dad8 = 0
0067dadc float data_67dadc = 0
0067dae0 float data_67dae0 = 0
0067dae4 float data_67dae4 = 0.5
0067dae8 float data_67dae8 = 0
0067daec float data_67daec = 0
0067daf0 float data_67daf0 = 0.225806445
0067daf4 float data_67daf4 = 1
0067daf8 float data_67daf8 = 0
0067dafc float data_67dafc = 0.0416666679
0067db00 float data_67db00 = 0.0416666679
0067db04 float data_67db04 = 0
0067db08 float data_67db08 = 0
0067db0c float data_67db0c = 0
0067db10 float data_67db10 = 0
0067db14 float data_67db14 = 0
0067db18 float data_67db18 = 0
0067db1c float data_67db1c = 0
0067db20 float data_67db20 = 1
0067db24 float data_67db24 = 0
0067db28 float data_67db28 = 0
0067db2c float data_67db2c = 0
0067db30 float data_67db30 = 0
0067db34 float data_67db34 = 1.875
0067db38 float data_67db38 = 0
0067db3c float data_67db3c = 1.875
vst param # name min max display unit default
0 MasterVol 0 100 = % 70
1 A Vol 0 100 = % 75
2 A Pan -50 50 = - 0
3 A Octave -4 4 = Oct 0
4 A Semi -12 12 = semitones 0
5 A Fine -100 100 = cents 0
6 A Unison 0 16 = - 0
7 A UniDet 0 1 ? - 0.5
8 A UniBlend 0 100 = - 75
9 A Warp 0 1 ? - 0
10 A CoarsePit 0 1 ? - 0.5
11 A WTPos 1 256 ? - 1
12 A RandPhase 0 100 = % 100
13 A Phase 0 1 ? ° 0.5
14 B Vol 0 100 = % 75
15 B Pan -50 50 = - 0
16 B Octave -4 4 = Oct 0
17 B Semi -12 12 = semitones 0
18 B Fine -100 100 = cents 0
19 B Unison 0 16 = - 0
20 B UniDet 0 1 ? - 0.5
21 B UniBlend 0 100 = - 75
22 B Warp 0 1 ? - 0
23 B CoarsePit 0 1 ? - 0.5
24 B WTPos 1 256 ? - 1
25 B RandPhase 0 100 = % 100
26 B Phase 0 1 ? ° 0.5
27 Noise Level 0 100 = % 25
28 Noise Pitch 0 100 = % 50
29 Noise Fine -1 1 = % 0
30 Noise Pan -50 50 = - 0
31 Noise RandPhase 0 100 = % 0
32 Noise Phase 0 100 = % 0
33 Sub Osc Level 0 100 = % 75
34 Sub Osc Pan -50 50 = % 0
35 Env1 Atk 0 1 ? ms 0.11
36 Env1 Hold 0 1 ? ms 0
37 Env1 Dec 0 1 ? s 0.5
38 Env1 Sus 0 1 ? dB 1
39 Env1 Rel 0 1 ? ms 0.215
40 OscA>Fil 0 1 ! - 1
41 OscB>Fil 0 1 ! - 0
42 OscN>Fil 0 1 ! - 0
43 OscS>Fil 0 1 ! - 0
44 Fil Type 0 1 ? - 0.0113636
45 Fil Cutoff 0 1 ? Hz 0.5
46 Fil Reso 0 100 = % 10
47 Fil Driv 0 100 = % 0
48 Fil Var 0 100 = % 0
49 Fil Mix 0 100 = % 100
50 Fil Stereo 0 100 = % 50
51 Env2 Atk 0 1 ? ms 0.11
52 Env2 Hld 0 1 ? ms 0
53 Env2 Dec 0 1 ? s 0.5
54 Env2 Sus 0 100 = % 100
55 Env2 Rel 0 1 ? ms 0.215
56 Env3 Atk 0 1 ? ms 0.11
57 Env3 Hld 0 1 ? ms 0
58 Env3 Dec 0 1 ? s 0.5
59 Env3 Sus 0 100 = % 100
60 Env3 Rel 0 1 ? ms 0.215
61 LFO1Rate 0 1 ! - 0.5
62 LFO2Rate 0 1 ! - 0.5
63 LFO3Rate 0 1 ! - 0.5
64 LFO4Rate 0 1 ! - 0.5
65 PortTime 0 1 ? ms 0
66 PortCurve -100 100 = % 0
67 Chaos1 BPM 0 1 ? - 0
68 Chaos2 BPM 0 1 ? - 0
69 Chaos1 Rate 0 1 ? - 0.251189
70 Chaos2 Rate 0 1 ? - 0.251189
71 A curve1 0 100 = % 50
72 D curve1 0 100 = % 67
73 R curve1 0 100 = % 67
74 A curve2 0 100 = % 50
75 D curve2 0 100 = % 67
76 R curve2 0 100 = % 67
77 A curve3 0 100 = % 50
78 D curve3 0 100 = % 67
79 R curve3 0 100 = % 67
80 Mast.Tun 0 0 = - 0
81 Verb Wet 0 100 = % 33
82 VerbSize 0 100 = % 33
83 VerbPDly 0 1 ? ms 0.12
84 VerbLoCt 0 100 = % 0
85 VerbDamp 0 100 = % 28
86 VerbHiCt 0 100 = % 50
87 VerbWdth 0 100 = % 100
88 EQ FrqL 0 1 ? Hz 0.333
89 EQ FrqH 0 1 ? Hz 0.666
90 EQ Q L 0 100 = % 60
91 EQ Q H 0 100 = % 60
92 EQ VolL -24 24 = dB 0
93 EQ VolH -24 24 = dB 0
94 EQ TypL 0 1 ? - 0
95 EQ TypH 0 1 ? - 0
96 Dist_Wet 0 100 = % 100
97 Dist_Drv 0 100 = % 25
98 Dist_L/B/H 0 100 = % 0
99 Dist_Mode 0 1 ? - 0
100 Dist_Freq 0 1 ? Hz 0.5
101 Dist_BW 0 1 ? - 0.5
102 Dist_PrePost 0 1 ? - 0
103 Flg_Wet 0 100 = % 100
104 Flg_BPM_Sync 0 1 ? - 0
105 Flg_Rate 0 1 ? Hz 0.25
106 Flg_Dep 0 100 = % 100
107 Flg_Feed 0 100 = % 50
108 Flg_Stereo 0 360 = ° 180
109 Phs_Wet 0 100 = % 100
110 Phs_BPM_Sync 0 1 ? - 0
111 Phs_Rate 0 1 ? Hz 0.25
112 Phs_Dpth 0 100 = % 50
113 Phs_Frq 0 1 ? Hz 0.5
114 Phs_Feed 0 100 = % 80
115 Phs_Stereo 0 360 = ° 180
116 Cho_Wet 0 100 = % 50
117 Cho_BPM_Sync 0 1 ? - 0
118 Cho_Rate 0 1 ? Hz 0.25
119 Cho_Dly 0 1 ? ms 0.5
120 Cho_Dly2 0 1 ? ms 0
121 Cho_Dep 0 1 ? ms 1
122 Cho_Feed 0 1 ? % 0.1
123 Cho_Filt 0 1 ? Hz 0.5
124 Dly_Wet 0 100 = % 30
125 Dly_Freq 0 1 ? Hz 0.5
126 Dly_BW 0.8 8.2 = - 6.8
127 Dly_BPM_Sync 0 1 ? - 1
128 Dly_Link 0 1 ? - 0
129+ Dly_TimL 0 1 ? - 0.625
130+ Dly_TimR 0 1 ? - 0.625
131 Dly_Mode 0 1 ? - 0
132 Dly_Feed 0 100 = % 40
133+ Dly_Off L 0 1 ? - 0.5
134+ Dly_Off R 0 1 ? - 0.5
135 Cmp_Thr 0 1 ? dB 0.5
136 Cmp_Rat 0 1 ? - 0.75
137 Cmp_Att 0 1 ? ms 0.3
138 Cmp_Rel 0 1 ? ms 0.3
139 CmpGain 0 1 ? dB 0
140 CmpMBnd 0 1 ? - 0
141 FX Fil Wet 0 100 = % 100
142 FX Fil Type 0 1 ? - 0
143 FX Fil Freq 0 1 ? Hz 0.5
144 FX Fil Reso 0 100 = % 0
145 FX Fil Drive 0 100 = % 0
146 FX Fil Var 0 100 = % 0
147 Hyp_Wet 0 100 = % 50
148 Hyp_Rate 0 1 ? % 0.4
149 Hyp_Detune 0 100 = % 25
150 Hyp_Unison 0 1 ? - 0.571429
151 Hyp_Retrig 0 1 ? - 0
152 HypDim_Size 0 100 = % 50
153 HypDim_Mix 0 100 = % 0
154 Dist Enable 0 1 ? - 0
155 Flg Enable 0 1 ? - 0
156 Phs Enable 0 1 ? - 0
157 Cho Enable 0 1 ? - 0
158 Dly Enable 0 1 ? - 0
159 Comp Enable 0 1 ? - 0
160 Rev Enable 0 1 ? - 0
161 EQ Enable 0 1 ? - 0
162 FX Fil Enable 0 1 ? - 0
163 Hyp Enable 0 1 ? - 0
164 OscAPitchTrack 0 1 ? - 1
165 OscBPitchTrack 0 1 ? - 1
166 Bend U -24 24 = semitones 2
167 Bend D -24 24 = semitones -2
168 WarpOscA 0 1 ? - 0
169 WarpOscB 0 1 ? - 0
170 SubOscShape 0 1 ? - 0
171 SubOscOctave -4 4 = Oct 0
172 A Uni LR 0 100 = - 100
173 B Uni LR 0 100 = - 100
174 A Uni Warp -100 100 = - 0
175 B Uni Warp -100 100 = - 0
176 A Uni WTPos -100 100 = - 0
177 B Uni WTPos -100 100 = - 0
178 A Uni Stack 0 1 ? - 0
179 B Uni Stack 0 1 ? - 0
180 Mod 1 amt -100 100 = - 0
181 Mod 1 out 0 100 = - 100
182 Mod 2 amt -100 100 = - 0
183 Mod 2 out 0 100 = - 100
184 Mod 3 amt -100 100 = - 0
185 Mod 3 out 0 100 = - 100
186 Mod 4 amt -100 100 = - 0
187 Mod 4 out 0 100 = - 100
188 Mod 5 amt -100 100 = - 0
189 Mod 5 out 0 100 = - 100
190 Mod 6 amt -100 100 = - 0
191 Mod 6 out 0 100 = - 100
192 Mod 7 amt -100 100 = - 0
193 Mod 8 out 0 100 = - 100
194 Mod 8 amt -100 100 = - 0
195 Mod 8 out 0 100 = - 100
196 Mod 9 amt -100 100 = - 0
197 Mod 9 out 0 100 = - 100
198 Mod10 amt -100 100 = - 0
199 Mod10 out 0 100 = - 100
200 Mod11 amt -100 100 = - 0
201 Mod11 out 0 100 = - 100
202 Mod12 amt -100 100 = - 0
203 Mod12 out 0 100 = - 100
204 Mod13 amt -100 100 = - 0
205 Mod13 out 0 100 = - 100
206 Mod14 amt -100 100 = - 0
207 Mod14 out 0 100 = - 100
208 Mod15 amt -100 100 = - 0
209 Mod15 out 0 100 = - 100
210 Mod16 amt -100 100 = - 0
211 Mod16 out 0 100 = - 100
212 Osc A On 0 1 ? - 1
213 Osc B On 0 1 ? - 0
214 Osc N On 0 1 ? - 0
215 Osc S On 0 1 ? - 0
216 Filter On 0 1 ? - 0
217 Mod Wheel 0 100 = % 0
218 Macro 1 0 100 = % 0
219 Macro 2 0 100 = % 0
220 Macro 3 0 100 = % 0
221 Macro 4 0 100 = % 0
222 Amp. 0 100 = % 0
223 LFO1 smooth 0 100 = - 0
224 LFO2 smooth 0 100 = - 0
225 LFO3 smooth 0 100 = - 0
226 LFO4 smooth 0 100 = - 0
227 Pitch Bend 0 1 ? - 0.5
228 Mod17 amt -100 100 = - 0
229 Mod17 out 0 100 = - 100
230 Mod18 amt -100 100 = - 0
231 Mod18 out 0 100 = - 100
232 Mod19 amt -100 100 = - 0
233 Mod19 out 0 100 = - 100
234 Mod20 amt -100 100 = - 0
235 Mod20 out 0 100 = - 100
236 Mod21 amt -100 100 = - 0
237 Mod21 out 0 100 = - 100
238 Mod22 amt -100 100 = - 0
239 Mod22 out 0 100 = - 100
240 Mod23 amt -100 100 = - 0
241 Mod23 out 0 100 = - 100
242 Mod24 amt -100 100 = - 0
243 Mod24 out 0 100 = - 100
244 Mod25 amt -100 100 = - 0
245 Mod25 out 0 100 = - 100
246 Mod26 amt -100 100 = - 0
247 Mod26 out 0 100 = - 100
248 Mod27 amt -100 100 = - 0
249 Mod27 out 0 100 = - 100
250 Mod28 amt -100 100 = - 0
251 Mod28 out 0 100 = - 100
252 Mod29 amt -100 100 = - 0
253 Mod29 out 0 100 = - 100
254 Mod30 amt -100 100 = - 0
255 Mod30 out 0 100 = - 100
256 Mod31 amt -100 100 = - 0
257 Mod31 out 0 100 = - 100
258 Mod32 amt -100 100 = - 0
259 Mod32 out 0 100 = - 100
260 LFO5Rate 0 1 ! - 0.5
261 LFO6Rate 0 1 ! - 0.5
262 LFO7Rate 0 1 ! - 0.5
263 LFO8Rate 0 1 ! - 0.5
264 LFO5 smooth 0 100 = - 0
265 LFO6 smooth 0 100 = - 0
266 LFO7 smooth 0 100 = - 0
267 LFO8 smooth 0 100 = - 0
268 FXFil Pan 0 100 = % 50
269 Comp_Wet 0 100 = % 50
270 Gain L 0 200 = % 100
271 Gain M 0 200 = % 100
272 Gain H 0 200 = % 100
273 LFO1 Rise 0 1 ! - 0.0
274 LFO2 Rise 0 1 ! - 0.0
275 LFO3 Rise 0 1 ! - 0.0
276 LFO4 Rise 0 1 ! - 0.0
277 LFO5 Rise 0 1 ! - 0.0
278 LFO6 Rise 0 1 ! - 0.0
279 LFO7 Rise 0 1 ! - 0.0
280 LFO8 Rise 0 1 ! - 0.0
281 LFO1 Delay 0 1 ! - 0.0
282 LFO2 Delay 0 1 ! - 0.0
283 LFO3 Delay 0 1 ! - 0.0
284 LFO4 Delay 0 1 ! - 0.0
285 LFO5 Delay 0 1 ! - 0.0
286 LFO6 Delay 0 1 ! - 0.0
287 LFO7 Delay 0 1 ! - 0.0
288 LFO8 Delay 0 1 ! - 0.0
vst param # name min max display unit default
0 MasterVol 0 100 = % 70
1 A Vol 0 100 = % 75
2 A Pan -50 50 = - 0
3 A Octave -4 4 = Oct 0
4 A Semi -12 12 = semitones 0
5 A Fine -100 100 = cents 0
6 A Unison 0 16 = - 0
7 A UniDet 0 1 ? - 0.5
8 A UniBlend 0 100 = - 75
9 A Warp 0 1 ? - 0
10 A CoarsePit 0 1 ? - 0.5
11 A WTPos 1 256 ? - 1
12 A RandPhase 0 100 = % 100
13 A Phase 0 1 ? ° 0.5
14 B Vol 0 100 = % 75
15 B Pan -50 50 = - 0
16 B Octave -4 4 = Oct 0
17 B Semi -12 12 = semitones 0
18 B Fine -100 100 = cents 0
19 B Unison 0 16 = - 0
20 B UniDet 0 1 ? - 0.5
21 B UniBlend 0 100 = - 75
22 B Warp 0 1 ? - 0
23 B CoarsePit 0 1 ? - 0.5
24 B WTPos 1 256 ? - 1
25 B RandPhase 0 100 = % 100
26 B Phase 0 1 ? ° 0.5
27 Noise Level 0 100 = % 25
28 Noise Pitch 0 100 = % 50
29 Noise Fine -1 1 = % 0
30 Noise Pan -50 50 = - 0
31 Noise RandPhase 0 100 = % 0
32 Noise Phase 0 100 = % 0
33 Sub Osc Level 0 100 = % 75
34 Sub Osc Pan -50 50 = % 0
35 Env1 Atk 0 1 ? ms 0.11
36 Env1 Hold 0 1 ? ms 0
37 Env1 Dec 0 1 ? s 0.5
38 Env1 Sus 0 1 ? dB 1
39 Env1 Rel 0 1 ? ms 0.215
40 OscA>Fil 0 1 ! - 1
41 OscB>Fil 0 1 ! - 0
42 OscN>Fil 0 1 ! - 0
43 OscS>Fil 0 1 ! - 0
44 Fil Type 0 1 ? - 0.0113636
45 Fil Cutoff 0 1 ? Hz 0.5
46 Fil Reso 0 100 = % 10
47 Fil Driv 0 100 = % 0
48 Fil Var 0 100 = % 0
49 Fil Mix 0 100 = % 100
50 Fil Stereo 0 100 = % 50
51 Env2 Atk 0 1 ? ms 0.11
52 Env2 Hld 0 1 ? ms 0
53 Env2 Dec 0 1 ? s 0.5
54 Env2 Sus 0 100 = % 100
55 Env2 Rel 0 1 ? ms 0.215
56 Env3 Atk 0 1 ? ms 0.11
57 Env3 Hld 0 1 ? ms 0
58 Env3 Dec 0 1 ? s 0.5
59 Env3 Sus 0 100 = % 100
60 Env3 Rel 0 1 ? ms 0.215
61 LFO1Rate 0 1 ! - 0.5
62 LFO2Rate 0 1 ! - 0.5
63 LFO3Rate 0 1 ! - 0.5
64 LFO4Rate 0 1 ! - 0.5
65 PortTime 0 1 ? ms 0
66 PortCurve -100 100 = % 0
67 Chaos1 BPM 0 1 ? - 0
68 Chaos2 BPM 0 1 ? - 0
69 Chaos1 Rate 0 1 ? - 0.251189
70 Chaos2 Rate 0 1 ? - 0.251189
71 A curve1 0 100 = % 50
72 D curve1 0 100 = % 67
73 R curve1 0 100 = % 67
74 A curve2 0 100 = % 50
75 D curve2 0 100 = % 67
76 R curve2 0 100 = % 67
77 A curve3 0 100 = % 50
78 D curve3 0 100 = % 67
79 R curve3 0 100 = % 67
80 Mast.Tun 0 0 = - 0
81 Verb Wet 0 100 = % 33
82 VerbSize 0 100 = % 33
83 VerbPDly 0 1 ? ms 0.12
84 VerbLoCt 0 100 = % 0
85 VerbDamp 0 100 = % 28
86 VerbHiCt 0 100 = % 50
87 VerbWdth 0 100 = % 100
88 EQ FrqL 0 1 ? Hz 0.333
89 EQ FrqH 0 1 ? Hz 0.666
90 EQ Q L 0 100 = % 60
91 EQ Q H 0 100 = % 60
92 EQ VolL -24 24 = dB 0
93 EQ VolH -24 24 = dB 0
94 EQ TypL 0 1 ? - 0
95 EQ TypH 0 1 ? - 0
96 Dist_Wet 0 100 = % 100
97 Dist_Drv 0 100 = % 25
98 Dist_L/B/H 0 100 = % 0
99 Dist_Mode 0 1 ? - 0
100 Dist_Freq 0 1 ? Hz 0.5
101 Dist_BW 0 1 ? - 0.5
102 Dist_PrePost 0 1 ? - 0
103 Flg_Wet 0 100 = % 100
104 Flg_BPM_Sync 0 1 ? - 0
105 Flg_Rate 0 1 ? Hz 0.25
106 Flg_Dep 0 100 = % 100
107 Flg_Feed 0 100 = % 50
108 Flg_Stereo 0 360 = ° 180
109 Phs_Wet 0 100 = % 100
110 Phs_BPM_Sync 0 1 ? - 0
111 Phs_Rate 0 1 ? Hz 0.25
112 Phs_Dpth 0 100 = % 50
113 Phs_Frq 0 1 ? Hz 0.5
114 Phs_Feed 0 100 = % 80
115 Phs_Stereo 0 360 = ° 180
116 Cho_Wet 0 100 = % 50
117 Cho_BPM_Sync 0 1 ? - 0
118 Cho_Rate 0 1 ? Hz 0.25
119 Cho_Dly 0 1 ? ms 0.5
120 Cho_Dly2 0 1 ? ms 0
121 Cho_Dep 0 1 ? ms 1
122 Cho_Feed 0 1 ? % 0.1
123 Cho_Filt 0 1 ? Hz 0.5
124 Dly_Wet 0 100 = % 30
125 Dly_Freq 0 1 ? Hz 0.5
126 Dly_BW 0.8 8.2 = - 6.8
127 Dly_BPM_Sync 0 1 ? - 1
128 Dly_Link 0 1 ? - 0
129 Dly_TimL 0 1 ? - 0.625
130 Dly_TimR 0 1 ? - 0.625
131 Dly_Mode 0 1 ? - 0
132 Dly_Feed 0 100 = % 40
133 Dly_Off L 0 1 ? - 0.5
134 Dly_Off R 0 1 ? - 0.5
135 Cmp_Thr 0 1 ? dB 0.5
136 Cmp_Rat 0 1 ? - 0.75
137 Cmp_Att 0 1 ? ms 0.3
138 Cmp_Rel 0 1 ? ms 0.3
139 CmpGain 0 1 ? dB 0
140 CmpMBnd 0 1 ? - 0
141 FX Fil Wet 0 100 = % 100
142 FX Fil Type 0 1 ? - 0
143 FX Fil Freq 0 1 ? Hz 0.5
144 FX Fil Reso 0 100 = % 0
145 FX Fil Drive 0 100 = % 0
146 FX Fil Var 0 100 = % 0
147 Hyp_Wet 0 100 = % 50
148 Hyp_Rate 0 1 ? % 0.4
149 Hyp_Detune 0 100 = % 25
150 Hyp_Unison 0 1 ? - 0.571429
151 Hyp_Retrig 0 1 ? - 0
152 HypDim_Size 0 100 = % 50
153 HypDim_Mix 0 100 = % 0
154 Dist Enable 0 1 ? - 0
155 Flg Enable 0 1 ? - 0
156 Phs Enable 0 1 ? - 0
157 Cho Enable 0 1 ? - 0
158 Dly Enable 0 1 ? - 0
159 Comp Enable 0 1 ? - 0
160 Rev Enable 0 1 ? - 0
161 EQ Enable 0 1 ? - 0
162 FX Fil Enable 0 1 ? - 0
163 Hyp Enable 0 1 ? - 0
164 OscAPitchTrack 0 1 ? - 1
165 OscBPitchTrack 0 1 ? - 1
166 Bend U -24 24 = semitones 2
167 Bend D -24 24 = semitones -2
168 WarpOscA 0 1 ? - 0
169 WarpOscB 0 1 ? - 0
170 SubOscShape 0 1 ? - 0
171 SubOscOctave -4 4 = Oct 0
172 A Uni LR 0 100 = - 100
173 B Uni LR 0 100 = - 100
174 A Uni Warp -100 100 = - 0
175 B Uni Warp -100 100 = - 0
176 A Uni WTPos -100 100 = - 0
177 B Uni WTPos -100 100 = - 0
178 A Uni Stack 0 1 ? - 0
179 B Uni Stack 0 1 ? - 0
180 Mod 1 amt -100 100 = - 0
181 Mod 1 out 0 100 = - 100
182 Mod 2 amt -100 100 = - 0
183 Mod 2 out 0 100 = - 100
184 Mod 3 amt -100 100 = - 0
185 Mod 3 out 0 100 = - 100
186 Mod 4 amt -100 100 = - 0
187 Mod 4 out 0 100 = - 100
188 Mod 5 amt -100 100 = - 0
189 Mod 5 out 0 100 = - 100
190 Mod 6 amt -100 100 = - 0
191 Mod 6 out 0 100 = - 100
192 Mod 7 amt -100 100 = - 0
193 Mod 8 out 0 100 = - 100
194 Mod 8 amt -100 100 = - 0
195 Mod 8 out 0 100 = - 100
196 Mod 9 amt -100 100 = - 0
197 Mod 9 out 0 100 = - 100
198 Mod10 amt -100 100 = - 0
199 Mod10 out 0 100 = - 100
200 Mod11 amt -100 100 = - 0
201 Mod11 out 0 100 = - 100
202 Mod12 amt -100 100 = - 0
203 Mod12 out 0 100 = - 100
204 Mod13 amt -100 100 = - 0
205 Mod13 out 0 100 = - 100
206 Mod14 amt -100 100 = - 0
207 Mod14 out 0 100 = - 100
208 Mod15 amt -100 100 = - 0
209 Mod15 out 0 100 = - 100
210 Mod16 amt -100 100 = - 0
211 Mod16 out 0 100 = - 100
212 Osc A On 0 1 ? - 1
213 Osc B On 0 1 ? - 0
214 Osc N On 0 1 ? - 0
215 Osc S On 0 1 ? - 0
216 Filter On 0 1 ? - 0
217 Mod Wheel 0 100 = % 0
218 Macro 1 0 100 = % 0
219 Macro 2 0 100 = % 0
220 Macro 3 0 100 = % 0
221 Macro 4 0 100 = % 0
222 Amp. 0 0 = - 0
223 LFO1 smooth 0 100 = - 0
224 LFO2 smooth 0 100 = - 0
225 LFO3 smooth 0 100 = - 0
226 LFO4 smooth 0 100 = - 0
227 Pitch Bend 0 1 ? - 0.5
228 Mod17 amt -100 100 = - 0
229 Mod17 out 0 100 = - 100
230 Mod18 amt -100 100 = - 0
231 Mod18 out 0 100 = - 100
232 Mod19 amt -100 100 = - 0
233 Mod19 out 0 100 = - 100
234 Mod20 amt -100 100 = - 0
235 Mod20 out 0 100 = - 100
236 Mod21 amt -100 100 = - 0
237 Mod21 out 0 100 = - 100
238 Mod22 amt -100 100 = - 0
239 Mod22 out 0 100 = - 100
240 Mod23 amt -100 100 = - 0
241 Mod23 out 0 100 = - 100
242 Mod24 amt -100 100 = - 0
243 Mod24 out 0 100 = - 100
244 Mod25 amt -100 100 = - 0
245 Mod25 out 0 100 = - 100
246 Mod26 amt -100 100 = - 0
247 Mod26 out 0 100 = - 100
248 Mod27 amt -100 100 = - 0
249 Mod27 out 0 100 = - 100
250 Mod28 amt -100 100 = - 0
251 Mod28 out 0 100 = - 100
252 Mod29 amt -100 100 = - 0
253 Mod29 out 0 100 = - 100
254 Mod30 amt -100 100 = - 0
255 Mod30 out 0 100 = - 100
256 Mod31 amt -100 100 = - 0
257 Mod31 out 0 100 = - 100
258 Mod32 amt -100 100 = - 0
259 Mod32 out 0 100 = - 100
260 LFO5Rate 0 1 ! - 0.5
261 LFO6Rate 0 1 ! - 0.5
262 LFO7Rate 0 1 ! - 0.5
263 LFO8Rate 0 1 ! - 0.5
264 LFO5 smooth 0 100 = - 0
265 LFO6 smooth 0 100 = - 0
266 LFO7 smooth 0 100 = - 0
267 LFO8 smooth 0 100 = - 0
268 FXFil Pan 0 100 = % 50
269 Comp_Wet 0 100 = % 50
270 Gain L 0 200 = % 100
271 Gain M 0 200 = % 100
272 Gain H 0 200 = % 100
273 LFO1 Rise 0 1 ! - 0.0
274 LFO2 Rise 0 1 ! - 0.0
275 LFO3 Rise 0 1 ! - 0.0
276 LFO4 Rise 0 1 ! - 0.0
277 LFO5 Rise 0 1 ! - 0.0
278 LFO6 Rise 0 1 ! - 0.0
279 LFO7 Rise 0 1 ! - 0.0
280 LFO8 Rise 0 1 ! - 0.0
281 LFO1 Delay 0 1 ! - 0.0
282 LFO2 Delay 0 1 ! - 0.0
283 LFO3 Delay 0 1 ! - 0.0
284 LFO4 Delay 0 1 ! - 0.0
285 LFO5 Delay 0 1 ! - 0.0
286 LFO6 Delay 0 1 ! - 0.0
287 LFO7 Delay 0 1 ! - 0.0
288 LFO8 Delay 0 1 ! - 0.0
289 FX Dist Level 0 1 ! - 0.0
290 FX Flg Level 0 1 ! - 0.0
291 FX Phaser Level 0 1 ! - 0.0
292 FX Chorus Level 0 1 ! - 0.0
293 FX Delay Level 0 1 ! - 0.0
294 FX Comp Level 0 1 ! - 0.0
295 FX Reverb Level 0 1 ! - 0.0
296 FX DimExp Level 0 1 ! - 0.0
297 FX Filter Level 0 1 ! - 0.0
298 FX Hyper Level 0 1 ! - 0.0
# Katai Struct Definition for VST 2.x FXP files
# NOTE: This is a very early/rough WIP / exploratory prototype
# Refs:
# https://github.com/demberto/fxp/blob/main/fxp/__init__.py
# https://github.com/blurkk/symbiosis-au-vst-2/blob/develop/Symbiosis.mm#L1430-L1730
#
# https://doc.kaitai.io/user_guide.html#_kaitai_struct_language
# > 4. Kaitai Struct language
# https://doc.kaitai.io/user_guide.html#process
# > 5.6. Processing: dealing with compressed, obfuscated and encrypted data
# https://doc.kaitai.io/user_guide.html#meta-imports
# > 7.4. Importing types from other files
#
# https://en.wikipedia.org/wiki/IEEE_754
# The IEEE Standard for Floating-Point Arithmetic (IEEE 754) is a technical standard for floating-point arithmetic established in 1985 by the Institute of Electrical and Electronics Engineers (IEEE)
# In Little Endian:
# 0000 0000 0000 f03f = 64bit double precision floating point value for 1.0
# 0000 00e0 ffff df3f = 64bit double precision floating point value for 0.4999999701976776
# 0000 0000 0000 0000 = 64bit double precision floating point value for 0.0
# Notes:
# - We can slice the 'opaque content' section from a .fxp like this:
# `dd if=SooperSaw.fxp of=SooperSaw.fxp_opaquesection.zlib bs=1 skip=60`
#
# ```
# ⇒ file SooperSaw.fxp_opaquesection.zlib
# SooperSaw.fxp_opaquesection: zlib compressed data
# ```
#
# ```
# ./decompress_zlib.py
# ```
# https://doc.kaitai.io/user_guide.html#_instances_data_beyond_the_sequence
# https://doc.kaitai.io/user_guide.html#valid-values
meta:
id: vst_fxp
file-extension: fxp
endian: be
license: GPL-3.0
# imports:
# - TODO
seq:
- id: chunk_magic
contents: 'CcnK'
- id: byte_size
type: u4
- id: fx_magic
type: str
size: 4
encoding: ASCII
- id: version
contents: [0x00, 0x00, 0x00, 0x01]
# type: u4
# valid:
# min: 1
# max: 2
# any-of: [1, 2]
- id: fx_id
type: str
size: 4
encoding: ASCII
- id: fx_version
type: u4
- id: num_params
type: u4
- id: program_name
type: str
size: 24
encoding: ASCII
- id: padding
size: 4
- id: content
type:
switch-on: fx_magic
cases:
'"FxCk"': params_content
'"FPCh"': opaque_content
types:
params_content:
seq:
- id: params
type: f4
repeat: expr
repeat-expr: _parent.num_params
opaque_content:
seq:
- id: len_data
type: u4
- id: data
size: len_data
process: zlib
type: serum_preset
# TODO: The following is unknown and just arbitrary guesses
serum_preset:
# https://doc.kaitai.io/user_guide.html#_instances_data_beyond_the_sequence
instances:
maybe_preset_name:
pos: 18800 # 0x4970
size: 32
type: strz
encoding: ASCII
maybe_macro_1_label:
pos: 19040 # 0x4A60
size: 32
type: strz
encoding: ASCII
maybe_macro_2_label:
pos: 19072 # 0x4A80
size: 32
type: strz
encoding: ASCII
maybe_macro_3_label:
pos: 19104 # 0x4AA0
size: 32
type: strz
encoding: ASCII
maybe_macro_4_label:
pos: 19136 # 0x4AC0
size: 32
type: strz
encoding: ASCII
seq:
- id: unknown_1
size: 0x37c8 # Assuming this is the starting offset where the first known data changes
- id: maybe_macro_1_value
type: f4le # Type float, little-endian (change as necessary)
- id: maybe_macro_2_value
type: f4le
- id: maybe_macro_3_value
type: f4le
- id: maybe_macro_4_value
type: f4le
- id: unknown_till_eof
size-eos: true # Continue to the end of the stream/file if no more known sizes
# Basic opaque byte array
# - id: data
# size-eos: true
# # Attempt 1
# meta:
# endian: le
# seq:
# # - id: unknown_data
# # size: 4
# - id: entries
# type: serum_entry
# repeat: eos
# serum_entry:
# seq:
# - id: unknown_data
# # size: 8
# type: f4
#!/usr/bin/env python
# Notes:
# - We can slice the 'opaque content' section from a .fxp like this:
# `dd if=SooperSaw.fxp of=SooperSaw.fxp_opaquesection.zlib bs=1 skip=60`
# - We can slice the pre-params section from a .fxp_opaque_decompressed file like this:
# `dd if=init.fxp_opaque_decompressed of=init.fxp_opaque_decompressed_preparams bs=1 skip=0 count=$((0x3460))`
# - We can slice the post-params section from a .fxp_opaque_decompressed file like this:
# `dd if=init.fxp_opaque_decompressed of=init.fxp_opaque_decompressed_postparams bs=1 skip=$((0x3908))`
#
# ```
# ⇒ file SooperSaw.fxp_opaquesection.zlib
# SooperSaw.fxp_opaquesection: zlib compressed data
# ```
#
# ```
# ./decompress_zlib.py
# ```
# Trying to figure out how the wavetable data is stored in the .fxp files; comparing diffs, I tend to see sections like these changing:
# 0x0 for 24-bytes * 27 lines = 648-bytes
# 0x50e8 for 24-bytes * 34 lines = 816-bytes
# 0x8448 for 24-bytes * 7 lines = 168-bytes
# But there doesn't seem to be enough data changing for what I would expect given the changes I make..?
import argparse
import os
import struct
import zlib
from types import SimpleNamespace
from dataclasses import dataclass
data_segments = [
# The following param values are basically read from the SYParameters.txt file; with the offset reverse engineered from the manual params below
('?? Param0: MasterVol', 0x3460+(4*0), '<f'), # LE, Float (4-bytes)
('?? Param1: A Vol', 0x3460+(4*1), '<f'), # LE, Float (4-bytes)
('?? Param2: A Pan', 0x3460+(4*2), '<f'), # LE, Float (4-bytes)
# ..snip..
('?? Param35: Env1 Atk', 0x3460+(4*35), '<f'), # LE, Float (4-bytes)
('?? Param36: Env1 Hold', 0x3460+(4*36), '<f'), # LE, Float (4-bytes)
('?? Param37: Env1 Dec', 0x3460+(4*37), '<f'), # LE, Float (4-bytes)
('?? Param38: Env1 Sus', 0x3460+(4*38), '<f'), # LE, Float (4-bytes)
('?? Param39: Env1 Rel', 0x3460+(4*39), '<f'), # LE, Float (4-bytes)
# ..snip..
('?? Param298: FX Hyper Level', 0x3460+(4*298), '<f'), # LE, Float (4-bytes)
# etc
# These parameters were manually reversed using diffs/etc
('env1_atk_ms', 0x34ec, '<f'), # LE, Float (4-bytes)
('env1_hold_ms',0x34ec+4, '<f'), # LE, Float (4-bytes)
('env1_dec_s', 0x34ec+8, '<f'), # LE, Float (4-bytes)
('env1_sus_db', 0x34ec+12, '<f'), # LE, Float (4-bytes)
('env1_rel_ms', 0x34ec+16, '<f'), # LE, Float (4-bytes)
('env2_atk_ms', 0x352c, '<f'), # LE, Float (4-bytes)
('env2_hld_ms', 0x352c+4, '<f'), # LE, Float (4-bytes)
('env2_dec_s', 0x352c+8, '<f'), # LE, Float (4-bytes)
('env2_sus', 0x352c+12, '<f'), # LE, Float (4-bytes)
('env2_rel_ms', 0x352c+16, '<f'), # LE, Float (4-bytes)
('env3_atk_ms', 0x352c+20, '<f'), # LE, Float (4-bytes)
('env3_hld_ms', 0x352c+24, '<f'), # LE, Float (4-bytes)
('env3_dec_s', 0x352c+28, '<f'), # LE, Float (4-bytes)
('env3_sus_db', 0x352c+32, '<f'), # LE, Float (4-bytes)
('env3_rel_ms', 0x352c+36, '<f'), # LE, Float (4-bytes)
('maybe_macro_1_value', 0x37c8, '<f'), # LE, Float (4-bytes)
('maybe_macro_2_value', 0x37cc, '<f'), # LE, Float (4-bytes)
('maybe_macro_3_value', 0x37d0, '<f'), # LE, Float (4-bytes)
('maybe_macro_4_value', 0x37d4, '<f'), # LE, Float (4-bytes)
('maybe_noise_path', 0x4008, '<512s'), # LE, String (512-bytes)
('maybe_preset_name', 0x4972, '<32s'), # LE, String (32-bytes)
('maybe_macro_1_label', 0x4A60, '<32s'), # LE, String (32-bytes)
('maybe_macro_2_label', 0x4A80, '<32s'), # LE, String (32-bytes)
('maybe_macro_3_label', 0x4AA0, '<32s'), # LE, String (32-bytes)
('maybe_macro_4_label', 0x4AC0, '<32s'), # LE, String (32-bytes)
]
@dataclass
class FXPHeader:
file_magic: bytes
data_size: int
fx_magic: bytes
version: int
plugin_id: int
plugin_version: int
programs_count: int
program_name: str
chunk_size: int
def read_fxp_header(f):
"""Read the .fxp file header, validate it, and return the essential information, while printing header details."""
# Calculate the file size
f.seek(0, os.SEEK_END) # Move to the end of the file
file_size = f.tell() # Get the file pointer
f.seek(0, os.SEEK_SET) # Move back to the start of the file
# Header format:
# file_magic (4 bytes)
# data_size (4 bytes)
# fx_magic (4 bytes),
# version (4 bytes)
# plugin_id (4 bytes)
# plugin_version (4 bytes)
# programs_count (4 bytes)
# program_name (24 bytes)
# padding (4 bytes)
# chunk_size (4 bytes)
header_format = '>4sI4sIIII24s4xI'
expected_header_size = struct.calcsize(header_format)
estimated_chunk_size = file_size - expected_header_size
header_data = f.read(expected_header_size)
header_data_size = len(header_data)
if header_data_size < expected_header_size:
raise ValueError(f"Invalid file format: File too short to contain a valid header (expected {expected_header_size}, got {header_data_size})")
unpacked_data = struct.unpack(header_format, header_data)
fxp_header = FXPHeader(*unpacked_data)
# Validate magic bytes and fx_magic to ensure correct file type and structure
if fxp_header.file_magic != b'CcnK':
raise ValueError(f"Invalid file format: Missing expected 'CcnK' magic bytes: {fxp_header.file_magic}")
if fxp_header.fx_magic != b'FPCh':
raise ValueError(f"Invalid file format: File does not contain an opaque chunk or is not of type 'FPCh': {fxp_header.fx_magic}")
if fxp_header.version != 1 and fxp_header.version != 2:
raise ValueError(f"Invalid file format: Unexpected version: {fxp_header.version}")
chunk_data = f.read(fxp_header.chunk_size)
program_name_str = fxp_header.program_name.decode('ascii').rstrip('\x00')
plugin_id_str = fxp_header.plugin_id.to_bytes(4, byteorder='big').decode('ascii')
print(f"File Size: {file_size}")
print(f"Expected Header Size: {expected_header_size}")
print(f"Actual Header Size: {header_data_size}")
print(f"Estimated Chunk Size: {estimated_chunk_size}")
print()
# Print the header content for verification
print("Header Contents:")
print(f" File Magic: {fxp_header.file_magic.decode('ascii')}")
print(f" Data Size: {fxp_header.data_size}")
print(f" FX Magic: {fxp_header.fx_magic.decode('ascii')}")
print(f" Version: {fxp_header.version}")
print(f" Plugin ID: {fxp_header.plugin_id} ({plugin_id_str})")
print(f" Plugin Version: {fxp_header.plugin_version}")
print(f" Number of Programs: {fxp_header.programs_count}")
print(f" Program Name: {program_name_str}")
print(f" Chunk Size: {fxp_header.chunk_size}")
meta = SimpleNamespace(
file_size=file_size,
expected_header_size=expected_header_size,
header_data_size=header_data_size,
estimated_chunk_size=estimated_chunk_size,
program_name_str=program_name_str,
plugin_id_str=plugin_id_str,
)
data = SimpleNamespace(
raw_header_data=header_data,
raw_chunk_data=chunk_data,
)
return SimpleNamespace(
meta=meta,
header=fxp_header,
data=data,
)
def parse_and_print_multiple_data(binary_data, data_segments, should_decode=False):
"""
Parse multiple parts of binary data using specified struct formats and print each with a label.
Parameters:
binary_data (bytes): The binary data to parse.
data_segments (list of tuples): A list where each tuple contains:
(label: str, offset: int, struct_format: str)
Returns:
None
"""
print("Known Chunk Contents:")
for label, offset, struct_format in data_segments:
# Calculate the size of the struct to unpack
size = struct.calcsize(struct_format)
# Extract the relevant slice from the binary data
data_slice = binary_data[offset:offset + size]
# Ensure there is enough data to unpack
if len(data_slice) != size:
print(f"Error: Not enough data for '{label}' at offset {offset}. Expected {size} bytes, got {len(data_slice)} bytes.")
continue
# Unpack the data according to the struct format
parsed_data = struct.unpack(struct_format, data_slice)
# Since single field is processed, assume there's only one element in parsed_data
parsed_data = parsed_data[0]
# Decode byte strings to UTF-8 strings, if applicable
if should_decode and isinstance(parsed_data, bytes):
try:
parsed_data = parsed_data.decode('utf-8').rstrip('\x00') # Decode and strip null characters
except UnicodeDecodeError:
parsed_data = repr(parsed_data) # Show raw bytes if not decodable
# Print the result with the label
print(f" [0x{offset:x} ({offset}), {struct_format}] {label}: {parsed_data}")
def main():
parser = argparse.ArgumentParser(description='Process .fxp files to extract and decompress opaque data')
parser.add_argument('filename', type=str, help='The .fxp file to process')
parser.add_argument('--force', action='store_true', help='Overwrite existing files without prompting')
parser.add_argument('--decode', action='store_true', help='Whether extracted byte arrays should be decoded as strings')
args = parser.parse_args()
data_output_file = f"{args.filename}_opaque"
decompressed_data_output_file = f"{args.filename}_opaque_decompressed"
with open(args.filename, 'rb') as f:
fxp_data = read_fxp_header(f)
# Attempt to decompress the data
try:
decompressed_data = zlib.decompress(fxp_data.data.raw_chunk_data)
except zlib.error as e:
print(f"Failed to decompress: {e}")
parse_and_print_multiple_data(decompressed_data, data_segments, should_decode=args.decode)
# Check if output files exist and handle according to --force flag
existing_files = []
if os.path.exists(data_output_file):
existing_files.append(data_output_file)
if os.path.exists(decompressed_data_output_file):
existing_files.append(decompressed_data_output_file)
if existing_files:
if not args.force:
raise FileExistsError(f"Output file(s) already exist and cannot be overwritten without using --force: {', '.join(existing_files)}")
else:
for file in existing_files:
print(f"Warning: {file} already exists and will be overwritten.")
# Save the opaque data to a file
with open(data_output_file, 'wb') as out_f:
out_f.write(fxp_data.data.raw_chunk_data)
print(f"Opaque data saved to {data_output_file}")
# Save the decompressed opaque data to a file
with open(decompressed_data_output_file, 'wb') as out_f:
out_f.write(decompressed_data)
print(f"Decompressed opaque data saved to {decompressed_data_output_file}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment