@Christoph-Hart awesome thank you for the info that is super helpful! is it possible to then select between them via scripting or by linking to a combobox or slider?
Posts
-
RE: Swapping a neural network model at runtime.
-
RE: Swapping a neural network model at runtime.
awesome thank you! ill try to get one network working smoothly today, then test out some methods to make a combobox to select between networks and also somehow reload/clear/initialize them. my first guess would be to make some function which clears out/resets the old network somehow, a quick chatgpt gave me something like this, but im sure itll need tweaking
// Define the model(s) const var MLmodel_1 = {MODEL1 JSON HERE}; const var MLmodel_2 = {MODEL2 JSON HERE}; const var tf = Engine.createNeuralNetwork("TensorFlowNetwork"); //function to clear/initialize the models (can be linked to a combobox in the future) function loadModel() { tf.clearModel(); tf.reset(); //no idea if this is needed lol tf.loadTensorFlowModel(MLmodel_1); } loadModel();
hopefully it's a start to keep experimenting !
-
RE: Swapping a neural network model at runtime.
would you be able to share a full working project? i've been working to create something similar, a free plugin for archiving and making old and un-updated free vst effects plugins available for modern pcs (windows only old compressors, unique saturation algorithms, etc), and im happy to help troubleshoot and get something working for everyone! i've been using NAM for my captures but havent had luck getting them to load yet in HISE so ill happily test with AIDA-X if it actually is running in HISE right now
-
Smooth Parametric Bezier Curve in a Script Panel
hi magical HISE friends! here's the code i got so far for this smooth parametric bezier curve in a script panel. i currently don't have a use for it (yet) but wanted to share it because it seems useful, especially with a few custom tweaks
the main features:
- parametric
- adjustable amount of equally spaced points/circles (locked in their x positions)
- the points and line are always centered to your script panel resolution
- the padding between the panel's width and height is easily adjustable (as a ratio rather than pixel values) (the padding border is drawn as the inset rectangle)
- super smooth bezier path, different than "quadraticTo" . based on the code i found here
Smooth Bézier Spline Through Prescribed Points
-
double click to reset values to starting position (.5 in this case)
-
save in preset works for me (each point automatically links to hidden sliders in this example)
hise snippet
HiseSnippet 3684.3oc6aztaabb7niYZrZcaBPe.15BjbLhhhTVJI0Ltw1z1oFN1Vvzw0DBBAKuaI4Ve7tC2GRjwP+ouM8sn.8EoOB8e8msyreb2tGORKo3XfBTAaQt6NyryNesyN6pCSh7XooQINMt1KVFybZ7qZNbYX1rAyn7PmGcemF+9lCmGEkMibHMgNmkkv8H2i8ibVBYPdxILxI8bt2xXZZJy2oQiO3aQDabsq5H94e8M2iFPC8Xkc437xHtG663y4Yk8d3cdLOH3gTe1K3yMfd+67HunvAQAQ4.S9AM65DS8dMcJ6oTDrqzzowG9.edVTxvLZFKEf4dQ9KGNK5zPI7ujmxGGvvF8bFBDR1syfY7.+C0BfTGmFW8vRwwGHEG+1lOg6yK5uTr7whAHkXXJCZbkMwR8t.rTCCV5pRV5SZNzKgGmUNBxO+xlOJLikLgBhZSVQBqyU92eVyAQ.DgYclSeM6gIPiBLb+htcaStY2ts5e8st9V6tqFTpuOvq4zfuMm6ybOBfp2AcOtMo6h8u6CE+fnrdDtIR3UQ35aAJ0zLxIzDvtJjEzibahlFSYYChlGGEBMbugb3aHwBgOLe9.dhW.KEv4K5SH6tKYTTNwiFR7lQCmxHYy3oHbiAizrHBOzKgQSYjnDhOS88rYLMHQSHdRJJmgAITedNR9d6CzWLCOW1E.JhnE3or.lWFOJ74ZzzD3yI857U8MYPp+eIGV2HMlmGjwiCPGIJvsLlOyWuF4ggrD4pTRzGR8.6Ifzc6z6OHnnpGX44y.03bdnbMkx+QllMEjwlY8SnSmxCm9nPe1Bfd6zSPsWDQxR.GKxoy3dyTnP.o3XF.rDKI6Up3dB3KbHnvA.dEJqNPPoTv+DQYLK6TFKjDi5Oxob+rY8I85h.tK7Avgh9VCAGgv0cCDbFiOcVFo2dFDT1mVFZvZlbpfl97S.WvnPxDoTbB7+WATV.hE5irQezZQeTI5JqnKJCnspqvHCtnbhlNVbD.6iB4YbZ.ZeHrgA2sjn.PxGjCPSSRnKM0Fpweob3aSN5XvEDouqvBEsE6Ce70FNjP6s2tE4MWeKzqwh.chySm4ZDl3wgQicugIL+vMHaS3PnB3esP+8UHxQ7i6jxffBmHCfdi1v5NHksIfeNFQvsaGLzE9K3a81Lw8YSnfuon2afHbvlgOkdB6QgGlvfV.7YI4ajgDMbUT8Lkt4twwAKIoABiZP9xoX.kTz8VDqfGxmmOmPC8IyoKDeejRyYpy.3d1jIvjHhTzsa2dx3iOQgejXPKLnKrwXOEFpYQiAn5yCEQ4HTjWG8xBlzUvGsgnMPHkBsOR7hEBP7RVaahq.TH7na4zuSIDsH6RbMByuCoWg8.RVYPTlOrp.BWLI0AAEiw0CnfITR3Jj5kbYTHzTIxmvS.QjLPnDA9DMie6aCBqhUpbRAQ.Yayk4tj8DtnCeM6TCJJgTpoCVJovYZdJgkkmDBB+rYv1zKbkegGpEwFqqVsMkCl1ROTqnvs9lGGvlCtbBN3EyhlC60PClFkvylMWDtHMJ3DL9JjYmOmNMJjFPRWBzcdpgROSfpKsMYbahWahukhF0CzNArvoPT9xt8hkwMPwfGINAxrqbPeiA8qN3B0XhM.hBxQdPKjpMFDZjXG9oPkUi5R3aFKiI4A9kfxZL7g1HS+iuBD+5A4LBCB97VnqKhEvcT7iOGF8HNxqG2ZcSlb1JPvu.gyKwNqvnB+XwOIphxeo.THgsTAn3G6cOTE7Gkphc1wRNu.o3sEyFNAdwxY.5FhBz6390a9uvvXdHjgDjYyDCaZOZfWd.jYcwVXwQ7vrTAWI1YKeLdHk+weSbJEO7TJFVxdPtk4YrARbOTfp6isLmi6o2uqnm8p1CZx+XkIuv3SNTQrkmiN36LCiXmBoBSNggaPmZDiRPQveR8om5yD8LUPpuiMIam4QPviT1TzYVNB8ntGK7.jMGKatmdqGYSMekHa9X7isI6AJgGeTOqYQbZ.gyubRRqwaq2F81nRscOCawwxt12nKuUgJQAkfq3kLX8VIEB25DIBVyTNLtrqurPzTzU2BwSQWekXpUM2F+pkXBNtFbn26t31iI4oXbypAU2fXaUQlXKXL3YQDFw7tpDT4hNG8OWEHk.LoDnDafJDdw8JWoEK5cKjR8qg6q3iuyNbqk.PQwj6plcOoON1sP80RE4rF03.oqH5coyk4BFfOdO4jaZu.PVL48shEBPWp46b.l.BpdAHKDKs5WIXzafwtE7+1.12B4zyVyVs34Jg0BkjJqWRLr2MbFG3W0DOBxraFMifmSG9VRT9zYDFs3jWeVJwig9ilwsDzWVLlCAZ6F2VE3qPh.bzCVfmiKCNDAF4ANBPTJWlJYJKll.TPmzgXaVY3OPbHoDjzQrqdFciABqECwcVzmblYVXKu.3tTgaoleSwvWH3cC1zyLVMddpZigqVLl7nEhiVGhKKQrLlaTTrslQEnQvav4gk4zgJYksUmzLZR1SYmNLerP+n3mivxerr36s5udibkfzXSkZCX3E2SJDLkJcD9g8WAxQUgbzZfbu5n4d0BYczrFHYg9hgQBqEFVtkUADo6xp.VBJnVtuVvWiOkZ+edp8dBRki.9WD4dDJ7ZKDLfZ4HbY2VrjfVE7a4WG0pLBhvoWVNJ7bbGBmEO64QPpogrR69oEZqoclvCBtaPfqr5kocFGP8dskU12xxTlQXMMvR2XjxA12eFqQBHUvkEVXLQaWSSbAX+IY0PJgS1g6Z74T0EfLllx7Ihr6YUKkPp4TTTHCClZ2xJbzeEXGogUwYk.OpdVB4frnLH8CeN3HE5gMIiw3CmvR.tb7RY4sTUCxksvKHWrJvtwBtwEtl50FUJYAEYZqR1SLECUzvZ4rCwE2DQuVao6PUKuVqmsqVfJg4oH58p0KTyGCRK3AKVZ0C9ZcdUrFMnbIETPLqn6ns+JyhriQGV.U0LKsWHlzylwKsTpT0Hw9ak0qXC6eulhDU8D6hpifIDUsHCqTJko5Ro.mDl2pRDkAREfzLTYQtcQcY2l35ZZctCwP0OR0Tq3guZwblSUUArpJWpIuUMo7TQEVJiMj8tpMuaUUSthh7xJsUb3qJEOuxV7vQAfxFcCx1pqe68.pvzRgyaHKtUw7CaLdqR5cVcBrgpPjdPPzjhi3Utu6TLVrLBaQf1krffnSml.di19s5TzBYmJyOCky.OhFfgKIwIrS3QfDvSVmRivZF2OgLQLwV7ZFF1eAIhacylHDgHqMlubRkmantrBUmOolL8pHKsln6uZ1HS6fonTjlH5rbunbHVnaOvcoW8nqb1aqhdArqv8VGQcRRzbicqX9SYWRGdic9pX7WNIp5QuFq1JhCLdvh2lYpEzKWalEmNiCZsTHXyqwPd4YXAHJA8bXuUBJpDdPP.ONk4dTA6ui1SqcISZ1WwsGsmUiisTbUY6z4zf.lnbdbe0hPeMNgXEHrkNxaXJY0arZMW8j0xBSrotkkIQsVa1CXM2hUY0dNttHA1aVMVXNWDPHg4AYMLMvHAJrKyHb8sGxbuAYgZw72sIVo4XFbbfhqSwjL5LzrRkvLShJSaQpZqeCH4MxYwGPnX71.vpHmGTb6Wn6IOTu2c4k8T0Ns6hCdP4kuV0xobVnInP0LVvmIkyL7nj31AZqHoo8yALcORHmaKkosKkIsMVt3E.2YeQQp0WwL4t99j4PvVFVPufw3kOBaKNGR2qHqCHyuLNN5RyDueBhz.ENkYdyNAL2rKimYFzJ7OG4PWBoQVz+rkKbMYD5dARKs0lRYDK+sPrzwOJeb.aP.GN.RkHwClw.QOWlumDtc7P.wq+0vBCulY0E.A6OgIHhaYZdAIWlsB9ImQxOOY7sgrMsCAqEyhapgNNUIuWfAzUKoVju91q7HA9zOkTAkkknLpNTVQroqEJduipX.VYmqygWRGvEVscf5BtTWyIQbUjqR425UWVEAkaSBKFOXrq7tCdNynTIXVCvjmG6qChWTsK89+qRVYMj5KqsEOiPm.BHh3xVyDm9KhPOIB1xaRdBPRHQNOYJxByVvDVGcwlzmU28kT0qQ3Fv72nGy+2U4+QbUp9xW3Fa5qGSYwTQQUTJdPY959WH6H6I82gu2lpVSeeo6v42AdRDlwo7sAfaGZmbGb7F84nW8pjMjgFJ0BE5tjyu1GSHEerFlm4yxZvZ4aDBQyflX9NL9QMtxBoz2GaI7WyagZHlqWgEwoyTkzQlqBXdj.pCrbHkEFrU+hpzGE9znL1yBcas0a15Zac1VjpCMYRsioJIMjBesCiuJxjMgnq7wr0VZ5T.nSiqZ+VD+vy2aQTcBXC.iBwGPzyhYp1OLJvGeig32W8kK5nNsrCLiJND.MS7BF+0pWv3P3jJrDGtO9bJsdIPccDqhxmA5+7abt3To26Dpr26Dpby2ITY+2IT4fZnx2+n6Syn3KNUo3.kYLl9MZyz39rS3dL46O8ZMuOK80fOhSieQw6zD5VN6WW+5TQuUwj+QMkd1NKbZzrANcK0eQ7B.KXi+9e8Nxy0T1SxcFGk.qBYXcy2Prr+g7ez5kESwnh5iF.v+aZdW3zRkc3Xvve342XbUN+DsWiro4SFqhx4hOe8dOOe68dd9t4644a+2yy2A+DluUet2ebymD4ik8v90miOyd0.v1.VO4a7gbDBaGtz7Y3eAdR5c23SR+7xheRyC4YdypmGuRM7HD64mCdT8P9udyGLYBjEUICd0lO7UW1Ws+aY5k2J3THkqDNZK7z74CixS7XvrGBwBSQ6fqfaRJa2UaWLjE5KZ7efeTC1Ca2PMXO8fNyodIQ+fxvC+SE3iD8.7Tn3uLhq07IXaxJaB53Lm6y+AOOaRsBh6cYQ7lWVD2+xh3AWVD+hKKhe4kEwu5siH9GVxcyyhlKcabbdxgOPr4biFOHjBVfBqUm+KfEn2uX
the code
Content.makeFrontInterface(600, 300); //Content.addVisualGuide([0, 150], 0x4AFFFFFF); //Content.addVisualGuide([300, 0], 0x4AFFFFFF); const var Panel1 = Content.getComponent("Panel1"); var numCircles = 6; // You can change this number to increase or decrease the number of circles var Cradius = 14; // Radius of the circles var selectionRadius = Cradius * 1.8; // You can adjust the multiplier as needed var innerCircleRadiusFactor = 0.19; // Factor to determine the size of the inner circles var draggingIndex = -1; // To track which circle is being dragged const var MainPaddingX = 15; // spacing between panel width; 10 = 1/10 of width const var MainPaddingY = 10; // spacing between panel height 12 = 1/10 of height var PaddingX = MainPaddingX; // division factor for X padding var PaddingY = MainPaddingY; // division factor for Y padding var CPaddingX = MainPaddingX; // division factor for Circles X padding var CPaddingY = MainPaddingY; // division factor for Circles Y padding // Initialize the control values array const var controlValues = []; for (var i = 0; i < numCircles; i++) { controlValues.push(Content.addKnob("controlValue_" + i, 0, 0)); controlValues[i].set("visible", false); controlValues[i].setRange(0.0, 1.0, 0.01); controlValues[i].set("defaultValue", 0.5); controlValues[i].set("saveInPreset", true); controlValues[i].setValue(0.5); } // Apply slight variations to the minimum and maximum Y values const var minOffset = 0.0001; // Minimum offset const var maxOffset = 0.0002; // Maximum offset function applyYVariations(value, index) { var variation = minOffset + (index * (maxOffset - minOffset) / (numCircles - 1)); var adjustedMin = variation; var adjustedMax = 1 - variation; // Apply variation only to the first circle if (index === 0) { value += minOffset / 2; // Skew the first value slightly } return Math.max(Math.min(value, adjustedMax), adjustedMin); } // Function to implement the Thomas algorithm for solving tridiagonal systems function thomas(a, b, c, d) { var n = a.length; var cp = []; // c prime var dp = []; // d prime var x = []; // solution for (var i = 0; i < n - 1; i++) { if (i === 0) { cp.push(c[i] / b[i]); dp.push(d[i] / b[i]); } else { cp.push(c[i] / (b[i] - a[i] * cp[i - 1])); dp.push((d[i] - a[i] * dp[i - 1]) / (b[i] - a[i] * cp[i - 1])); } } x.push((d[i] - a[i] * dp[i - 1]) / (b[i] - a[i] * cp[i - 1])); // i === n - 1 for (i = n - 2; i >= 0; i--) { x[i] = dp[i] - cp[i] * x[i + 1]; } return x; } // Spline function to calculate control points for the cubic Bézier curve function computeControlPoints(K) { var p1 = []; var p2 = []; var n = K.length - 1; // Right-hand side vectors var a = [], b = [], c = [], r = []; // Left-most segment a[0] = 0; b[0] = 2; c[0] = 1; r[0] = K[0] + 2 * K[1]; // Internal segments for (var i = 1; i < n - 1; i++) { a[i] = 1; b[i] = 4; c[i] = 1; r[i] = 4 * K[i] + 2 * K[i + 1]; } // Right-most segment a[n - 1] = 2; b[n - 1] = 7; c[n - 1] = 0; r[n - 1] = 8 * K[n - 1] + K[n]; // Solve Ax=b using Thomas algorithm for (var i = 1; i < n; i++) { var m = a[i] / b[i - 1]; b[i] = b[i] - m * c[i - 1]; r[i] = r[i] - m * r[i - 1]; } p1[n - 1] = r[n - 1] / b[n - 1]; for (var i = n - 2; i >= 0; --i) { p1[i] = (r[i] - c[i] * p1[i + 1]) / b[i]; } // Compute p2 values for (var i = 0; i < n - 1; i++) { p2[i] = 2 * K[i + 1] - p1[i + 1]; } p2[n - 1] = 0.5 * (K[n] + p1[n - 1]); return { p1: p1, p2: p2 }; } // Function to create a smooth path with cubic Bézier curves that pass through each circle's center function createSmoothPath(p, points) { // Extract X and Y positions separately var xPoints = points.map(function(p) { return p.x; }); var yPoints = points.map(function(p) { return p.y; }); // Calculate control points for x and y var controlPointsX = computeControlPoints(xPoints); var controlPointsY = computeControlPoints(yPoints); // Loop through each segment and draw the path p.startNewSubPath(xPoints[0], yPoints[0]); for (var i = 0; i < points.length - 1; i++) { var cp1X = controlPointsX.p1[i]; var cp1Y = controlPointsY.p1[i]; var cp2X = controlPointsX.p2[i]; var cp2Y = controlPointsY.p2[i]; var endPointX = xPoints[i + 1]; var endPointY = yPoints[i + 1]; // Draw the cubic Bézier curve for this segment p.cubicTo([cp1X, cp1Y], [cp2X, cp2Y], endPointX, endPointY); } } Panel1.setPaintRoutine(function(g) { g.fillAll(Colours.black); // Get the panel size var panelWidth = this.getWidth(); var panelHeight = this.getHeight(); // Calculate padding based on the division factors var paddingX = panelWidth / CPaddingX; var paddingY = panelHeight / CPaddingY; // Calculate the total distance to be covered by the spacing (excluding the radii and padding at the ends) var totalSpacing = panelWidth - (2 * paddingX) - (2 * Cradius); // Calculate the spacing between the centers of the circles var Cspacing = totalSpacing / (numCircles - 1); // Array to store Y positions for circles var circleYPositions = []; // Calculate the Y positions of the circles based on control values with variations for (var i = 0; i < numCircles; i++) { var adjustedValue = applyYVariations(controlValues[i].getValue(), i); var CcenterY = paddingY + Cradius + ((panelHeight - 2 * paddingY - 2 * Cradius) * adjustedValue); circleYPositions.push(CcenterY); } // Array to store the circle positions (X and Y) var circlePositions = []; for (var i = 0; i < numCircles; i++) { var CcenterX = paddingX + Cradius + (i * Cspacing); var CcenterY = circleYPositions[i]; circlePositions.push({ x: CcenterX, y: CcenterY }); } // Set the color for the path g.setColour(Colours.yellowgreen); // Create a new path and clear any previous content var p = Content.createPath(); p.clear(); // Create the smoothed path using cubic Bézier curves createSmoothPath(p, circlePositions); // Draw the path g.drawPath(p, p.getBounds(1), 1); // Draw the circles, centered with padding from the panel edges for (var i = 0; i < numCircles; i++) { // Get the circle position from the array var CcenterX = circlePositions[i].x; var CcenterY = circlePositions[i].y; // Draw the white stroked outline g.setColour(Colours.yellowgreen); g.drawEllipse([CcenterX - Cradius, CcenterY - Cradius, Cradius * 2, Cradius * 2], 1); // Draw the smaller solid white circle inside var innerCradius = Cradius * innerCircleRadiusFactor; g.fillEllipse([CcenterX - innerCradius, CcenterY - innerCradius, innerCradius * 2, innerCradius * 2]); } // Calculate the bounds for the rectangle var rectX = paddingX; var rectY = paddingY; // Start the rectangle from the top padding var rectWidth = panelWidth - 2 * paddingX; var rectHeight = panelHeight - 2 * paddingY; // The rectangle spans the full height within the Y padding g.setColour(0x5EFFFFFF); // Draw the rectangle around the circles' bounded Y space g.drawRect([rectX, rectY, rectWidth, rectHeight], 0.4); }); // Add mouse callback to move circles vertically Panel1.setMouseCallback(function(event) { var panelWidth = Panel1.getWidth(); var panelHeight = Panel1.getHeight(); var paddingX = panelWidth / CPaddingX; var paddingY = panelHeight / CPaddingY; var Cspacing = (panelWidth - (2 * paddingX) - (2 * Cradius)) / (numCircles - 1); if (event.doubleClick) { // Check if the double-click is within the detection area of any circle for (var i = 0; i < numCircles; i++) { var CcenterX = paddingX + Cradius + (i * Cspacing); var CcenterY = paddingY + Cradius + ((panelHeight - 2 * paddingY - 2 * Cradius) * controlValues[i].getValue()); if (Math.abs(event.x - CcenterX) <= selectionRadius && Math.abs(event.y - CcenterY) <= selectionRadius) { // Reset the Y control value of the selected circle to the default (0.5) controlValues[i].setValue(0.5); Panel1.repaint(); // Redraw the panel to update the circle's position return; // Exit after resetting to avoid further actions in this callback } } } if (event.clicked) { // Check if the click is within the detection area of any circle for (var i = 0; i < numCircles; i++) { var CcenterX = paddingX + Cradius + (i * Cspacing); var CcenterY = paddingY + Cradius + ((panelHeight - 2 * paddingY - 2 * Cradius) * controlValues[i].getValue()); if (Math.abs(event.x - CcenterX) <= selectionRadius && Math.abs(event.y - CcenterY) <= selectionRadius) { draggingIndex = i; // Start dragging this circle break; } } } if (draggingIndex != -1) { // Update the Y control value of the selected circle to follow the mouse var newValue = Math.max(Math.min((event.y - paddingY - Cradius) / (panelHeight - 2 * paddingY - 2 * Cradius), 1), 0); controlValues[draggingIndex].setValue(newValue); Panel1.repaint(); // Redraw the panel to update the circle's position } if (event.mouseUp) { draggingIndex = -1; // Stop dragging when the mouse is released } });
i have been messing about with more interactive / animated hise panels, and collaborating with chatGPT , so please let me know if this code works for you and if have any suggestions to make this code even better or simpler please share it !