NAM A2 and IR Player with plate reverb

optilude

Member
For fun, I’ve made a pedal based on the excellent DaisySeedProjects 125B @kshep hardware. The code is open source here: https://github.com/optilude/AmpSim

You can load it up (at build time) with up to 128 (I think, I’ve not actually tested more than a dozen or so) either NAM A2 amp+cab captures or cabinet IR (.wav) files, which you can then easily browse using the rotary encoder. There is also a good-sounding plate reverb based on the Dattorro algorithm (I originally discovered it in the Flick – see https://github.com/joulupukki/Flick).

It took a bit of doing to make both NAM + plate reverb run on the Daisy Seed, but it seems to work well and sound good. I’ve included a few captures of my own hand-built amps (a Fender style and a Marshall style) but really https://www.tone3000.com/ is where it’s at.
 
Yes’s it’s the same reverb. The only difference is that in the Mulebox it runs at 48Khz but that was too CPU intensive alongside NAM so it runs at 24Khz here. It sounds subtly different but still good.

@xconverge - Very cool that you made the Mulebox. Would love to hear more about how that worked out!

Did you change the reverb from the upstream version?
 
Yes’s it’s the same reverb. The only difference is that in the Mulebox it runs at 48Khz but that was too CPU intensive alongside NAM so it runs at 24Khz here. It sounds subtly different but still good.

@xconverge - Very cool that you made the Mulebox. Would love to hear more about how that worked out!

Did you change the reverb from the upstream version?
Ah I didn't see you used datorro in the upstream also. My build is here https://forum.pedalpcb.com/threads/reactive-load-ir-headphone-setup.29065/ I think you may have already seen it.

Do you have any idea what sort of processing limits you are at? If you have a a screen, I check with https://docs.daisy.audio/libDaisy/classdaisy_1_1CpuLoadMeter/

On the bkshep project, last I checked, NAM is ~60% CPU, with a 1024 IR its another ~20% bringing it to 80%.

Loop unrolling lowered my CPU for the IR a LOT, so I would give it a try and you might be able to use a full sample rate reverb:

C_DEFS += -DARM_MATH_LOOPUNROLL
 
Hi,

With NAM A2 + Dattorro at 48Khz and after a bunch of optimisation, I ended up with 98% CPU. That was a bit too close for comfort.

I could not get NAM + IR + reverb (which is less of an issue, I think, since most of the NAM models are amp + cab, not amp only).

I think from memory, NAM hovered around 60-65% and Dattorro at 48Khz at 30-35%. So that's not wildly different from your estimates above.

I had Claude Opus spend quite a lot of time finding micro optimisations and this was the best we could get to. ;)

Martin
 
Hi,

With NAM A2 + Dattorro at 48Khz and after a bunch of optimisation, I ended up with 98% CPU. That was a bit too close for comfort.

I could not get NAM + IR + reverb (which is less of an issue, I think, since most of the NAM models are amp + cab, not amp only).

I think from memory, NAM hovered around 60-65% and Dattorro at 48Khz at 30-35%. So that's not wildly different from your estimates above.

I had Claude Opus spend quite a lot of time finding micro optimisations and this was the best we could get to. ;)

Martin
The loop unrolling by adding that C_DEF to your makefile should be a free performance optimization (at the cost of binary size)
 
The loop unrolling by adding that C_DEF to your makefile should be a free performance optimization (at the cost of binary size)
It will help the IR loader marginally (but that was not CPU-constrained anyway). It does nothing for the NAM code I think, which is already optimised (this was from DaisySeedProjects originally – I think maybe contributed by you :)
 
It will help the IR loader marginally (but that was not CPU-constrained anyway). It does nothing for the NAM code I think, which is already optimised (this was from DaisySeedProjects originally – I think maybe contributed by you :)
Correct, but for me it was more than marginally, and my CPU usage for the IR when using ~1024 long IRs was not marginal.
 
Correct, but for me it was more than marginally, and my CPU usage for the IR when using ~1024 long IRs was not marginal.
I was thinking about it a bit more and I realised that my limitation was basically NAM + Dattorro and I didn’t really put too much time into NAM + IR, since the NAMs I tend to use are amp+cab generally. I also have 2048-long IRs by default (from the Mulebox), which is probably unnecessary. I can see how this makes a difference if the goal is NAM + IR.
 
Ah yea, I typically play through a cabinet (or my mulebox which has the IR) so I like my NAM to be without the cabinet!

I have been eyeing the raspberry pi project to start to chain effects together without needing to worry about CPU as much, but I still just really like the 125b form factor

It would be cool if we made it a bit easier to chain effects together on the kshep project, but that just seems like a not-so-fun endeavor with the CPU limitations and user interface/experience.
 
Ah yea, I typically play through a cabinet (or my mulebox which has the IR) so I like my NAM to be without the cabinet!

I have been eyeing the raspberry pi project to start to chain effects together without needing to worry about CPU as much, but I still just really like the 125b form factor

It would be cool if we made it a bit easier to chain effects together on the kshep project, but that just seems like a not-so-fun endeavor with the CPU limitations and user interface/experience.
Yeah. When I first picked the DasiySeedProjects multi-fx up, I’d expected to pick a couple of effects to load and basically have them run in a chain with a default order. It took me a minute to realise it was “one at a time” but I could have dozens of them available in the firmware.

To be honest I actually think that’s fine. Maybe you could create some kind of “FX chain” meta-effect that you could enable and instantiate with a specific combination of effects in order? So imagine that in `loaded_effects.h` you had:

Code:
    new FxChain(“DLY+REV”, [
        new DelayModule(),
        new ReverbModule(),
    ]),

and then FxChain would process the audio through a DelayModule and then a ReverbModule. It’d have to expose settings for both and probably an “on/off” type setting for each. By giving a name (first parameter), you could have multiple FxChain instances in your effects list.

One unresolved question, is what you map the knobs to in this case. You could create some UI thing that let you page through the effects: click the encoder when on the main FxChain page, then you choose between the underlying effects (Delay, Reverb), click again and the knobs are now mapped to that effect’s parameters, click again and you go into the menu-based parameter editing screen. That would require some rewiring of the UI I think.

Another option would be for the FxChain constructor to take some extra parameters that described how to map each of the six knobs to an underlying parameter on one of the effects.

This isn’t quite a “any effects in any order set up at runtime” but it would be somewhat manageable to implement, and for any given firmware build you could test that it works and doesn’t overload the CPU (adding a small CPU meter to the bottom of the screen might come in handy here, like on the AmpSim pedal).
 
Last edited:
Yea, all good ideas, and wouldn't be hard to get it done, but something like this https://forum.pedalpcb.com/threads/nam-a2-raspberry-project.29837/ just makes too much sense to me at that point IMO, especially for the UI/UX.

Also I have more than 1 125B pedal so I just chain them PHYSICALLY :)

I think the daisy seed stuff a few years ago was incredible and had a medium learning curve to get started, but with access to LLMs and a lot of reference material, and stuff like NAM, people can certainly help themselves get exactly what they personally want (and have fun and build and learn along the way).
 
Back
Top