Considering building a Mac companion app for Tonverk (card overview, health check, verified backups)

I own a Tonverk and I build small Mac apps for musicians on the side (It’s mono, yo! and It’s 404, yo!, both for sample prep). After a few months with the Tonverk my SD card is already getting away from me, and reading the SD card folders and filetypes thread here, it seems I’m not the only one.

A few things I keep bumping into. Files that aren’t 48 kHz load fine but play back with degraded quality, and nothing warns you. Presets store absolute paths, so reorganizing folders can quietly break them. Deleting or moving a sample breaks every project that referenced it, with no warning, which makes cleaning up feel like defusing a bomb. And backup is a manual Finder copy in USB disk mode, with no way to know the copy is complete and intact.

So I’m considering building a native Mac companion app for exactly this. It would scan the card and give you a browsable library of everything on it, with waveforms and the technical details that matter (sample rate, bit depth, mono or stereo, length). It would run a health check that flags the problems above in plain language. It would find duplicates, but never delete anything on the card itself, instead moving files to a quarantine folder on the Mac so it’s always reversible. And it would make verified, versioned backups instead of hope-for-the-best folder copies.

It would deliberately not touch projects, patterns or parameter locks. The project format is Elektron’s own and changes with OS updates, so this would be a companion, not an editor.

Before I build it I want to know whether this is a real problem or just my own tidiness anxiety. What do you actually do today to keep your card under control and backed up? And is there something about managing the card that annoys you more than the things I listed? Curious what you think.

15 Likes

good idea!
a pattern manager would be dope (chatGPT told me it’s possible to reorder them by creating a software, but i’m to afraid of bricking my TV by trying this…)

I can see checking drum and multi files is achievable but if I make patterns : projects and don’t save presets / instruments then it’s still impossible to audit loaded samples to check if they can be deleted .
Plus , if I used an lfo to play a range of samples then you can’t extract that data ( I think similar edge cases are dealt with in elkherd for digitakt )

So … start making a tool you’ll find useful and it’s likely others may too , but I suspect it’ll only be able to check easily read formats that are documented …
But tidying those up … moving samples and updating paths / file names could be handy .

Historically these tools have been made by the community , elektron focus on overbridge ( audio streaming , patch editing and management ) … nothing to do with pattern / sequence / step editing / project etc . Elkherd is the main one I’m familiar with ( others exist )
I think he’s had some support from elektron so perhaps if your tool develops you could approach them in some way .

Thanks! A pattern manager is the one thing I’ve deliberately ruled out. The pattern and project format is Elektron’s own, it changes with OS updates, and writing to it from the outside is exactly how you end up in the bricking scenario you describe. So the app stays read-only on everything Elektron-formatted. It looks after samples, folders and backups, and never writes a byte of project data. Safe pattern reordering really needs to come from Elektron themselves.

3 Likes

I think the functionality of helping with projects where samples can no longer be found would be most welcome, and wouldn’t need to write to anything.

1 Like

Go for it!

There’s a similar tool for OP-XY. Even though it was just released recently, I can’t live without it anymore. It’s awesome.

Similar to Tonverk, the OP-XY also suffers from absolute paths to folders and samples and doesn’t tell you which samples are missing or broken.

The OP-XY tool doesn’t just fix broken assignments automatically—it also bundles all the elements of a project into a handy zip file and provides some interesting statistics, such as the memory requirements of projects, which presets are used in which projects, which samples used the most and much more.

Check it out. I think it could be a great blue print for your own project.

https://opxy.app/

You’re describing exactly the line I’ve drawn, and honestly better than I did. Reliably auditing which samples are in use isn’t possible from the outside (unsaved presets, LFO-swept sample ranges, all of it), so the app doesn’t pretend to. That’s why the duplicate handling never deletes from the card: files move to a quarantine folder on the Mac, checksum-verified, so if a project turns out to miss something, putting it back is trivial.

The move-samples-and-update-paths idea is a good one. It would mean rewriting paths inside preset files, which is the one place I’d tread very carefully since that format isn’t mine. If it ever happens it would be strictly opt-in and behind a verified backup.

Thanks for the Elkherd pointer, I didn’t know about the Elektron support angle. And yes, that’s the plan: I already have a working prototype of the scanner, health check and verified backup running against my own card, so I’m building the tool I need first and we’ll see who else finds it useful.

That one is already on the list, and you’re right that it doesn’t need to write anything. Presets store their sample references as plain absolute paths, so the health check can read those and flag references that point at nothing. The honest caveat: it can only check what’s actually saved to the card, so it will report the breakages it can prove and stay quiet about what it can’t see, rather than pretending to be a complete audit.

Thanks, I didn’t know opxy.app, and the parallels are striking. Same disease, different sampler: absolute paths and samples going missing in silence. The read-only indexing approach is very close to what I’m building, and it helps that the OP-XY community has open format documentation to lean on. Where I’ll stay more careful is anything that fixes files automatically, since that means writing into preset formats that aren’t mine. If that ever comes it will be opt-in and behind a verified backup. Studying it properly, good pointer.

Small update, and thanks again for the thoughts earlier in the thread, they genuinely shaped this.

It has a name now, TonVault, and a page at tonvault.iamjarl.com. There isn’t much to see there yet beyond what it does and a box to leave your email, but the engine is real and already running against my own card. It scans the card, shows every sample with a waveform and the details that matter, runs the health check we talked about, and makes verified, versioned backups.

A couple of things from this thread went straight into the design. The duplicate handling never deletes anything on the card, it moves files to a quarantine folder on the Mac so anything can be put back, which felt like the only safe answer to the missing-samples problem re5et and I got into. And the health check flags presets that point at samples which are no longer there, the read-only version verdurin asked about, with the honest caveat that it only reports what it can actually prove.

It stays a companion, not an editor, so it never touches projects, patterns or p-locks. It will be a one-time purchase like my other apps, no subscription.

If you want to know when it ships, there’s an email box on the page, one message when it’s ready and nothing else. And if there’s something about managing the card that still bugs you, I’m still all ears.

2 Likes

TonVault is out.

Two and a half weeks ago I asked in here whether a Mac companion for the card was worth building. It is on the Mac App Store now:

It does roughly what this thread landed on. It scans the card and gives you a browsable library with a waveform and the details for every sample, runs a health check that explains in plain language what is worth fixing, finds byte identical duplicates, and makes backups that are checksum verified on both sides of the copy, so you know a backup is complete before you trust it.

@verdurin, your suggestion about spotting presets that point at samples which are no longer there is in it. That one took the longest. I ended up reading the preset files directly to work out how they store their sample references (.tvpst keeps absolute paths, .elmulti keeps a bare filename next to the preset), then validated it against about 9,200 references on an intact card with zero false positives. It only flags your own presets, since the factory ones always resolve.

@MLTPLX, there is no pattern manager, and I am not planning one. The project format is proprietary and shifts with OS updates, so anything that writes to it risks exactly the bricking you were worried about. TonVault never reads or changes projects, patterns or p-locks.

@re5et, you were right that auditing what an unsaved project references is not something I can do reliably, so I left it out rather than guess. Same reason there is no sample to project usage map yet. If that ever becomes possible to do properly, it goes in.

@krunchr, I did look at opxy.app. Same shape of problem, though I stayed more conservative about writing to files.

Nothing on the card is ever deleted. Duplicate cleanup copies files to a quarantine folder on your Mac after verifying the copy, and you can put any of them back.

It is $1.99, once. No subscription, no account, and it runs entirely on your Mac with no network calls.

One practical note. The App Store listing describes the app generically and does not name the device, because Apple requires written authorization from a hardware maker before you can use their product name in a listing. So searching the store for the device will not turn it up. The link above, or tonvault.iamjarl.com, is the way in.

Next on my list is the processing side: 48 kHz conversion, mono downmix to save project RAM, silence trim, batch rename, and a ready to copy export. If you try it and something looks off on your own card, say so here and I will fix it.

Thanks for the input. It genuinely changed what got built.

6 Likes

Quick Q - if you do a silence trim on a tonverk style auto sample ( all one wav file ) I guess you have to then update all of the start / end / loop points for every key group and velocity layer to keep them aligned ?
And it needs to ensure it’s a ‘gap’ at the end of a sample and not in the middle ? Eg if it’s spoken word sentence you wouldn’t want to trim the gaps during the sentence … only near the beginning and end ? ( perhaps this is just a weird edge case )
My main point being it’s not as easy as it might seem ?

1 Like

@re5et You’re right. Every multisample I have auto sampled on my own card is one wav with 29 key zones pointing into it, and each slot stores its start and end as frame offsets. Trim anything off the front and all 29 zones shift. Silently, until you play it.

So TonVault won’t touch it. Trimming writes a new file and leaves the original alone, so whatever a preset points at keeps working. I’m not going to patch offsets back into an undocumented format that moves with OS updates. It already resolves preset references while scanning, so it can just tell you the file belongs to a multisample.

And it only ever trims the head and tail, never gaps inside the audio. Your spoken word example is exactly why.

Good catch. Cheaper to learn now than after shipping.

1 Like

Just tried it after a week or so away from my TV.

Now using a 512GB card, and TonVault ended up using all the application memory (19.81GB on a 16Gb Mac Mini) and I ended up having to force quite everything and reboot.

Suspect part of the problem is that I’ve copied lots of sample packs on there, so there are many thousands of files.

Happy to send more details if that’s useful.

@verdurin Thank you, and sorry about the reboot. That one is on me.

I found the cause. The scanner had no autorelease pools, so everything Foundation and CoreAudio allocate while reading each file stayed alive until the whole scan finished. That means memory grew with the number of files rather than staying flat, and a 512GB card has more than enough files to run a 16GB machine out of room. Reading a WAV header also memory mapped the file, which made it worse.

It is fixed now: the per-file work, the preset parsing and the duplicate hashing each run in their own pool, so peak memory is bounded by the largest single file instead of by the card. I also capped the waveform cache, which used to grow for as long as you kept scrolling.

I have not been able to reproduce it at that scale, since my own card is 58GB, so I would rather not claim it is solved until it is measured. If you are willing: roughly how many files are on the card, and does the Samples list matter, or did it climb during the initial scan alone? That tells me whether the transient allocations were the whole story.

It will go out as soon as I can verify it properly. Thanks for reporting it with the numbers, that made it findable.

1 Like

The thing that bounds it for good is never mapping the file at all.

A header read needs the first few KB, so open the file, read that much, find the chunks you need, and close.

Mapping the whole file for a header pulls pages you never look at and the OS still charges you for them.

Same idea for the waveform previews - just keep a fixed-size summary per file in a cache with an eviction limit, never the raw audio.

@NovateAI That is exactly the shape the fix took, and it is already in the version now waiting on review.

The header parse reads a bounded prefix instead of mapping, with a chunk-count cap and an early stop when a chunk declares a size of zero, which previously made the walk advance eight bytes at a time to the end of the file. The waveform cache holds 120 peak values per file, well under a kilobyte, with an eviction limit rather than growing for as long as you scroll. I also removed the last remaining mapping today, in the preset parser.

One thing worth adding, since it surprised me: not mapping the file was not what mattered most. I measured a single malformed 300MB wav with one reader enabled at a time, and both of the system’s own audio readers allocate on the order of the declared data length rather than the real one:

AudioFileOpenURL 2405MB, AVAudioFile 2255MB, my own header parse 11MB.

So the file has to be kept away from CoreAudio entirely, not just read differently by me. The scanner now checks whether a wav’s chunk table is self-consistent and, when it is not, answers from its own parse and never opens the file with the system reader. That took the malformed file from 2405MB to 12MB, with 20,000 normal files unchanged at 41MB.

The autorelease pools were worth having but were a small part of it: 72MB to 41MB on 20,000 files. Nowhere near what @verdurin saw.

1 Like

A simple recursive directory listing of User shows 64,417 entries.

It’s at the “Checking for Duplicates” stage that reported memory usage drastically increases, very roughly 100MB every refresh on Activity Monitor.

64k files and it’s the duplicates pass, that narrows it a lot.

If the dupe check is hashing every file in full, the work scales with the card instead of with the duplicates. What saved me on big sample libraries: group by file size first. It’s free, no I/O, and most files fall out right there as unique. Then for anything that shares a size, hash just the first 100K or so, and only do a full hash when the prefixes match. Almost everything dies at the prefix.

Two gotchas from sample libraries specifically. Sampler cards have way more same-size files than normal folders: one-shots and stems exported at fixed bar lengths land on identical byte counts, so you’ll get a few fat buckets instead of none. And when you do reach the full hashes, stream them through one reused buffer instead of Data(contentsOf:). Pulling a 300MB stereo file into memory just to hash it is the same spike you killed in the scanner, back in a different spot. Pool per file there too.

At 64k entries the bookkeeping itself starts to matter - keep digests as raw bytes hanging off the file table you’ve already got, not hex strings in a dictionary of URLs. It adds up quietly.

That steady ~100MB per refresh over a long stage smells like whole-file reads grinding through one of those fat buckets. Log bucket sizes and I bet it shows up right away.

@verdurin That was a much better lead than the one I chased, and it found a mistake in my own fix.

The duplicate check hashes every file whose size matches another one, reading it a megabyte at a time. I had put the memory pool around each file rather than around each chunk, so every megabyte read stayed alive until that file finished. Hashing one large file therefore held the whole file. Two 800MB files measured 777MB peak. With the pool in the right place they peak at 14MB, and 8,000 same-size files sit at 22MB.

Your 100MB per refresh fits that exactly. It was not a leak growing without limit, it was one file being read into memory a megabyte at a time.

64,417 entries is genuinely useful, thank you. 1.1.1 is out now, but it fixes a different path: the one where a malformed wav made the system audio reader allocate for the length the file claims rather than the length it actually has. The duplicate check fix is in 1.1.2, which is in review. When it lands, that phase is the one to watch.

Backups get the same benefit, since verifying a backup hashes both sides of every copy through that same function.

@NovateAI Both of those are worth doing and neither is in there yet. Size grouping already happens, so only files whose sizes collide get hashed at all, but I hash those in full. Prefix hashing first would cut most of that: my own test card had 8,000 files of identical size, so every one of them was read end to end for nothing. And a reusable buffer is cleaner than what I did, since it removes the allocation instead of pooling it. I am building both now.

2 Likes