HISE Logo Forum
    • Categories
    • Register
    • Login
    1. HISE
    2. HISEnberg
    3. Topics
    • Profile
    • Following 0
    • Followers 6
    • Topics 77
    • Posts 895
    • Groups 1

    Topics

    • HISEnbergH

      Reference External C++ Node as Audio Sample script - is it possible?

      Watching Ignoring Scheduled Pinned Locked Moved Solved Feature Requests
      11
      1 Votes
      11 Posts
      253 Views
      HISEnbergH

      @Christoph-Hart I'll try it again but last time I tried it failed to compile. The recorder node is more or less what I am after though. There's a number of features my node possesses that aren't featured here like playback speed, reversing, etc. But I should study this node and see if I can't replicate it.

    • HISEnbergH

      Get Audio File Length Independent of Audio Looper Start/End Points

      Watching Ignoring Scheduled Pinned Locked Moved Solved Feature Requests
      14
      0 Votes
      14 Posts
      720 Views
      HISEnbergH

      @d-healey I appreciate you looking into this, I'm learning quite a bit from your work here as well!

    • HISEnbergH

      WebView - Preset Browser not working in Standalone but works in HISE?

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved General Questions
      6
      0 Votes
      6 Posts
      325 Views
      StraticahS

      @HISEnberg Yes HISE tutorial then custom UI instead of the simple HTML list.

      I never compiled as standalone tho?

      here is my adjusted script from Example:
      Its probably not usable and makes it even harder to debug but might give enough context.

      The HSIE example worked inside a VST for me i believe.

      /** Custom User Preset Browser using a webview! This example project shows how to use a webview to implement a custom preset browser using a HTML webview. It supports bidirectional synchronisation, so if you load a user preset, it will update the selection in the webview and vice versa! The state here is just a single knob that will send it's value to the webview to be displayed. The HTML side only consists of a javascript file that defines the callbacks and populates a standard HTML select element. You probably want to use something more fancy in the end, but the communication will be pretty similar. */ // All const var declarations must be at the very top in HISE const var userPresetObject = []; const var expansions = Engine.getExpansionList(); const var expansionInfo = []; const var wv = Content.getComponent("WebView1"); const var webroot = FileSystem.getFolder(FileSystem.AudioFiles).getParentDirectory().getChildFile("Images/preset-browser"); const var uph = Engine.createUserPresetHandler(); var expansion = null; var expansionPresetFolder = null; var expansionPreset = null; var userPresetsFolder = null; var expansionFolders = []; var presetPath = null; var pathParts = null; var webviewInitialized = false; // Flag to prevent re-initialization var expansionFolderName = null; var folderExists = false; var j = 0; var k = 0; var expansionObject = null; var rootFolder = null; var folderName = null; var wildcardRef = null; var sourceArtwork = null; var artworkFolder = null; var targetFileName = null; var targetFile = null; const var initTimer = Engine.createTimerObject(); const var startupTimer = Engine.createTimerObject(); const var presetTimer = Engine.createTimerObject(); //Content.makeFrontInterface(600, 600); // This is required because JS will mess up the "\\" path on Windows inline function getEscapedFilePath(file) { return file.toString(0).replace("\\", "/"); } // Let's build up the preset database. For our example we'll use an array of // JSON objects with a `name` and a `file` key that will be consumed by the Webview and // populate the select element, but you're free to attach whatever other things you might need // Get root presets for(userPreset in FileSystem.findFiles(FileSystem.getFolder(FileSystem.UserPresets), "*.preset", true)) { userPresetObject.push({ "name": userPreset.toString(1), "file": getEscapedFilePath(userPreset) }); } // Get expansion presets Console.print("Found " + expansions.length + " expansions"); // Collect expansion info for the webview var expansionFolders = []; // Track unique expansion folder names for(i = 0; i < expansions.length; i++) { expansion = expansions[i]; Console.print("Processing expansion: " + expansion.getExpansionType()); // Try to get expansion root folder and look for UserPresets subfolder expansionPresetFolder = expansion.getRootFolder(); if(expansionPresetFolder) { Console.print("Expansion root folder: " + expansionPresetFolder.toString(0)); // Look for UserPresets folder within the expansion userPresetsFolder = expansionPresetFolder.getChildFile("UserPresets"); if(userPresetsFolder) { Console.print("Found UserPresets folder in expansion: " + userPresetsFolder.toString(0)); // Get presets from this expansion's UserPresets folder for(expansionPreset in FileSystem.findFiles(userPresetsFolder, "*.preset", true)) { userPresetObject.push({ "name": expansionPreset.toString(1), "file": getEscapedFilePath(expansionPreset) }); // Extract expansion folder name from the preset path (0.2.2 working approach) presetPath = getEscapedFilePath(expansionPreset); pathParts = presetPath.split("/"); // Look for the expansion folder name in the path // Typically: .../Expansions/ExpansionName/UserPresets/... for(j = 0; j < pathParts.length; j++) { if(pathParts[j] == "Expansions" && j + 1 < pathParts.length) { expansionFolderName = pathParts[j + 1]; // Check if we already have this folder name folderExists = false; for(k = 0; k < expansionFolders.length; k++) { if(expansionFolders[k] == expansionFolderName) { folderExists = true; break; } } if(!folderExists) { expansionFolders.push(expansionFolderName); Console.print("Found expansion folder: " + expansionFolderName); } break; } } } } else { Console.print("No UserPresets folder found in expansion: " + expansion.getExpansionType()); } } else { Console.print("No root folder found for expansion: " + expansion.getExpansionType()); } } // Convert array to expansion info for the webview // Metadata for known expansions: descriptions and tags var expansionMeta = { "Hardware-Lab": { "description": "A collection of distorted, textured sounds with that classic, vintage synth touch. Expect experimental tones, heavy synth sounds, glitches, and that analog character processed through hardware pedals.", "tags": "Analog, Bright, Vintage" }, "Immersive": { "description": "Cinematic sounds inspired by legendary film composers like Hans Zimmer and Ludwig Gรถransson, but also epic composers in the rap industry such as Mike Dean. Cinematic, Melodic, and built for epic atmospheres.", "tags": "Epic, Melodic, Cinematic" }, "Pro-Essentials": { "description": "Your go-to expansion of proven sounds, first designed after studying the sound behind various hit songs of popular albums. Everything from simple and essential sounds to carefully processed and reliable tones.", "tags": "Essential, Polished, Reliable" } }; for(i = 0; i < expansionFolders.length; i++) { // Use the expansion handler approach - get the expansion object expansionObject = null; for(j = 0; j < expansions.length; j++) { expansion = expansions[j]; rootFolder = expansion.getRootFolder(); if(rootFolder) { // Handle Windows/Mac path compatibility var rootPath = rootFolder.toString(0).replace("\\", "/"); folderName = rootPath.split("/").pop(); if(folderName === expansionFolders[i]) { expansionObject = expansion; break; } } } // Use specific metadata if available, otherwise fallback var meta = expansionMeta[expansionFolders[i]]; var expansionDescription = meta ? meta.description : ("High-quality presets for " + expansionFolders[i]); var expansionTags = meta ? meta.tags : ""; // Use HISE founder's method - generate complete HTML with {EXP::...} syntax // Use exact expansion folder name (with spaces) for {EXP::...} syntax var expansionNameFormatted = expansionFolders[i]; // Keep original name with spaces var expansionHTML = '<img class="expansion-cover" src="{EXP::' + expansionNameFormatted + '}artwork.png" alt="' + expansionFolders[i] + ' cover art" onerror="this.style.display=\'none\';" />'; Console.print("Generated HTML for " + expansionFolders[i] + ": " + expansionHTML); expansionInfo.push({ "name": expansionFolders[i], "type": "expansion", "description": expansionDescription, "tags": expansionTags, "htmlContent": expansionHTML }); } Console.print("Total presets found: " + userPresetObject.length); Console.print("Total expansion folders found: " + expansionInfo.length); // Debug: Show what we're sending to the webview Console.print("Expansion info being sent to webview:"); for(i = 0; i < expansionInfo.length; i++) { Console.print(" " + expansionInfo[i].name + " - " + expansionInfo[i].coverArt); } // Grab a reference to our little budddy // That's a bit ugly, but we grab the image folder by getting the HISE project AudioFiles folder // and then doing some next level-hacking to get a subdirectory of the Images folder which I think is a nice // place for web stuff... // Call this to make sure that there is no intermediate temp stuff being carried around wv.reset(); // set the index file (this is already the default, but I'll call it here so that you know it exists) wv.setIndexFile(webroot.getChildFile("index.html")); // Enable caching for better performance //wv.set("enableCache", true); wv.set("enablePersistence", true); // Initialize webview with proper timing inline function initializeWebview() { Console.print("=== INITIALIZING WEBVIEW ==="); // Wait a bit for webview to be ready, then populate data initTimer.setTimerCallback(function() { Console.print("=== POPULATING WEBVIEW DATA (TIMER) ==="); Console.print("Current HISE zoom level: " + Settings.getZoomLevel()); // Now we call the updatePresetList function that is defined in the Javascript of the Webview // (and tucked onto the global `window` object). wv.callFunction("updatePresetList", userPresetObject); // Also populate the left panel with expansion info wv.callFunction("updateExpansionPanel", expansionInfo); Console.print("=== WEBVIEW DATA POPULATED (TIMER) ==="); this.stopTimer(); }); initTimer.startTimer(500); // Wait 500ms for webview to be ready } // Add webview ready callback to ensure data is sent when webview is actually ready wv.bindCallback("webviewReady", function(args) { Console.print("=== WEBVIEW READY CALLBACK TRIGGERED ==="); Console.print("Current HISE zoom level: " + Settings.getZoomLevel()); // Send data to webview now that it's confirmed ready // HISE should handle webview scaling automatically wv.callFunction("updatePresetList", userPresetObject); wv.callFunction("updateExpansionPanel", expansionInfo); Console.print("=== DATA SENT TO READY WEBVIEW ==="); }); // Note: Scale factor handling removed - letting HISE handle webview scaling natively // The webview should automatically scale when HISE's zoom level changes // Initialize the webview with a delay to ensure it's ready startupTimer.setTimerCallback(function() { Console.print("=== STARTING WEBVIEW INITIALIZATION ==="); initializeWebview(); this.stopTimer(); }); startupTimer.startTimer(200); // Wait 200ms before initializing inline function onKnob1Control(component, value) { // This just simulates the communication from HISE -> WebView // (the function window.updateValue() is defined in browser.js) wv.callFunction("updateValue", value); }; Content.getComponent("Knob1").setControlCallback(onKnob1Control); // This binding will call the given function when the Webview is // calling the loadUserPreset function (which happens in the onselection callback) wv.bindCallback("loadUserPreset", function(args) { Console.print("LOAD FROM WEBVIEW"); Console.print("Args received: " + args); Console.print("Args[0]: " + args[0]); Console.print("Args[0] type: " + typeof args[0]); Console.print("Checking if args[0] == '__REQUEST_CURRENT_PRESET__': " + (args[0] == "__REQUEST_CURRENT_PRESET__")); // Check if this is a test from filter click if (args[0] == "__FILTER_CLICKED_TEST__") { Console.print("๐ŸŽฏ FILTER CLICKED - BROWSER CAN CALL HISE!"); return; } // Check if this is a request for current preset if (args[0] == "__REQUEST_CURRENT_PRESET__") { Console.print("=== REQUEST CURRENT PRESET FROM WEBVIEW ==="); Console.print("getUserPresetList() returned: " + Engine.getUserPresetList().length + " presets"); Console.print("uph object available: " + (typeof uph !== 'undefined')); if (typeof uph !== 'undefined') { Console.print("uph.getCurrentUserPresetFile available: " + (typeof uph.getCurrentUserPresetFile === 'function')); Console.print("getCurrentUserPresetFile() result: " + uph.getCurrentUserPresetFile()); if (uph.getCurrentUserPresetFile()) { Console.print("Sending back to webview: " + getEscapedFilePath(uph.getCurrentUserPresetFile())); wv.callFunction("setSelectedPreset", getEscapedFilePath(uph.getCurrentUserPresetFile())); } else { Console.print("No current preset file found"); } } Console.print("=== END REQUEST CURRENT PRESET ==="); } else { Engine.loadUserPreset(FileSystem.fromAbsolutePath(args[0])); } }); // This binding will call the given function when the Webview is // calling the savePresetInHise function (which happens when saving a preset) wv.bindCallback("savePresetInHise", function(args) { Console.print("=== SAVE PRESET CALLBACK TRIGGERED ==="); Console.print("SAVE FROM WEBVIEW"); Console.print("Args received: " + args); Console.print("Args type: " + typeof args); Console.print("Args length: " + (args ? args.length : "null")); if (args && args.length > 0) { var filePath = args[0]; Console.print("File path received: " + filePath); // Create folder if the path contains a slash (indicating subfolder) var userPresetsDirectory = FileSystem.getFolder(FileSystem.UserPresets); Console.print("UserPresets directory: " + userPresetsDirectory.toString(0)); // Handle Windows/Mac path compatibility for folder detection var normalizedPath = filePath.replace("\\", "/"); if (normalizedPath.contains("/")) { var folder = normalizedPath.split("/")[0]; Console.print("Creating folder: " + folder); var folderCreated = userPresetsDirectory.createDirectory(folder); Console.print("Directory created: " + folderCreated); } // Create a File object from the path var presetFile = userPresetsDirectory.getChildFile(filePath); Console.print("Created file object: " + presetFile.toString(0)); // Save the current preset to this file (remove .preset extension for Engine.saveUserPreset) var presetPath = presetFile.toString(0).replace(".preset", ""); Console.print("Preset path for Engine.saveUserPreset: " + presetPath); // Call Engine.saveUserPreset with the path string Engine.saveUserPreset(presetPath); Console.print("โœ… Engine.saveUserPreset() called successfully"); Console.print("โœ… Preset save process completed"); } else { Console.print("โŒ Invalid preset data received"); Console.print("Expected: file path string"); Console.print("Received: " + args); } Console.print("=== END SAVE PRESET DEBUG ==="); }); // This binding will call the given function when the Webview is // calling the overridePreset function (which happens when overriding current preset) wv.bindCallback("overridePreset", function(args) { Console.print("=== OVERRIDE PRESET CALLBACK TRIGGERED ==="); Console.print("OVERRIDE FROM WEBVIEW"); // Get the current user preset file path if (typeof uph !== 'undefined' && typeof uph.getCurrentUserPresetFile === 'function') { var currentPresetFile = uph.getCurrentUserPresetFile(); Console.print("Current preset file: " + currentPresetFile); if (currentPresetFile) { // Extract the path without extension for Engine.saveUserPreset var presetPath = currentPresetFile.toString(0).replace(".preset", ""); Console.print("Preset path for Engine.saveUserPreset: " + presetPath); // Call Engine.saveUserPreset with the current preset path Engine.saveUserPreset(presetPath); Console.print("โœ… Engine.saveUserPreset() called successfully for override"); Console.print("โœ… Preset override process completed"); // Send success callback to webview wv.callFunction("onOverrideSuccess", currentPresetFile.toString(0)); } else { Console.print("โŒ No current preset file found - cannot override"); wv.callFunction("onOverrideError", "No current preset selected"); } } else { Console.print("โŒ UserPresetHandler not available"); wv.callFunction("onOverrideError", "UserPresetHandler not available"); } Console.print("=== END OVERRIDE PRESET DEBUG ==="); }); // This will attach a WebView function call to anytime a user preset is loaded // and will update the selection (window.setSelectedPreset is defined in browser.js) uph.setPostCallback(function(presetFile) { Console.print("=== PRESET LOADED CALLBACK ==="); Console.print("Raw presetFile: " + presetFile); Console.print("Type of presetFile: " + typeof presetFile); Console.print("Escaped path: " + getEscapedFilePath(presetFile)); Console.print("=== END PRESET LOADED CALLBACK ==="); wv.callFunction("setSelectedPreset", getEscapedFilePath(presetFile)); }); // Handle request for current preset selection from webview Console.print("=== BINDING REQUEST CURRENT PRESET CALLBACK ==="); wv.bindCallback("requestCurrentPreset", function(args) { Console.print("=== REQUEST CURRENT PRESET FROM WEBVIEW ==="); // Try to get current preset using Engine API Console.print("getUserPresetList() returned: " + Engine.getUserPresetList().length + " presets"); // Try to get current preset file from uph Console.print("uph object available: " + (typeof uph !== 'undefined')); if (typeof uph !== 'undefined') { Console.print("uph.getCurrentUserPresetFile available: " + (typeof uph.getCurrentUserPresetFile === 'function')); Console.print("getCurrentUserPresetFile() result: " + uph.getCurrentUserPresetFile()); if (uph.getCurrentUserPresetFile()) { Console.print("Sending back to webview: " + getEscapedFilePath(uph.getCurrentUserPresetFile())); wv.callFunction("setSelectedPreset", getEscapedFilePath(uph.getCurrentUserPresetFile())); } else { Console.print("No current preset file found"); } } Console.print("=== END REQUEST CURRENT PRESET ==="); }); Console.print("=== REQUEST CURRENT PRESET CALLBACK BOUND ==="); // Trigger preset selection update when webview loads // This handles the case where plugin reopens with a preset already loaded Console.print("=== PRESET SELECTION HANDLED BY UPH CALLBACK ==="); // This is just a zoom factor combobox that demonstrates the correct scaling // of the WebView - HISE handles webview scaling natively inline function onZoomFactorControl(component, value) { if(value) { Settings.setZoomLevel(component.getItemText()); Console.print("Zoom changed to: " + component.getItemText() + " - HISE will handle webview scaling automatically"); } }; Content.getComponent("ZoomFactor").setControlCallback(onZoomFactorControl);

      Also make sure if offline you have persistance and cache enabled.
      I also clear the exported_webviews folder from time to time

      If it works in HISE it usually works in VST build aswell at least on my end.
      The scaling and initializing bugs i had were both in HISE and build.

    • HISEnbergH

      Trying to Embed Audio Files into Plugin Binary - file_player node causing issues?

      Watching Ignoring Scheduled Pinned Locked Moved Solved General Questions
      2
      0 Votes
      2 Posts
      81 Views
      HISEnbergH

      @HISEnberg Okay I see my error now. I was loading the audio files from the Audio Files folder (using the File System API) and not the Pool which explains why it works in HISE but not in the compiled plugin.

      So for anyone else who comes here the answer looks something like this:

      const var audioFileList = Engine.loadAudioFilesIntoPool(); // get the audio files from the pool const var AudioReference = Synth.getAudioSampleProcessor("AudioReference"); const var cmb_MatchLoader = Content.getComponent("cmb_MatchLoader"); cmb_MatchLoader.set("items", ""); for (file in audioFileList) { var displayName = file.replace("{PROJECT_FOLDER}", "").replace(".wav", ""); cmb_MatchLoader.addItem(displayName); } inline function oncmb_MatchLoaderControl(component, value) { if (value > 0) { AudioReference.setFile(audioFileList[value - 1]); } } cmb_MatchLoader.setControlCallback(oncmb_MatchLoaderControl);
    • HISEnbergH

      Preset Next/Previous Buttons - How to navigate different categories?

      Watching Ignoring Scheduled Pinned Locked Moved Solved Scripting
      8
      0 Votes
      8 Posts
      204 Views
      HISEnbergH

      @d-healey @Oli-Ullmann haha yes that's why I will leave it up. I think I learned about this before (watching David's video) and just sort of forgot about what the boolean was for. ๐Ÿ˜†

    • HISEnbergH

      Project Info - Version Number

      Watching Ignoring Scheduled Pinned Locked Moved Solved General Questions
      6
      0 Votes
      6 Posts
      440 Views
      HISEnbergH

      @Christoph-Hart I gave this a shot but this wasn't the solution. It's my mistake.

      @d-healey you are exactly right.

      Basically for anyone who ends up here I recommend looking at and comparing the Info.plist that is part of the .component bundle. In my case I had changed the company code and this is why the plugin wasn't being recognized properly. Strange I couldn't find this in my Github commits but my issue had nothing to do with the version number.

      Thanks both for your responses!

    • HISEnbergH

      Compiling C++ nodes and Scriptnode Networks

      Watching Ignoring Scheduled Pinned Locked Moved Solved Bug Reports
      39
      0 Votes
      39 Posts
      3k Views
      ustkU

      @Christoph-Hart Nice thanks! ๐Ÿ‘

    • HISEnbergH

      Dynamic Container - how to use?

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved Scripting
      5
      3 Votes
      5 Posts
      1k Views
      oskarshO

      @Christoph-Hart can u share the example here would love to explore as well!

    • HISEnbergH

      FFTW3 in C++ node - how to?

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved C++ Development
      6
      0 Votes
      6 Posts
      803 Views
      HISEnbergH

      @HISEnberg Still can't seem to figure this out. I have an extra folder in my HISE project named External, which contains the bulk of my C++ code.

      I've changed methods to adding this from FFTW3 directly into my project:

      fftw3.h
      libfftw3-3.lib
      libfftw3-3.dll

      And in my external C++ node I am doing something like this:

      #define HAVE_FFTW 1 #define FFTW_DLL #pragma comment(lib, "../../External/libfftw3-3.lib")

      But every time the compiler is failing to link:

      !LINK : fatal error LNK1104: cannot open file '../../External/libfftw3-3.lib' [C:\Users\mikez\Desktop\HiseProjects\Personal\fftw-test\DspNetworks\Binaries\Builds\VisualStudio2022\fftw-test_DynamicLibrary.vcxproj]
    • HISEnbergH

      Preset Browser in CSS

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved Scripting css preset browser bugzzz
      3
      10 Votes
      3 Posts
      757 Views
      HISEnbergH

      @d-healey Nice thanks for clarifying, that does open up a bit more possibilities.

      I'm trying some things to hack around it so I can get the best of both worlds. For instance, in CSS I am not seeing a way of distinguishing the list items by column. The items in bank > category > preset are all drawn the same in CSS.

    • HISEnbergH

      Multichannel Routing Broken

      Watching Ignoring Scheduled Pinned Locked Moved Bug Reports
      1
      0 Votes
      1 Posts
      95 Views
      No one has replied
    • HISEnbergH

      External C++ Node file management

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved C++ Development
      7
      0 Votes
      7 Posts
      721 Views
      HISEnbergH

      @Christoph-Hart You move quick! Glad I mentioned it, my HISE-senses were tingling when I heard about this project. :)

      Are you considering integrating the klang toolchain for rapid C++ deployment inside Scriptnode? I've been trying to find faster methods like this.

      On another tangent which I don't think anyone else here cares about except for me, is the introduction of MIDI 2.0 to the JUCE Framework. Obviously this will take a bit of time, as there really aren't any major devices on the market that even support this yet, but it would be good to keep an eye on this development and possible integration into HISE in the future!!!!

    • HISEnbergH

      Audio FX - Play an audio file?

      Watching Ignoring Scheduled Pinned Locked Moved Solved General Questions
      7
      0 Votes
      7 Posts
      212 Views
      HISEnbergH

      Cool just to confirm for anyone else who ends up here, it does indeed work with the file_player in scriptnode

      HiseSnippet 1448.3ocuX8zSabDEeVCiSvoIsopsms5IRUDxFLjf5gXL1t0sAvB6PiTOfF1cLdj2cls6NKXmnHkC8P+Vzy8qP+1zC8d9Fz9dyt16t0FJXQqQB44OuY9898dueuA5Fnr4ggp.hUo9S74DqOh1ahTOb+gLgjzoIw5SnsGuWjiPcTjtOOTSZLwmEFxcHVVq7M3trVaUh4yGdQClKSZySmhPNQIr4uT3Izoy1s92Kbcayb38EdY1cs5crUx8UtpH.QqPqP7Y1iXmyOjgaq.k7srvgDquht8laYWy4YNat416tiMaG9tCXCFTcKmZ01446VcqcY0d9N7JaSrJ1xQnUA8zLMODNzFJmI8FptTFeAmHBEm4xwAUI8faNdZx9CEtNcmROgDh0pcSIqUhIqOidfvQLa9rjFtP4TKxRZVEtNHU8V.IqLPZ0XH8XZO6.guNcEDOOf1Qp4ACXPrIKTh2Kw5Oo6qfMH0a3wFwaG.ClYv5aVoxSKC+5IecoRsjmKj7MbULGSRQagKOD1ppqR4tNtiRChj1ZgRVVIOTo4GIW+Ikdao0J8tRk+mKMXvBWCwRfx0kGrvkwblfqyv0kQdmwCdZ4KXtQ7YaD3n7DewaFwaGSMY1nR1QJzG4ySF2V45fDJ984CSjDtEBXERPHb2ZS35ySBWFx7GXWvGnB7HBGLEJ2bUIFmIakkCSyHVeI8scO9nuq098Os8QurYqie2IBkKWW9PkHjuwkrKHAL44bvoCfHM0BM0LSKoCN9298hwPzfqUhw0iRvUiHsVIM.ZMZ7fEfDxq5zDACjRk3qf+6yCzBjlsZxu.z.hyOWi1jGNRq7MjgmuRhLiE8VSGiyBfIYG3Ok663XzyLmX41uFiMo2XwafidE2w6+w5W8c3yB.wJn1AW4QzFZog46gtLY95UPoP4D4xz4kOPg0jEfT6b0rXgoLTnmjU38VnoT4Z0TtoP7wztBs8vEiwBK.iX1++AXLQI9gzVCFvs0o.bUZ6WurxtUt4xtz36uTRJ.bm3kmKiHKHNLxKU2Dq9vxwopv+BMULyOfCYR79pttrIqGx77c4GC.+okOyUYOpm3M74U.SxJaf6Xc6gLoj6FtLBkEui5PQNVEoExyOfoCDP0DE7+dPyca99InC4fBnFY73JSUn5wkNlA+E7IYwpyHLXwpSWLUdkbHWeoJXjIFk7ch08w.xWDKefjIO3zjX0XxdttpKQQAQRRLDhLy0U4NwenRJrwoh2wTLummJxnYY.dZEPioAlo9.7Xk9LgKVPzKJD5V3bjrGbNlWHYsxI7fPycdOZkMfefBjCUNvR2qMyFX+IcY5gXkF1.BRq4AaXOK89Jbnb4ZlGMcEaDuooOzJFsfS5YTFgmYgw5tSExPI7BVqjQROtD.GAE3EhS36DdBtpMykbRb+AfdvaINZXbrh3VeHc.vAm5a.DImq9ofqFv2H65y6P4s+58i7n1H+6xGOsWUlJwri.siNRG93oGXKnFwA5uaLKIo6.gLwKi2yArwyFaZnlg8vmNNcDjNlZZpzXp4ylqdOM2ONaJUlu2H9kwLV1YQV8QTLBeF7b4CPptOertuxblP4wE.Cf28CnuBbrAPpjCYNLzjOfE4pmadRFvu1MC7.PuUfuHzuSeGB5O7h8hzJO3LMciHWO8Wq9bdP8ecAzOn6bkdvGSOVozsC3+TDTdO4V6Ju+s0Wnq.yStCRdp+Gu4muF9+ATD4GipX29fvGdwUEDxWDXk0OhSYy83n69TqVigKSxby7HEnQcSQHCZd4jO2Y9TKyaYkbSKyv7CSTpwW3kWMpa1G+kjUSZnTi7Xl1RK0Ck+eoIpGyNPcpc76BP289lY.EToQ0cM5A33xK30+dvep6o114Op4Lbyk0vsVVCqsrFt8xZ3NKqgOaYM74+6Fh+mHRjCwTWnnpaq3VYVsjwUBPuUxeCPIPoOE
    • HISEnbergH

      The Audio Market Over the Next 10 Years

      Watching Ignoring Scheduled Pinned Locked Moved Blog Entries
      6
      6 Votes
      6 Posts
      848 Views
      ustkU

      Yeah as @d-healey says the audio pro industry is wide and DSP are everywhere from automotive the adaptive sound systems for venues and so on. I also think the plugin world will change in the future in the manner we are interacting with, and more AI/DSP research leads to the necessity of getting more and more specialised with tools that might not be simple to use for the "simple man". Of course the implementation of some tools is made easy sometimes, but then the top notch systems will always be ahead, broader, and more complex. And with complexity arises computation power and compatibility issues. I am happy to see many great tools arriving but afraid at the same time, not being able to catch up compared to specialised folks.
      In fact if I agree the market will grow, it might be for more engineered DAWs and tools integrating tech that I can't compete with for myself (like DAWs doing almost everything in the box, very "intelligent" plugins, automatic mixing tools, and other funky sweeteners...) while I am still struggling with basic DSP theory like I'm stuck in the 90s...
      But I might be off-topic lol

    • HISEnbergH

      Filter Display in External C++ Node

      Watching Ignoring Scheduled Pinned Locked Moved C++ Development
      1
      4 Votes
      1 Posts
      139 Views
      No one has replied
    • HISEnbergH

      Is this what I think it is? :D

      Watching Ignoring Scheduled Pinned Locked Moved General Questions
      7
      1 Votes
      7 Posts
      364 Views
      HISEnbergH

      @Lindon Yes I recall debating this a few months ago in one of the HISE meetings. You're essentially right as it looks like the dynamic container is essentially doing this anyways on the backend, just dumping the data to JSON (and writeToStream which is a new one I am not familiar with).

      Probably it boils down to preference, I like having as few UI components doing the heavy lifting with scripting.

    • HISEnbergH

      Windows codesigning certificate - Any suggestions?

      Watching Ignoring Scheduled Pinned Locked Moved Solved General Questions
      11
      1 Votes
      11 Posts
      558 Views
      bendursoB

      What about this? https://techcommunity.microsoft.com/blog/microsoft-security-blog/trusted-signing-is-now-open-for-individual-developers-to-sign-up-in-public-previ/4273554

      Some comments say it didn't work for them, but others say it did.

      @d-healey you may wanna check this https://signpath.org/. I found it on a github comment, not sure if it works.

    • HISEnbergH

      Procedure for writing our own API for HiseScript?

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved General Questions
      6
      0 Votes
      6 Posts
      322 Views
      HISEnbergH

      @Christoph-Hart Thank you for the nudge I was trying to find a good example to build from and this is giving me a better sense of the folder/file hierarchy relationship. I am still in the poke around the codebase and find out phase so will report back once I understand more.

      Happy to make a pull request to add it to the official version of HISE as well if I get it working, but I know this is a pretty niche case so unless there is a demand for it I won't bother!

    • HISEnbergH

      Floating Tile Keyboard - Possible to Rotate?

      Watching Ignoring Scheduled Pinned Locked Moved Unsolved Scripting
      9
      0 Votes
      9 Posts
      366 Views
      d.healeyD

      @HISEnberg Sure

      https://youtu.be/pmwC9Jmmwuo

      Ah you found it first :)