SRAM overflow: help making patch more efficient


#1

Hi again.

I've hit a brick wall with the development of my first Axoloti project. I need your expert help.

I was just adding the finishing touches to my patch: a mod matrix. But have now run out of ram.

The mod matrix is essential to the design of my synth, so it would be great to get this going.

SRAM' overflowed by 38504 bytes
CCMSRAM' overflowed by 26400 bytes

that's a lot!

my mod matrix is rather large, if I remove it the patch runs... I just can't map any of my modulation points.

Since it is an MPE synth, a lot of the mod targets are inside the voice subpatch. The way it works is I have "modreceive" supbatch for each modulation target inside my voice subpatch. Each of these modreceive subpatches receives ALL the mod sources, and these get multiplied together in the interface-specified amounts in order to produce one grand total mod amount for each target.

This is obviously very costly, but I'm not sure how else to implement it.
Perhaps it would be more efficient if I could hard code a modreceive object?

Any help, tips, concepts or strategies would be appreciated.


#2

Another thing that is using up ram is the midi interface... I am using midi rotary encoders and led-lit buttons and changing the behavior of the interface in order to access every part of the synth.

I have 16b tables for recording the position of the encoders and these are currently in sram. I tried placing those tables in sdram, but that seemed to overload the dsp. I'll try again, and try to make the oscillators and effects more efficient, but I'm not sure even that would be enough.


#3

So I just passed all my tables to sd ram and it did not help much at all. I'm getting these numbers now:

`SRAM' overflowed by 37368 bytes

`CCMSRAM' overflowed by 25408 bytes


#4

there are I think quite a few topics discussing this...
the one to start with is:

perhaps the tip that is least obvious, is making sure execution is done in the right order.
the reason is simply, if you do something that is required to be executed on the next cycle,
the the previous value is stored in ram..
on a large patch, thats not kept this in mind, this can add up really quickly

(also yes, modulation sources/targets and presets can eat memory fast - so minimise these)

generally with DSP (actually most coding :wink: ) its best to try to keep in mind 'best practice' as you go along like those above, rather than trying to come back and fix things later.
ok, you do have to avoid premature optimisation... thats why i say best practices, rather than optimise as you go along.

of course, at the end of the day Axoloti is not like your desktop, its ram/cpu is limited, thats part of the fun, seeing how much we can squeeze out of a small/inexpensive thing.


#5

EDIT - spent too long writing and technobear beat me too it!

Some things to think about with sram-

Execution order is important, especially for audio signals, make sure no output wires are going to objects above or directly to the left.

It can help to remove any unneeded inlets/dials from objects. It's coding, but pretty simple

Try alternative methods - I've found nearly everything can be implemented in different ways. There may be alternative ways of doing things in your patch, or alternative objects, that use less sram.

Changing the amount of voices in poly sub patches can help. Also, make sure anything that doesn't need to be polyphonic isn't in the subpatch. I.e. If you have an lfo in the subpatch there is an lfo per voice. So unless you need poly lfos, keep it out of the subpatch and feed it into an inlet. In my first patch I had a bunch of control scaling going on in the poly subpatch which overflowed sram, but I moved the scaling to the main patch and it was fine.

Also, maybe the patch is just too ambitious?


#6

I hope not!

Yes I've read about these methods of optimization. I think I was pretty good at laying things out from left to right, top to bottom, but I'll go over it again and see what else I can do.

Also I've kept my LFOs outside the voice patch, but since it is mpe polyphonic, i have my envelopes and of course x, y, and z controls inside the voice.

I agree that this is part of the fun. And I like the challenge...

But I was hoping for more advanced ideas like perhaps another strategy for making a mod matrix that combines several sources to each target...

For instance: is there a way to have global variables that are exposed to all subpatch without the use of inlets and patch cords? Right now I'm using send and receives...

And perhaps it would be more efficient if my mod receive subpatch were replaced by a coded object doing the same thing?

Would love to hear your thoughts about other ways to approach this. I'm not giving up!
cheers! thanks for your help.


#7

If you post the patch or at least a screenshot, it's going to be a lot easier to see what you have done.

Without it's pretty much like shooting in the dark.


#8

OK I'll post some hing when I get home. Thanks for the help!


#9

yes, use a table ….

ive done this a few times, think of the table as raw data, and you can use an offset via polyindex for voices. with a bit of thought, and design, tables can be used as a way to implement alternatives to lots of things

my personal approach is if things are getting too complex is to create a custom object in c++.

as @jaffasplaffa said, its often hard to generalise optimisation, since it its highly dependent on how you have patched things and what you are trying to achieve... and 'compromise' can sometimes be part of the solution, and that requires knowing whats the important or problematics parts are.


#10

That is an excellent idea!

I'll try this first thing tomorrow.

I don't know c++ but if it will allow me to finish this synth the way I want it, I'm willing to learn what I have to.

I'll try the table approach first and report back.


#11

@thetechnobear Ok I'm getting there. But I'm having trouble accessing my tables from within a subpatch within my voice subpatch.

I know the that to read a table from the main patch in the subpatch, you address it with ../mytable

But what if rour tableread is two patch levels deep?
I tried ../../mytable but that doesn't work...


#12

So I've implemented the mod matrix with tables. Right now there is a table for each source that contains the amounts of mod applied to each of the targets. Next I'll implement a table for the modulation sources.


The first image is how my interface distributes modulation amounts from sources to destinations.
The second is how these are received inside my voice subpatch. This is to be encapsulated into multiple "mod receive" subpatches inside my voice.

But I still need to figure out how to do this. Right now I can't read from a table two levels up (in the main patch) making it quite difficult to place everything in the voice supbatch. Can someone please indicate how this is done?

Also right now there is a fair amount of processing that happens within the mod receive subpatch. I would like suggestions on how to make it more efficient as I feel this still won't cut it, memory wise.