Since the OP-1 is using the APPL AIFF chunk we have to figure out how to read the data out of it. Thankfully it seems that the OP-1 is writing a contiguous blob of JSON within this chunk. In a hex editor you will see the following (whether or not you're looking at a drum patch or a synth patch)

If you load your patches into an app like Hex Fiend this is what you'll see.

If you load your patches into an app like Hex Fiend this is what you'll see.

When we read the first 4 bytes (after the APPL) we'll get a big endian int of the remaining size of the chunk. This will pull out the following string:

op-1{"adsr":[8768,16320,10240,4160,8192,8896,4000,4000],"fx_active":true,"fx_params":[8000,10624,8328,10168,0,0,0,0],"fx_type":"delay","knobs":[5576,0,32767,32767,23255,0,0,15743],"lfo_active":true,"lfo_params":[4912,8265,2000,2000,0,0,0,0],"lfo_type":"element","name":"20181230_0340","octave":2,"synth_version":2,"type":"dsynth"}

So at this point we can check the first 4 bytes of this string to ensure they start with op-1 and if so, strip them off, trim any control characters that might be present on the end of the string, and send it into any standard JSON parser.

Synth Header Format

{
	"adsr": [8768, 16320, 10240, 4160, 8192, 8896, 4000, 4000],
	"fx_active": true,
	"fx_params": [8000, 10624, 8328, 10168, 0, 0, 0, 0],
	"fx_type": "delay",
	"knobs": [5576, 0, 32767, 32767, 23255, 0, 0, 15743],
	"lfo_active": true,
	"lfo_params": [4912, 8265, 2000, 2000, 0, 0, 0, 0],
	"lfo_type": "element",
	"name": "20181230_0340",
	"octave": 2,
	"synth_version": 2,
	"type": "dsynth"
}

Synth JSON Values

Drum Header Format

To the right is a sample drum header pulled out of a file made with the OP-1 Drum Utility.

I've tried to break out the data type and calculation formula for each of these values where I could figure things out.

Some are still a mystery that may have to be deduced through trial and error.

{
	"drum_version": 1,
	"type": "drum",
	"name": "user",
	"octave": 0,
	"pitch": [6144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	"start": [0, 35186754, 73270908, 193926863, 262863847, 282963028, 327734734, 374604417, 422374972, 456892160, 477153660, 548131809, 570661720, 597144106, 696446963, 726788489, 830413096, 918041142, 955370511, 1001935845, 1053265249, 1053265249, 1053265249, 1053265249],
	"end": [35182696, 73266850, 193922805, 262859789, 282958970, 327730676, 374600359, 422370914, 456888102, 477149602, 548127751, 570657662, 597140048, 696442905, 726784431, 830409038, 918037084, 955366453, 1001931787, 1053261191, 1153253906, 1153253906, 1153253906, 1153253906],
	"playmode": [8192, 16384, 8192, 8192, 8192, 8000, 8192, 8192, 16384, 8000, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192],
	"reverse": [8192, 16384, 8192, 8192, 8192, 16384, 8192, 8192, 8192, 8192, 16384, 8192, 8192, 8192, 8192, 8192, 8192, 16384, 8192, 8192, 8192, 8192, 8192, 8192],
	"volume": [9195, 8192, 5190, 8192, 8192, 4969, 8192, 8192, 16384, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192],
	"dyna_env": [0, 8192, 0, 8192, 0, 0, 0, 0],
	"fx_active": false,
	"fx_type": "delay",
	"fx_params": [8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000],
	"lfo_active": false,
	"lfo_type": "tremolo",
	"lfo_params": [16000, 16000, 16000, 16000, 0, 0, 0, 0]
}

Drum JSON Values

Debugging

If you want to debug an AIFF file to see these chunks for yourself, I've documented this script that I used to start digging into these here as a Swift script that could easily be pulled into a project or something if you wanted to have some more fun.