Shader vs paint routine performance
-
@ustk said in Shader vs paint routine performance:
but these are no wave files...
But there is sound output?
-
@Christoph-Hart Thanks I'll try all of these.
drawing the upper part and then the lower one is what I do already. So adding a downsampling algorithm should do.
Fetching the best value though I don't know, but that shouldn't be too complicated...But there is sound output?
No, just statistical computation
-
@ustk said in Shader vs paint routine performance:
No, just statistical computation
Aha now I get it.
-
Alright here you go (it took me way too long for this example lol).
HiseSnippet 1832.3ocsXs2aabbD+nrYRHSCPLP9.L0+iIkooHSTRaiaZT0qThFqPXJamf.ifU2Mjbita2q2tmnIJBPy237MHclcuWTkx0QIQ+gD2cmG+l2bzzLcHZL5rfVcNecJFz5Ozd1Zkc4QKERUvjiCZcu1Swr45rDgJDOGM1fCWmJLFLJnUq67ELYs5b2.2O+zmenHloq9pffmqkg3WJSj15amdv+TFGepHBOWlzf58OXRnVcjNVmSP5NsGEjJBuTr.OSvjsS6fVu0IQRqNalUXQSPq6dnNZ8rk5UJO8OWZjWDi7gwAyHA4u9TcbDiX91fiVJiilVZ5l.RJSqcD2w6H9f1OQFIqtu1g79tGfZNZ5OZsylv6Na.uwMg2nFvaKPpUCHcWOjtW6YgYxTa8KLdd21STVJDIH2dSn3oMXme9caejlnPYGlHtDOMiNTwQuOYznA.8q9Ota281CdA9f3X36yMVHLCIa.DvE4ymiYvJocIcxfTDJBzyAiNWE0kNQDekHCLvmAG5ncnm2d6u+3JImFKVChLlGunrKkFvpIAh.4fnyHrRbEx4Z.wen03ILRxxjvOKl4Y3+JGUgRz.8jVhBBugKEpEnSBkuulQHeQDFJVKUKpjc+BHajpSIhIPOZ3n8cf7OBGmmjrldZgRD68.RspKwVOIS3iAI7WAmYQe7gOre2+c2NDpDQQrqQp7lP2NluU9RhgwCGA6BOQXWNjdjjwtkpsO73tcp30nSPPoklRVeHipOrj2LgJRmzqeEKoowjyDP0UXrNsjoc8JbOvoHxpF8WfGBioOLlX8GHKb2cgyHW8J7AYXg4QdFAnDxqPHkzEjabWQdUiHIMFMCgc2qaiv7YLsSEJLlLvxLqEn8HcRpVQG5c+ZRtOo3ZVU96IsTyoOUgujsutz0FcLNLMSVIIOvJiF2uIYFqHydHEuWlHxtjkv+2XkRCQT8ny5HSc.PkBYbQIjV2nqamJrNjnBOW2SN.Xur2SVqec5FpuassOzf1oTWC6S04jeF6MOWExVPuENrrfIv2qqm+OlgqVJsnONeMOwrXJv0ygp9vylPUHpHjdZA6O5by9CRMyoZDmCtxlF3p93n1WpCEwGxUkldi5uontlo0o6O3pkqShnjjbC0hv.jSaMDIrBHUSv0v2shpqEbzS9JL1bsrnYjTsu9rnZRbg7FMZ7O7ZRipnXXXLJxbAFmVO+oSN9DhsTQlAotf8LCiQ0BRT60.RLPdgLhkUQ2quQmCIxEKs.dEp.oh0mw2xoJah59PcszYttZIZsqIWcSMRNE52Un9QjjkJN4BJSL.RuNT7bQbN1SOeNkgL.7Hb.jmRYnkowOSEpSRHSeqMRcULwZ8kFPNGVSnORqdfk9MPQJm.b9nMJE.gkK74WyPadlhR38X3kkcdNm0kuma43gLz0cNDYLHXOqsr2qexQ2NwbRlCm94C0CJbLSEWlAvlVKmu4Y6J1W36RWhhyvUPBZWpiFv1FmGpPLhAPZdbrS2w7.XK7OlL6D3S6WJrL2fhOqAV3X8TTb4S4Wpaw5yvgB+.RygHXyxcIkEvBlByTEI5RII.1sSAotfD74dM8sieI7oEebzK2nyQYYsKJL85M3t45YWdrhRmXPSVhqJ9IhEJoMOxY.aM62E6PJikS3LzjCSdFm9Jr04KTnUDuRr1.gH+EDHOJM3woLQLMaJZXCQ6PFEHlkegqpiBOCfGUBrMpA2Jou4TR+pvB9BMAV5qPrvWXUTzo4bOFnT.NLmi6tW8AhKbs1tooB7bVeMoqrpFH0872rjjtvMQNgll6YbfWXvi.YepsZVN1uXXqOIZgFtf9NraAfb5SI.GVgvRo4kNiw+VArezuwXctH1z.ru.qJhBi0lhjCehghR2iPWisKn1UT8OFsQZFQeYLaywyWe7Xilr+ZFOdyUQznwmdKFMVYL2pQizfwpd3Z0YZK9UpdNqfbtv0eZ97s9FOJKSSt1rs9LuoT1qiwdp7jKvrA9FRUDRqOr4NIsu4cRZtxTnexZCB0pITWluJEU2zhTAEiioO8rIGSec.dQlh6H5nBRqjgPqiwqnsB8q0zo8wn4RxkRK3UM9On0aacu9dkK8v4LAxHdE05uiUvqZt7355CSNXEO.u5h+yOdvRjGfWSx2bfEekszTdiTbc16MpX4uPE++tlGsfoNhaSr4Vm7p1EOPg8MV0iWmSYj10MWE+2rUQeSg38ZOUZCWtcLtyVvHkb76AFKVf+8ZeBMeOzVCv619zu92ms0C78vVP8ayjTlQ6yxSlQcrBQR6JJcgK6ZsCWf3OOhOydfYTuJ2gel9o3ww74VEONt7wfDQXl96B8E67+hf2wcCgIk6+NRm1OgOCiCbM.H9ZSiNCRjQxuKLjM+GQ4aammO7VvyGcK3Y+aAOe7sfmO4Vvye5Vvye90xC+OJ5uma0I9xA5hom35J1p0IJAkY4xBC9uTMEYiA
I've added a few convenient methods to the buffer class, so you need to pull the latest commits.
This is the code. It uses one naive path rendering using all sample points and then the smart downsampled solution where it looks for a upper and lower value for each pixel.
Content.makeFrontInterface(600, 600); // We'll just create a buffer with a second of sound const var s = Buffer.create(44100); // play around with this to see how the waveform reacts with different // frequencies (it will change the frequency of the decaying waveform) const sinFreq = 0.04; //! Dummy signal creation for(i = 0; i < 44100; i++) { // add a sine wave s[i] = 1.0 * Math.sin(i * sinFreq) ; // add some noise s[i] += 0.2 * Math.random(); // apply a envelope s[i] *= 1.0 / (i * 0.009 + 10.01); } /** Now we're creating a naive path using all samples. */ const var NaivePanel = Content.getComponent("NaivePanel"); const var naivePath = Content.createPath(); Console.print("Naive path creation"); Console.startBenchmark(); for(i = 0; i < 44100; i++) { // no downsampling, terrible performance naivePath.lineTo(i, s[i]); } Console.stopBenchmark(); NaivePanel.setPaintRoutine(function(g) { g.setColour(Colours.white); Console.print("Slow (naive) UI rendering"); Console.startBenchmark(); g.fillPath(naivePath, this.getLocalBounds(0)); Console.stopBenchmark(); }); /** Now we'll use as many data points as we have pixels */ const var SmartPanel = Content.getComponent("SmartPanel"); const var smartPath = Content.createPath(); smartPath.clear(); var STRIDE = parseInt(s.length / SmartPanel.getWidth()); // You might even increase the downsample factor to smooth the waveform //STRIDE *= 1.3; inline function getSmartValue(offset, length, upper) { // Uncomment this to see how the path looks if you don't do any // smart downsampling at all //return s[offset]; // This will create a reference to a part of the buffer local thisBuffer = Buffer.referTo(s, offset, length); local value = 0.0; // New method, you'll need to pull the latest HISE :) local range = thisBuffer.getPeakRange(); // Now we return either the highest or lowest value return upper ? range[1] : range[0]; } Console.print("Smart Path creation"); Console.startBenchmark(); var normPeak = s.getMagnitude(); smartPath.clear(); // These lines ensure that the path is always centered and normalised. smartPath.startNewSubPath(0.0, -normPeak); smartPath.startNewSubPath(0.0, normPeak); smartPath.startNewSubPath(0.0, 0.0); // Go through the sample once and calculate the upper bounds for(i = 0; i < 44100; i += STRIDE) { smartPath.lineTo(i, getSmartValue(i, Math.min(STRIDE, 44100 - i), true)); } // Now go back and calculate the lower bounds. for(i = 44100 - STRIDE; i >= 0; i -= STRIDE) { smartPath.lineTo(i, getSmartValue(i, Math.min(STRIDE, 44100 - i), false)); } // We need to close that path in order to be filled smartPath.closeSubPath(); Console.stopBenchmark(); SmartPanel.setPaintRoutine(function(g) { g.setColour(Colours.white); Console.print("Smart Path UI Rendering"); Console.startBenchmark(); g.fillPath(smartPath, this.getLocalBounds(0)); Console.stopBenchmark(); })
Debug Output:
Interface: Naive path creation Interface: Benchmark Result: 121.742 ms Interface: Smart Path creation Interface: Benchmark Result: 24.656 ms Interface: Slow (naive) UI rendering Interface: Benchmark Result: 2.642 ms Interface: Smart Path UI Rendering Interface: Benchmark Result: 0.060 ms
You get a 50x performance gain like this :)
-
@Christoph-Hart said in Shader vs paint routine performance:
You get a 50x performance gain like this
:smiling_face_with_heart-eyes:
-
@Christoph-Hart That is very cool, I'll try a cherry-pick then because for this project I am using a modified version of develop
-
@Christoph-Hart said in Shader vs paint routine performance:
I've added a few convenient methods to the buffer class, so you need to pull the latest commits.
I'm not seeing them in github.
-
@d-healey @Christoph-Hart Yeah strange, only the name of the set method changed...
EDIT: but it works, it was just a redundant function name... Thanks Chris!
-
@Christoph-Hart Why did you need to add the getPeakRange function? This is just a
[max, min]
array right? So easily doable with hise script? -
But FASTER!!!