MiMi-d - creating a new software synth for Zynthian

I have loaded up OB-Xd with MiMi-d and the load is lighter. As you might have noticed I’ve fired up a lot of Pi3’s recently and have been distracted by this as an enterprise, and I’ve also had a clock to repair and readjust which has involved a new Thingy…


Which is an original pi model b with a distance sensor for measuring a clock pendulum position. So my only excuse is discovering that Pi3 seem, for want of a better word, a little more agile, I’ve been revising VERY early pi’s to see what I can get them to do, now that the PI software release seems considerably more mature. We’ve also just spent a fair amount of hard won money getting the clock serviced and a bit more for the problems that emerged from having the clock dissembled. The need for checking it’s accuracy over the next week has pushed its way to the front of the queue. It’s running fast by about a minute every two days so we are giving it a week to settle in and then we will start adding and removing pendulum weights. But locking a phase lock loop to the pendulum is one way of checking the results, especially when combined with a few one-wire sensors for temperature measurement. The results are transmitted as qmidinet messages as it didn’t seem sensible to invent a message protocol just for one clock in Sandbach when we could make something that will sing it’s state. I’m actually trying to make that tune melodious as it locks. . . .

I have got two pi 3s running sise by side one running obx and the other running MiMi-d but they are unplugged at the moment to allow clock development. Worry not they will return. I have been running them both monophonically to avoid clunks and bumps and I will be putting together a test sequence to exercise them similarly. I’ve not been too selective in patches used but that would seem to be beneficial research to see what can be learned.


Three pi3s waiting to be employed. The one on the right is going to end up as violin effect pedal. I tend to rotate around several projects at once but the MiMi d is running from the motor 61 as my default keyboard at the moment.

3 Likes

Yes, I was thinking along the lines of the mechanism loading the preset cross-referencing the parameters against the .ttl file, which also contains a default value for each parameter, and load the default if no corresponding parameter exists in the preset file. That way there won’t be more parameters being set than when loading a previously saved preset.

I might have a look a this. Do you know where this preset management happens?

As a workaround I realized one could have a ‘default’ patch with all parameters set to their default values, which could be loaded between patches to ‘clean the slate’ (makes me think of wine tasting events where they eat a piece of bread between tasting different wines to clean the palate).

1 Like

I was gifted with the loan of an RPi3 by a colleague of mine, so I spent part of the evening in amazement at how easy it was to run it completely headless (although for some reason I initially had problems understanding how to use the keyboard keys in the VNC UI; it works fine now), and then got into comparing the MiMi-d and OB-Xd to see if there was a significant difference.

The MiMi-d is more CPU-hungry than the OB-Xd, but I got the MiMi-d to comfortably play 5 voices (green heart) while the OB-Xd could play 6 voices under the same conditions. In this case, the plugin was using about 63% CPU as measured by top.

I had economy mode off (because then all the voices consume DSP regardless of whether their actually playing a note or the release phase has run out, so it makes CPU load measurements easier), oversampling on (or Filter_Warm as it’s called on the OB-Xd), and the OB-Xd filter set to 4 pole mode (to be comparable with the MiMi-d).

Moving to 7 voices for OB-Xd or 6 voices for MiMi-d turned the heart dark yellow, the CPU load went up to 78%, and there were occasional clicks in the audio output, coupled with the heart occasionally turning into a red warning triangle.

Oddly enough, the OB-Xd seems to have a tendency to spike the CPU load and cause clicks when the envelopes have reached the sustain phase. This didn’t seem to be the case with the MiMi-d, but instead the same occurred when the voices had passed the release phase. I’m not sure what causes this; I’ll have to give it some thought. It’s like when the synth reaches some form of steady state, it starts using bursts of CPU. EDIT: In practice, this is probably not much of a problem, as one would normally set Economy Mode to On, which causes the CPU load to drop to virtually 0 for non-playing voices. (The only reason I can think of the set Economy Mode to Off in normal use is if the preset uses the filter as an oscillator, as it takes a short while for the oscillations to build up the first time the voice is played after the resonance parameter has been brought up).

Anyway, there are two conclusions that I can draw from tonight’s exercises:

  1. The CPU load for the MiMi-d is slightly higher than the OB-Xd, so the fact that it can run one voice less than the OB-Xd would seem to be roughly in line with that.
  2. I think a lot of the OB-Xd presets have ‘Filter_Warm’ turned off, which drops the CPU load by about 50%, as it turns off oversampling; oversampling causes the synthesizer to run at twice the sample rate, plus there is an antialiasing filter employed when downsampling at the output. In contrast, in an effort to avoid nasty surprises in the form of digital artifacts when twiddling the factory presets, I’ve left oversampling on in all the presets. Perhaps I should rethink that, and turn oversampling off on those presets for which there is no appreciable difference. It’s mostly when it comes to FM and to a lesser extent VCA overdrive that oversampling provides a cleaner sound with less aliasing. But for standard VCO-VCF-VCA sounds I can’t really hear a difference (regardless of the name (Filter_Warm) of the corresponding OB-Xd parameter), so I should simply turn it off for those presets.

EDIT: A third point is to research why the CPU load spikes when the plugin is in a more idle state.

EDIT2: Another point of comparison is that on an RPi4 Zynthian, I can get about 15 voices out of the MiMI-d (needs a code change as the published code caps at 8 voices) with a yellow heart showing, which is more than twice the 6 voices obtainable on the RPi3 under the same conditions, which sets some sort of a benchmark for the difference in performance between the two platforms. I think the ARM Cortex-A72 CPU in the RPi4 has a larger cache and better branch prediction than the Cortex-A53 in the RPi3, so the perfomance difference would likely be different for another plugin where the software and data were layed out differently in memory.

4 Likes

Could this be that in idle, there is a tight loop where there is little or no processing required so the processor time is grabbed simply for NOP? Maybe during normal processing there is more opportunity to yield CPU time. Check if there is an opportunity to add sleep cycles / yield during idle loop.

I recommend increasing to a higher maximum value (32?) to support RPi5+ which may be even better. Of course, such a high value may be daft for many users and factory presets shouldn’t push such limits.

Check the jalv engine class which handles all LV2 hosting. It will have code for presets and for saving and recalling state.

Well, there’s no obvious loop like that; note that this problem only occurs with ‘economy mode’ turned off, which means that the DSP code for all voices is run even when the voices are actually not emitting any sound (because the loudness envelope has reached the end of the release phase) - in normal mode, it’s not a problem at all. And the only difference to when a voice is playing or not when economy mode is switched off is thus that the envelopes have reached an idle state, and the final VCA has a control signal of zero. But clearly there’s something going on which warrants further investigation.

In a plugin, there is no idle loop per se, basically there’s a call from ‘somewhere’ requesting a bunch (= latency period) of samples, and after the synth fills in the supplied buffer control is returned to the infrastructure. So if the problem lays in the synth, it must randomly be doing something that uses up a lot of CPU at random intervals. Ah well, once the problem has been solved it will probably be blatently clear. :slight_smile:

That’s a good idea. I’ll still keep the factory presets at 6 voices.

Good, thanks, I’ll have a look there.

Ok. I’m back up with the Motor61 connected to a Pi3 ( via usb) and a Pi 4 via 5pin MIDI

Been working MiMi-d on a Pi3, hard over MIDI.
It doesn’t like long streams of MIDI notes and cc. I have a clock generator that spits out an endless stream of MIDI cc’s and notes. MIMI-d seizes up under this stream whilst OBXD behaves much better at it. MDA DX10 was rather more stable than both in this regard.

relentless-MIDI_stream.001.mid (1.2 KB)

014-Relentless Midi.zss (54.1 KB)

The MIMI-D Chorus Harp note 38 is getting a lot of use as a rhythm at the moment.

I pulled in the .zss file and the .mid file in my (borrowed) headless RPi3 Zynthian. When playing the .mid file using the Zynthian MIDI recorder, it only seems to play on channel 1 (OB-Xd).

I noted that the OB-Xd patch used (BzBEL TinkerBells-C3) is set to use 3 voices, whereas the MiMi-d Chorus Harp patch is set to 6 voices, and Zynthian is obviously struggling when playing it. Going down to 5 voices seems to work much better. Both patches use oversampling so they’re comparable from that point of view., but the three voice setting on the OB-Xd patch is obviously going to place less of a load than the siex voice MiMI-d patch. But I’m not sure I’m reproducing what your hearing considering the .mid file is only playing on one channel. Certainly, once you get clicks and crackles from the plugin due to it overloading the CPU a lot of data will get lost.

Indeed, my philosophy for the factory patches has been to have oversampling on default, so that anyone tinkering with the patches will not run into any too obvious surprises. But perhaps the philosophy should be to keep the CPU load low, and thus turn off oversampling for all presets except those where it makes an audible difference.

My plans for the MiMi-d is to implement the envelope hold feature as requested by @riban and then do some optimizations to try and bring the CPU load down, although I think it’s hard to bring it down by several tens of percent without a complete rewrite which is not in my plan. In the meantime, I think the solution for running on the RPi is to reduce the voice count for MiMi-d patches to 5 voices or less, or try turning Oversampling off (with Oversampling off, the CPU load drops to about half).

Apologies The grabbed snapshot wasn’t as the failure mod, The no of voices as well was probably altered as well. I will try to reconstitute and produce a more acceptable error report. It seemed to be more to do with voice allocation than actual resource. Notes seemed to be left hanging and mistriggering.

So it wasn’t just the Zynthian running out of steam with klicks and pops and the sound dropping out due to excessive CPU loading then? But rather playing more or less normally, but with some notes hung etc?

Indeed, plugins such as MiMi-d tend to not have a completely uniform CPU load, so there needs to be a bit of margin to avoid CPU load spikes causing dropouts and other issues.

It seemed to be the continual nature of the midi that seemed to be producing problems. I’ve a busy couple of days but I will revisit.

Yes, please do. So far my conclusions from the symptoms you’ve experienced and my own testing are just that with the RPi 3 having very roughly slightly less than half the CPU resources than the RPi 4, that it runs out of steam with the voice count set to 6 and oversampling on, which is the setting for most if not all of the Factory presets. 5 voices with oversampling on seems to be what it can safely manage.

I’ve been on an optimization binge for a couple of weeks now, although the difference is not great so far, a couple of percent here and there, and there is still more to be done. But above all I need to revisit the factory presets and turn off oversampling for the vast majority where there is no audible difference, if nothing else to bring them into line with the resources used by OB-Xd and other synth engines.

And I really need to create a patch for zynthian_engine_jalv.py to load parameters which are net present in a loaded preset from the default values in the .ttl file. I see that the zynthian_engine_jalv class actually adapts to whatever engine it is controlling, so my plan is to add that feature only for the MiMi-d which should alleviate any fears of changing the behavior for other engines.

Are you happy with the note allocation in high rate events? That did seem to cause it real trouble in comparison with other engines.

I’ve not noticed anything unusual but I’ve mostly played by hand from a master keyboard. Just to test, I entered a stream of 128th note block chords into my sequencer (not Zynthian; connected to Zynthian using MIDI), and played it back at 120 BPM. At that rate of course it’s impossible to hear the individual notes, but I could not notice any residual hanging when reduced the tempo. (My sequencer crashed when went up a bit over 200 BPM though …).

What have you experienced, do notes hang or get missed or does the plugin behave chaotically? Are you using the built-in Zynthian sequencer (Zynseq)?

EDIT: Thinking about it, I wonder if you have hit Notes can hang when changing voice count parameter · Issue #13 · polluxsynth/audio-plugins · GitHub . There’s a bug in the voice allocation which can cause notes to hang when the voice count parameter is changed. There is a fix but it is not yet on the master branch. A workaround is to dial up the voice count parameter after changing the preset, first setting it to 1 and then back up to the required number of voices.

Just tagged and released version 2.0.4 which includes the fix for the issue mentioned in the previous post. (@jofemodo )

4 Likes

Probably best to populate via the zynthian infrastructure rather than try to do manual updates. It also refines the zynthian workflow…

And stops me producing ghastly mutated zynthians best treated like the practice Ripley’s in which ever alien film that was . . .

Meanwhile down in the zynthian coding dungeons…

Yes, you’re probably right, if you want to avoid unwelcome surprises. I thought I’d announce the release anyway and it’ll get into the latest oram eventually.

In this case, it’s easy to work around by turning down the voice count parameter to 1 and then back up again, but it might not be what instinctively comes to mind when notes are hanging.

Actually, from what I can tell, Zynthian still always installs the latest version on the master branch, so if you disable the plugin and then reenable it you should get the latest version automatically.

1 Like

That surprises me. I thought that disabling/enabling an engine in webconf just flagged it in the cache file. I would not expect it to download a new version.

And it doesn’t! To install a new version you have to manually run the install recipe from the command line, like this:

$ZYNTHIAN_RECIPE_DIR/install_mimi.sh

Regards,

3 Likes

Ah, my bad of course. :blush:

But still, it does mean that for instance if someone were to start with a brand new image, Zynthian would build and use the latest MiMi-d version out of the box.