SynthMaker

Buffering & caching

Archive · 2009 16 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

mwvdlee ·

Has anybody ever tried to do buffering or caching of views? Is this even possible with SM?

Having the GUI redraw an entire wave display if only a small overlay text changes is a very inefficient way of doing things. One may be able to render the wave display to an internal bitmap only once when a new wave file is loaded and have the GUI draw the prerendered wave display instead of doing all the underlying math and rendering every refresh.

MegaHurtz ·

You can move the text to a subbpatch and redraw this.

trogluddite ·

Do a search for 'render' on the SynthMaker Wiki - there's a nice little module there that will get you part of the way to what you need. It's designed for rendering front panel backgrounds, but I'm pretty sure it can be adapted to work with any combination of GUI primitives.

The Luddite

exonerate ·

No need to redraw the whole view just use the redraw area primitive.

Cheers 😉

Exo

aliasant ·

I think we might be trying to do the same thing and this is not just limiting redraws.

If I want to display say 1 minute audio moving so that new audio appears on the right and then moves left to make room for new drawn audio...

The simple but bad method is to us a mono to graph at its maximum 16384 and send that data to a Graphline.

Problem with this is that we can only display 16384 / Samplerate eg. 16384/44100 = 0,3715192743764172 seconds

That is our max time and it gets worse with higher samplerates. We can link several Mono to Graph and delay them individually and finaly stich them together but its just another bad solution that aint very flexible.

What I was thinking was this.

If I use a mono2Graph and sample say 20 / sec. That means each sample needs to be 2205 samples if the samplerate is 44.1kHz

So. 20 times / sec I get a new chunk of data at 2205 samples. I draw this chunk on the right side of the display, maybe over just 1 grid width. I think I should be able to resample this down to 8 from the original 2205 ( or what ever works best )

Anyways. On the next chunk of data the first chunk has moved to the left so there is room for the new data to be displayed and this continues til I have the whole display filled with the wavefile.

Im not sure this would be easy or even work but I think it could?

I just built a test example and it kind of works but not really... It is not even as I planned it to work but still.

mwvdlee ·

aliasant wrote: I think we might be trying to do the same thing and this is not just limiting redraws.

On this one, I actually was just trying to limit redraws. 😀 Or rather; partial redraws; redraw parts that rarely change only when they change, Refreshing only area's wasn't an option, since the overlay in this particular case overlapped the entire area. If I understand correcly, you are talking about background rendering to a canvas larger than 2^15 pixels?

Anyway, I followed trogluddite's hint (to look in the wiki), hacked around a bit and ended up with the following module...

I'll try to build an example soon, but I haven't tested it thorougly yet.

The idea is to insert the View Cache module just before the parts of a view that rarely change and trigger the "Update" input when and only when the data that's used for the cached part of the view is changed. In case of a wave display this means only when a new wave file is loaded.

If you look inside, you'll notice a switch. If only the view created by the Bitmap Create module would include details of the area, you wouldn't even need that (feature request? I don't understand why it doesn't include this in the first place). On each Update trigger, the view is rendered both to screen and the bitmap. Alternatively, there's also a View Cache 2 module, which omits the switch (and the double rendering on Update) at the expense of requiring you to use the give Area output. I haven't really tested VC2 though.

For the case I needed this for, it made a noticable difference from jerky and lagging animation to smooth as a baby's bottom.

aliasant ·

Lol

I was probably on the wrong path anyways.... 🙂

infuzion ·

mwvdlee wrote: On this one, I actually was just trying to limit redraws. 😀 Or rather; partial redraws; redraw parts that rarely change only when they change, Refreshing only area's wasn't an option, since the overlay in this particular case overlapped the entire area.... Anyway, I followed trogluddite's hint (to look in the wiki), hacked around a bit and ended up with the following module...

I'll try to build an example soon, but I haven't tested it thorougly yet.

The idea is to insert the View Cache module just before the parts of a view that rarely change and trigger the "Update" input when and only when the data that's used for the cached part of the view is changed. In case of a wave display this means only when a new wave file is loaded.... For the case I needed this for, it made a noticeable difference from jerky and lagging animation to smooth as a baby's bottom.

I'd like to see the example, since I'm trying to figure out exactly how your modules work.

I would have just used a single Redraw Area for the entire View in question, attached to a homemade trigger limiter fed by Area Unions as needed.

mwvdlee ·

infuzion wrote: I'd like to see the example, since I'm trying to figure out exactly how your modules work.

Here's an example.

It's a modified version of the standard wave player. Never mind the uglyness, it's just to make the drawing slow enough for demonstration purposes. If you open & close the preferences, you'll see the jerkiness of drawing directly to screen (because VC still redraws (twice!) when changing size). Play the MIDI sample and you'll see the big counter incrementing smoothly. Bypass the VC module (just drag the wires in the Draw Wave module), and you'll notice the counter updates far less often.

aliasant ·

Honestly I cant see the difference. I copied the waveplayer and placed the second one under the first one and then bypassed the cache and played them at the same time... Then again. You are still updating the entire screen with that Redraw fed by a 25 tick?

stw ·

There is a difference. But the provided schematic isn't very meaningful because if you want to verify the results at least you have to use an area redraw instead of a view redraw. Í altered the osm a little bit to make it more compareable. I split the wave and the counter draw into two different modules. A selector can change between the "cached view" and the normal view to see the difference. I additionally set up one draw module with the wave and the counter areas at different places. So we have three modules. Upper: seperated areas with seperated draw modules. Middle: layered areas with seperated draw modules. Lower: "mwvdlees" original module with enabled cache on one draw module.

What you can observe (if your eyes re fast enough 😉 ) is this: 1) counters are syncronous when all draws are set to "cached view". 2) with disabled view cache the seperated counter still runs (99,9%) syncrous to the lower (mwvdlees) module but the layered module in the middle is a little bit slower.

Conclusion: Bitmap rendering is faster than drawing elements. That's not really new. I've no knowledge on how the grapic things work in SM but i guess the pixels of draw elements have to be recalculated (even if not changed) whilst the bitmaps values ae taken from memory. However it shows that one has to keep an eye on how to arrange (big) drawings. So the cache view idea can be useful at some circumstances. I saw this already on some older user modules (maybe on some knobs by shif or sambean? - hm... don't remember), so the idea is not really new but "mwvdlees" module is easy to implement and can come in handy.

mwvdlee ·

I've been using buffering techniques such as this for well over a decade in other programming environments and it's pretty much a "standard" trick if you need fast graphics (2D games, animation).

For pure display purposes it's use may not be that much of a benefit, but I'm using it to update large overlays in response to mouse interaction. If you're doing user interaction, any lag is too much lag.

I created this because nowhere in the forum did I see anything like this, and the module is quite easy to "plug in".

Obviously it isn't suitable to all graphics operations and has the expense of memory for the bitmap and some other problems of itself, but for certain situations, I consider this trick essential.

By the way, the reason you aren't seeing much difference in your altered version is because you're doing both cases on screen at once; you're always looking at the performance of the total. I'm surprised you can see any difference at all actually 🙂 That probably has different reasons.

infuzion ·

..but I still do not see a apples (your buffering) to oranges (trigger-limiting via heartbeat) comparison; I just see a yellow vs red apples comparison.

trogluddite ·

Don't know if this explanation s any help - but here's what I've noticed....

Say you have a small GUI area which is superimposed on a big one. The big one contains vector graphics which could cover any part of that area.

When the view for the small area on top is redrawn, there is no way of knowing whether any part of the vector graphics beneath will overlap with the small area to be redrawn; not without doing a load of maths to see where the vector graphics happen to be right now, anyway. In effect the whole of the larger area gets recalculated just to see if one little bit of it happens to affect the area we're interested in redrawing. Calculating where things are is a seperate load of processing to actually putting pixels on the screen - when you draw, say, a vector arc, there's a lot of maths goes nto working out exactly which pixels need turning on or off which is not visible on your SM schematic.

So rendering the graphcs to a bitmap, which can just be stored in memory, saves a whole load of calculations. For this reason, using lots of overlapping views with big transparent areas, all one on top of the other, really does seem to affect the CPU use of the GUI. I always render the static components of controls to one big front panel bitmap when I can for this reason - sometimes it's only the pointers of knobs which are contained within my animated control components, so there's basically just one layer of static stuff and one layer of moving stuff.

The Luddite

infuzion ·

OK, I understand where you are coming from now Luddi, thanks! 😇

aliasant ·

infuzion wrote: OK, I understand where you are coming from now Luddi, thanks! 😇

Lol Me too.

And thanx for this View Cache. It seems to be a very good trick 🙂

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.