@Christoph-Hart Nah, I did look at it among some other ones and settled on hermes before rolling my own. embedding use-cases like that sound very useful though
Posts
-
RE: My setup for building HISE plugins with AI (YMMV)posted in AI discussion
-
RE: My setup for building HISE plugins with AI (YMMV)posted in AI discussion
@dannytaurus great writeup :)
I can't share the source for the harness because it contains a web-exploitation module & toolkit I use for bug-bounties and could very easily be used inappropriately / illegally if a bad actor got hold of it.
In general it's a simple harness written in Python using the
textualpackage for the UI. It contains all of the standard tools likeread_file,write_file,run_commandetc, plus some extra goodies:Git Tools
Includes things like
diffandstatusto verify the code it wrote, as well asresetin case it breaks something. It can't commit or push or otherwise modify the repo directly.Browser
It includes the
camofoxbrowser, which uses various techniques to bypass turnstiles / captchas and bot-detection. It's not 100% successful but it's able to consistently browse sites like reddit, run web-searches etc.ComfyUI
The harness contains additional custom tools for controlling a local ComfyUI instance directly, so I can have the harness create images, videos, edit things etc. Probably one of my favourite features as I get access to a variety of local models for product images, videos etc. I've been using it to make ad creatives for meta.
Ponytail
It leverages the popular
ponytailskill in the system prompt, basically a checklist to help improve the quality and consistency of the code:Before adding code, walk this ladder and stop at the first solution that fully holds: 1. Does this need to exist? Do not build speculative work. 2. Does the standard library already solve it? Use that. 3. Does the platform or framework solve it natively? Use that. 4. Does an already-installed dependency solve it cleanly? Reuse it before adding machinery. 5. What is the smallest readable implementation that fits the codebase?And later:
## Editing Files Make file changes with `write_file` — it creates or overwrites in a single call, so there is no separate "create" step, and parent directories are created automatically. Prefer `write_file` over shell redirection for anything that creates or replaces a file. For surgical edits to an existing file, use a Python script via `run_command`: read the file, transform the text, write it back — preserving the file's existing line endings (e.g. CRLF). Read the file before editing it; never write blind.This combination of Ponytail and surgical Python edits noticeably improved the quality and consistency of the code.
Verification
The system prompt includes things like:
Verify your changes work, but scale the verification to the size of the change — verification should never become the bottleneck of a session. - Small, localized fixes: run the smallest check that exercises the changed behaviour — compile the affected target, run a single filtered test, or do a quick manual check. Do not run the full test suite or a full rebuild for a small fix. - Major fixes, rewrites, and new features: run the full build and relevant test suite. This is the only case that justifies building a broader verification harness. - Prefer the project's existing test/lint/build commands. Do not build verification harnesses (new tools, pipelines, or persistent test files) unless the change is major, a rewrite, or a new feature.This sort of pessimistic critic-gating is a combination of GAN-style adversarial gating, and some of the stuff in
hermes-agent.Deepseek Harness
I (the agent) also ripped some of the guts out of DSH: https://github.com/deepseek-ai/deepseek-harness to improve the cache hit rate and context compression (doesn't work 100% but I haven't bothered to go in and fix it yet).
Models
It's hardcoded to run Deepseek Flash via API, which costs cents on the dollar at 80-90% of the quality of the "western" models. For my personal uses it has outperformed basically everything else, including Gemini.
It can also use Ollama, either locally or one of their cloud models. As well as strata: https://github.com/niko1221/strata
Unfortunately my PC is not amazing for local models, 12gb VRAM and 32gb system RAM can only just run strata with nothing else open, the instant I open a web-browser or anything it OOMs.
Security / Safety
The harness is initialized by
cd'ing to a directory and launching it. Only the read tools work on files outside of that directory (and sub-directories), if the agent tries to write files or do anything sketchy to anything outside the workspace - it gets blocked.Example Project
I'm noodling at a harmonic + stochastic model trying to recreate my sample libraries without any actual samples. I put some of the original samples in the workspace and asked it to do some web-research, write up a plan for whichever method it thinks is the best and start working on the model.
It researched things like DDSP and Loris, wrote up a plan and used Python to continuously analyze the generated synthetic output against the original samples until it was happy. It took 1-2 extra rounds but it was able to accurately recreate my guitar harmonics instrument as a synth with infinite round-robins and an extended keyrange, all for just 100kb of data (no torch / DDSP used, it just researched it to understand the harmonic + stochastic decomposition).
I think the main takeaways are:
- Secure the harness to prevent external writes
- Be intentional with tooling, too few restricts the agent, too many tools confuses it.
- Iterate on the system prompt so the agent understands the available tools and how to use them
- Test it on real work and incrementally improve it to fit your specific use-cases
-
RE: W̶h̶e̶r̶e̶'̶s̶ ̶C̶h̶r̶i̶s̶t̶o̶p̶h̶?̶ We found him and now we talk about AIposted in General Questions
@dannytaurus said in
Where's Christoph?We found him and now we talk about AI:Have you tried headroom with your setup? Might make it even cheaper. Or have you got that kind of functionality built in?
I haven't seen headroom before but some of it is already in the harness. Output tokens are really the ones to watch out for, overly verbose replies or doom-spiraling can bump up the price. That being said I do need to sort out the context compaction, it fails sometimes which means the full chat history gets sent to the model and that can cost a bit more.
-
RE: W̶h̶e̶r̶e̶'̶s̶ ̶C̶h̶r̶i̶s̶t̶o̶p̶h̶?̶ We found him and now we talk about AIposted in General Questions
@dannytaurus said in
Where's Christoph?We found him and now we talk about AI:Is that a subscription or API calls?
API, I also have strata running the Qwen flash 110b locally but my system is the "bare minimum" so it's not super reliable.
The Chinese models are all distilled from Claude / GPT anyway, they just focus more on optimization via KV cache tweaks or attention trickery, hence why they're so cheap. Deepseek recently published their entire inference engine for running models at scale, and I think the Kimi team posted the full training run of their latest model, including the costs which is pretty cool.
I've also been training a tiny (<10m param) dual-mamba model designed to fetch information at runtime instead of storing it in the weights, getting it to form coherent sentences for the first time was cool to see :D
-
RE: W̶h̶e̶r̶e̶'̶s̶ ̶C̶h̶r̶i̶s̶t̶o̶p̶h̶?̶ We found him and now we talk about AIposted in General Questions
It's very bittersweet: on the one hand I love the current technological renaissance we're in, on the other I feel bad about ditching HISE since it's where I first cut my teeth learning to code, and Christoph has obviously put years of his life into it (as well as answering my dumb as shit questions on the forum).
As for the LLM part of the discussion - the harness is 80-90% of the output quality, I "vibe-coded" my own harness (I'm sick of that term at this point) that has my C++ syntax force-loaded as a skill, as well as a working (bot-detection avoiding) web browser and other goodies. I use Deepseek Flash and the combination works as well or better than any standard Claude / Codex setups at 1/100th the price. It also uses
grill-with-docsandponytailliberally, two of the most popular coding skills - in fact my harness doesn't even have "editing" tools, it just writes python files and executes them to modify code, which works WAY better (at least for my setup).Last thing I'll touch on is the idea of breaking things into reasonable chunks, the more tasks you give the model, the less effort it spends on each (I guess that's where subagents come in but I haven't needed to use them at all yet). A small list or one large feature per prompt / run, and make sure the agent cleans up after itself (diff checks, delete temp scripts etc).

Caveat in case someone thinks I'm stealing their .ch1 files with my "ch1 extractor" - I'm building out an MVP to see if I can convert my existing sample libraries into a synth and I can't be bothered downloading the original sample files lol
-
RE: Payment providers comparedposted in General Questions
Just throwing my 2c in - I've just moved from Payhip to a more dedicated stack (Github Pages + Cloudflare for frontend, Polar as MoR / processor).
I've had a positive experience so far, very easy to setup and the API lets me run sales by just pushing an update to a config.json file - the Github actions & Cloudflare workers take it from there. They use Stripe for payment processing so it's pretty straightforward.
Payhip was a great alternative to Gumroad, but over time I found their load speeds were getting slower and slower. I'm not sure what the reason is, but I had page loads of up to 20 seconds (simple home pages, it wasn't a content issue). This included checkout and was likely inflating bounce rates like crazy. They also have limited metrics / analytics, and my entire site was basically HTML injected so I didn't need the page editor / designer tools.
Now everything is hosted on Cloudflare and I get sub 1s page loads, the Polar checkout is just an iframe.
When it comes to Trustpilot reviews - be aware that a lot of people try and use Polar, Payhip etc to sell lazy, low-effort products like e-books, .pdfs etc. They then promptly get banned from the platforms and then leavy a crybaby negative review saying they got scammed.
This was a very recent move, so I haven't completed a payout yet through Polar, but I've been in contact with their support (had to verify my ID and the Stripe ID checker wasn't working on my old ass Australian ID card) - they replied within 48 hours both times and the communication was crystal clear.
@dannytaurus said in Payment providers compared:
- Whether Polar charge their 50¢ on a free ($0) download. None of them says. If you give away a lot of free products, ask first.
I've had a few hundred free product downloads over the last week or so - no fees from what I can tell. There's not even a payment form for free products or 100% discount codes: free is free.
The one sort of "downside" I guess is there's only checkout embeds, no cart / add-to-cart (you'd have to roll your own). And no Paypal from what I can tell, I'm not sure how big of a deal that is - Amazon doesn't use Paypal.
If I do come across any negative experience I'll update this post, but so far Polar has been great all around. I've just requested my first payout (only $50) and their docs say they can take up to 2 weeks which isn't a big deal really. Larger payouts might take longer.
-
RE: NeuralNetwork.loadNAMModel() functional?posted in General Questions
@resonant iirc NAM files are just large JSON objects which can be embedded in the final plugin easily
test it yourself, rename a NAM file to .json and open it in something like Sublime Text
-
RE: NeuralNetwork.loadNAMModel() functional?posted in General Questions
@resonant Nope, I vibe coded a manual NAM wrapper for Altar:
https://github.com/nytemairqt/altar/blob/main/DspNetworks/ThirdParty/amp.h
-
RE: Agentic coding workflowsposted in AI discussion
This was all a big surprise to wake up to.
Altar had quite a bit of vibe-coding involved, specifically on the modular drag-n-drop FX panels, and some of the third-party DSP nodes. I used various models available on Github Copilot (mostly Claude) because it seems to handle multiple files / larger context window better than the standalone models.
That being said, it still required quite a bit of manual fixing up. A common one mentioned above was using var instead of local with inline functions etc, and it would default to using JUCE buffers instead of the templated SNEX methods which I assume comes with a performance hit.
I think a good idea would be to establish some sort of global guiding prompt which includes some of the most important best practices for HISE and appending that to individual case-specific prompts eg:
"Use this
bestPractices.mdto familiarize yourself with the HISE codebase, remember to make use of the existing templated functions in the auto-generated files and only use JUCE methods as a fallback" etc etc -
RE: (ScriptNode) Smeary Reverb / Washy Cymbals?posted in ScriptNode
@Christoph-Hart said in (ScriptNode) Smeary Reverb / Washy Cymbals?:
@iamlamprey haha everybody always rips out the dither stuff from air windows :)
i assume he has it there for a reason but most DAWs apply dithering now anyway and I can't hear a difference lol
-
RE: (ScriptNode) Smeary Reverb / Washy Cymbals?posted in ScriptNode
Okie, here's the wrapper if anyone else needs it:
// ==================================| Third Party Node Template |================================== #pragma once #include <JuceHeader.h> namespace project { using namespace juce; using namespace hise; using namespace scriptnode; // ==========================| The node class with all required callbacks |========================== template <int NV> struct phaseNudge: public data::base { // Metadata Definitions ------------------------------------------------------------------------ SNEX_NODE(phaseNudge); struct MetadataClass { SN_NODE_ID("phaseNudge"); }; static constexpr bool isModNode() { return false; }; static constexpr bool isPolyphonic() { return NV > 1; }; static constexpr bool hasTail() { return false; }; static constexpr bool isSuspendedOnSilence() { return false; }; static constexpr int getFixChannelAmount() { return 2; }; static constexpr int NumTables = 0; static constexpr int NumSliderPacks = 0; static constexpr int NumAudioFiles = 0; static constexpr int NumFilters = 0; static constexpr int NumDisplayBuffers = 0; void prepare(PrepareSpecs specs) { } void reset() { } void handleHiseEvent(HiseEvent& e) { (void)e; } double dL[1503]; double dR[1503]; int one = 1; int maxdelay = 9001; double A = 0.0; double B = 1.0; uint32_t fpdL; uint32_t fpdR; int allpasstemp; double outallpass = 0.618033988749894848204586; int maxdelayTarget = (int)(pow(A,3)*1501.0); double wet = B; double bridgerectifier; double inputSampleL; double inputSampleR; double drySampleL; double drySampleR; template <typename T> void process(T& data) { const int numSamples = data.getNumSamples(); const int numChannels = jmin(2, (int)data.getNumChannels()); maxdelayTarget = (int)(pow(A, 3) * 1501.0); wet = B; dyn<float> chL, chR; int idx = 0; for (auto ch : data) { if (idx == 0) chL = data.toChannelData(ch); else if (idx == 1) chR = data.toChannelData(ch); ++idx; } if (numChannels == 1) chR = chL; for (int s = 0; s < numSamples; ++s) { double dryL = chL[s]; double dryR = numChannels > 1 ? chR[s] : dryL; double xL = chL[s]; double xR = numChannels > 1 ? chR[s] : xL; // might add dithering later // bridge rectifier xL /= 4.0; xR /= 4.0; double br = std::fabs(xL); br = std::sin(br); if (xL > 0) xL = br; else xL = -br; br = std::fabs(xR); br = std::sin(br); if (xR > 0) xR = br; else xR = -br; // allpass if (std::fabs(maxdelay - maxdelayTarget) > 1500) maxdelay = maxdelayTarget; if (maxdelay < maxdelayTarget) { maxdelay++; dL[maxdelay] = (dL[0] + dL[maxdelay-1]) / 2.0; dR[maxdelay] = (dR[0] + dR[maxdelay-1]) / 2.0; } if (maxdelay > maxdelayTarget) { maxdelay--; dL[maxdelay] = (dL[0] + dL[maxdelay]) / 2.0; dR[maxdelay] = (dR[0] + dR[maxdelay]) / 2.0; } allpasstemp = one - 1; if (allpasstemp < 0 || allpasstemp > maxdelay) allpasstemp = maxdelay; xL -= dL[allpasstemp] * outallpass; xR -= dR[allpasstemp] * outallpass; dL[one] = xL; dR[one] = xR; xL *= outallpass; xR *= outallpass; one--; if (one < 0 || one > maxdelay) { one = maxdelay; } xL += (dL[one]); xR += (dR[one]); // second bridge rectifier stage br = std::fabs(xL); br = 1.0 - std::cos(br); if (xL > 0) xL -= br; else xL += br; br = std::fabs(xR); br = 1.0 - std::cos(br); if (xR > 0) xR -= br; else xR += br; xL *= 4.0; xR *= 4.0; // apply dry / wet if (wet < 1.0) { xL = (dryL * (1.0 - wet)) + (xL * wet); xR = (dryR * (1.0 - wet)) + (xR * wet); } // apply dither goes here // write back to channelData chL[s] = xL; chR[s] = xR; } } template <typename T> void processFrame(T& data) { } int handleModulation(double& value) { return 0; } void setExternalData(const ExternalData& data, int index) { } template <int P> void setParameter(double v) { switch (P) { case 0: { A = v; break; } case 1: { B = v; break; } } } void createParameters(ParameterDataList& data) { { parameter::data p("PhaseNudge", { 0.0, 1.0 }); registerCallback<0>(p); p.setDefaultValue(0.5); data.add(std::move(p)); } { parameter::data p("Dry/Wet", { 0.0, 1.0 }); registerCallback<1>(p); p.setDefaultValue(0.5); data.add(std::move(p)); } } }; // end struct } // end namespaceIt's missing the dithering stuff, but it sounds basically identical to the original implementation, just make sure to set up the third party node using the template and call it "phaseNudge.h"
-
RE: (ScriptNode) Smeary Reverb / Washy Cymbals?posted in ScriptNode
@Lindon That's a good idea, I'll keep it in the back pocket for now because I want to keep everything in scriptnode but if I can't figure it out I'll make a wrapper
-
RE: (ScriptNode) Smeary Reverb / Washy Cymbals?posted in ScriptNode
@Lindon Yep that's the one I'm following :)
he's using an airwindows plugin for the allpass but the HISE allpass node sounds nothing like that, not sure how all the coefficient stuff works
I ended up going a harmonic + stochastic approach which is showings its obvious limitations
-
(ScriptNode) Smeary Reverb / Washy Cymbals?posted in ScriptNode
I'm noodling at physically modeled drums, specifically cymbals and I need an efficient way to "smear" the excitation impulse
I know the typical route is to use allpass filters in the delay line, but I find I have to use a
math.mulat 0.5 just to keep the audio from blowing up.I currently have 5 delays with different fractional delay times and I'm also passing a long noise tail into it but it just sounds like a noisy sawtooth buzz rather than a nice chorusy wash.
Not sure how to proceed towards that metallic ringing without overloading the delay lines or the CPU
-
RE: Checking the HISE Source with AI?posted in General Questions
HISE is a big codebase with a variety of dependencies, I think the risk of hallucination & context-rot is a lot bigger than your average JUCE plugin.
There's also a lot of templated functions, specific versions of things like JUCE and the C++ version HISE uses which LLMs usually don't "keep in mind".
Also GLM4.7 has noticeably outperformed Claude & GPT 5.2, at least in my own tests

I'm sure Christoph uses some of these tools occasionally, but I think if he started depending on them for the short-term benefit we'd probably end up with a lot more bugs in the long term
-
RE: Apple is ridiculousposted in General Questions
@David-Healey said in Apple is ridiculous:
Usually below that text you quoted there is a tiny link that says something like Continue on Web.
yeh there's nothing, I've clicked every link on the page, I even tried signing out and clicking Subscribe and logging back in and it just flops
I've opened a ticket but I assume the answer will be "use our 1.5 stars app"
-
Apple is ridiculousposted in General Questions
I'm trying to renew my apple developer subscription, instead of a "Renew" button, I'm greeted with this:

I can't download the app from the app store (VM is using an older version of MacOS), and every support article, web link, even the emails they sent me with manual renew links, all just go straight back to the main account home page.
Has anyone had to deal with this crap recently and found a solution? All of my other devices are PC so I can't download the Developer app at all
-
RE: Building a replication of a piece of gear I have (.NAM)posted in General Questions
@Orvillain I believe David made one into a pull request, one was from the forum (I think it was also David's, so it's probably a PR as well). the others were specific to the Rubberband library, but I'm no longer using it in Altar anyway, they were just namespace conflicts with
using namespace juce -
RE: Building a replication of a piece of gear I have (.NAM)posted in General Questions
@cemeterychips You can clone/download it or just copy the stuff you need from the amp.h file, you'll also have to get the dependencies like RTNeural and RTNeural-NAM
If you don't know C++ concepts like pointers and classes/structs then it will be quite a struggle, and you'll also need to connect the NAM stuff to the interface if you want to dynamically load/swap models at runtime.
Also I highly recommend David's course if you're new to HISE, before jumping into any C++ stuff: