New plugin: PianoRes, imitating "damper resonance" for sampled pianos

I implemented my first JUCE project, an audio/MIDI plugin that imitates the resonance of piano strings when the damper is down, causing all the strings to resonate. It’s a pretty simple idea, but I couldn’t find one so I made one: GitHub - jlearman/PianoRes: Resonance plugin for sampled pianos · GitHub . Ideally you’d just plug it in downstream of a sample player like Sforzando or Sfizz, but unfortunately they don’t pass the MIDI, so some host plumbing is required. (I’ll be filing a feature request for sfizz.)

It’s still pretty rough; the UI needs work. I started with an existing simple resonance plugin (GitHub - etosphere/coneko: Coneko (con-echo), a convolution reverb plugin in JUCE. ฅ(^・ω・^ฅ) · GitHub), stripped out the features I didn’t want, and added control from sustain pedal.

JUCE rocks! I’m amazed that I was able to create this in about two days.

Please take a look and LMK what you think. Any feedback would be greatly appreciated!

FYI, my plugin is now released, alpha version for Windows VST3 only. If anyone’s interested in trying it, you can get it at Release Alpha release, win vst3 only · jlearman/PianoRes · GitHub .

The default IR file is for Accurate Salamander Grand 62.beta2, available here: Request Rejected . I use the live/flat version. IMHO, it really makes a great piano even more fun to play. The controls are set up so it’s easy to compare with or without the effect, or even to hear just the effect.

It doesn’t save/restore settings yet and there are a few other issues.

The built-in/default IR file is a short one for Accurate Salamander Grand (about 4 seconds.) It works better with the longer (10 second) IR file, which is included in the release. I was worried about the CPU usage, especially for my eventual target of Zynthian, and thus making the short one the default.

I’d appreciate any feedback!

1 Like

Beta release: Load/Save is now implemented.

Release v0.2.0 Beta: load/save added, win vst3 only · jlearman/PianoRes · GitHub

If CPU usage for longer impulse responses is a concern (which it should be when using JUCE’s convolution) I would look for a different library to do this part of the processing.

This one is a pretty decent solution with a (slightly outdated) JUCE example: GitHub - HiFi-LoFi/KlangFalter: Convolution audio plugin (e.g. for usage as convolution reverb) · GitHub

I think the logic of how the MIDI interacts with the processing could do with some work, but I see a lot of “To Do” notes in there, so maybe those will help.

I also agree with your note to replace the hard reset of the convolution with each pedal press. Perhaps there’s a solution by having the convolution process silence when the pedal is up, and then process the input when the pedal is down (essentially the pedal would control an audio gate on the input signal)? Of course this would need some smoothing as well. Just a thought.

1 Like

PianoRes is now supported on Zynthian (same release link as above.)

See README at GitHub - jlearman/PianoRes: Resonance plugin for sampled pianos · GitHub for usage details.

Thanks! I’ll look into that. On my Windows laptop, the CPU usage is marginal. My worries were based on running the debug version, but with the release version it was fine.

On Zynthian, the CPU usage is low, but I need to configure 256-byte buffers and 3 buffers to avoid constant overruns. Thanks for the tip! I’ll look into that and maybe it’ll run better on the Raspberry Pi.

That’s actually how it works now, except it has to keep processing until the ADSR expires. The problem is leftover sound from when the pedal was down earlier, still processing through the convolution, and the ADSR opens up to the very short attack phase.

I think the solution is to keep a pair of convolvers, each with its own ADSR. One is active, one is standby. Whenever the pedal goes down, switch to the standby and reset the new current one. No input goes to the standby, but its output continues to be processed.

One problem is that it would increase CPU, which is already an issue on Zynthian (Raspberry Pi.) I can’t just stop processing the standby convolver, as it could be in its ADSR release phase. (This is the only time we get the glitch, because it drops to zero from nonzero on reset.)

The CPU penalty could be minimized a bit by stopping processing the standby when it’s no longer in the release phase.

But I probably have a few mistakes above. Re-pedaling is tricky. I suspect the application of ADSRs isn’t correct as described above. Maybe rather than reset as described, I attach a fast release (separate ADSR) and when that expires reset the (standby) convolution and stop processing it. No doubt that could get messed up with rapid re-pedaling too, in which case the theoretically ideal solution might be to have as many convolvers as are needed, but that’s probably not practical.

I don’t plan to make pedaling sample-accurate. I think per-buffer is plenty good enough. I’d appreciate any input on what you think should be improved otherwise.

BTW, some code on Zynthian was still debug mode. (The Projucer’s makefile clean doesn’t work well at all, but it’s easily fixed by deleting the build folder, and in some cases, other build artifacts.) It now runs well on a Pi5 with two 256-byte buffers. I’ll be looking into the convolver you mentioned, though, since the default is two 128-byte buffers at 48000 samples per second and I’d like to avoid overruns with the default settings. Little hope on Pi4, I suspect.