• Automatic Installer for Windows: Inno Setup Script

    Blog Entries
    9
    5 Votes
    9 Posts
    4k Views
    H

    Thank you for this script ! The samples you have in your "Downtown Grand Piano Samples" folder, are they archive files, monoliths ? I tried with archive files but it still asks for samples installation when loading the VST.

  • Full Expansions Included Scripts

    Scripting
    12
    0 Votes
    12 Posts
    31 Views
    S

    @David-Healey The Problem was that I was including the same Expansions.js in the actual Expansion! Ive commented that and deleted the file and is working in the exported Plugin!

  • 1 Votes
    3 Posts
    21 Views
    dannytaurusD

    @David-Healey I doubt it. Once you start notarising, I reckon you'll never stop.

  • Custom controls

    General Questions
    27
    0 Votes
    27 Posts
    72 Views
    MorphoiceM

    @David-Healey I rewired a test slider in my plugin as a panel-as-parameter exactly like you did in your example, no change in Cubase. I'm attempting to patch HISE to have that handle click gated

  • 0 Votes
    12 Posts
    128 Views
    B

    @David-Healey Thank you, kind sir.

  • 0 Votes
    11 Posts
    43 Views
    Y

    @Oli-Ullmann Ok,

    Thank you 🙏

  • Testers Needed for Rhapsody v3

    General Questions
    36
    1 Votes
    36 Posts
    1k Views
    David HealeyD

    @jeffd Thanks for confirming.

  • Bug: Wavetable only imports to left channel

    Bug Reports
    10
    0 Votes
    10 Posts
    76 Views
    dannytaurusD

    @paper_lung Gotcha. Not too far behind then. Still worth getting up to date though 👍

  • 1 Votes
    3 Posts
    181 Views
    B

    @VybeCodeDSP StripKit looks really nice!

    It seems you only support the Windows platform?
    If so, are you planning to support MacOS?
    If so, let me know if you need a beta tester!

  • waveform: draw loop position/crossfade

    General Questions
    2
    0 Votes
    2 Posts
    41 Views
  • Which version of faust works fine for HISE?

    Faust Development
    2
    0 Votes
    2 Posts
    74 Views
    David HealeyD

    @Sawatakashi said in Which version of faust works fine for HISE?:

    it crashed after i loaded a faust scriptnode.

    A blank node or are you copying in a script?

  • 0 Votes
    3 Posts
    94 Views
    griffinboyG

    @Phelan-Kane

    Here's a real life example of c++ modslots.

    It's not minimal i'm afraid but it shows it in use.
    If you'd like to see the minimal example, it's just as @ustk said, have a look at this post:
    https://forum.hise.audio/topic/14270/how-do-you-set-up-external-modulation-slots-c

    // ==============================| Griffin Poly EQ Filter |=================================== // // File: Griffin_EQFilter_Poly.h // Node: Griffin_EQFilter_Poly // Package: Griffin DSP Essentials for HISE // Author: Griffinboy // HISE Forum: https://forum.hise.audio/user/griffinboy // Copyright: Copyright (c) 2026 Griffinboy // // Description: // Minimum-phase EQ filter with per-voice state and frame processing. // Designed for sample-accurate modulation in synthesis contexts. // Uses more CPU than the block-rate Griffin_EQFilter. // // Has Mod slots for frequency, Q, and gain. // // License: // GNU General Public License v3.0 or later (GPL-3.0-or-later). // // This file is part of Griffin DSP Essentials for HISE. // // This program is free software: you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A // PARTICULAR PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with this // program. If not, see <https://www.gnu.org/licenses/>. // // ================================================================================================ #pragma once #include <algorithm> #include <cmath> #include <JuceHeader.h> #include "src/griffinboy/modules/essentials/eq_filter/eq_filter.h" namespace project { using namespace juce; using namespace hise; using namespace scriptnode; template <int NV> struct Griffin_EQFilter_Poly: public data::filter_node_base { using VoiceState = griffin::modules::essentials::eq_filter::EQFilterFrameProcessor; using PlotModel = griffin::modules::essentials::eq_filter::EQPlotModel; using Defaults = griffin::modules::essentials::eq_filter::EQFilterDefaults; PolyData<VoiceState, NV> voices; PlotModel plotModel; SimpleReadWriteLock topologyLock; double plotSampleRate = 44100.0; SNEX_NODE(Griffin_EQFilter_Poly); struct MetadataClass { SN_NODE_ID("Griffin_EQFilter_Poly"); }; static constexpr bool isModNode() { return false; }; static constexpr bool isPolyphonic() { return NV > 1; }; static constexpr bool hasTail() { return true; }; static constexpr bool isSuspendedOnSilence() { return true; }; static constexpr int getFixChannelAmount() { return 2; }; static constexpr int NumTables = 0; static constexpr int NumSliderPacks = 0; static constexpr int NumAudioFiles = 0; static constexpr int NumFilters = 1; static constexpr int NumDisplayBuffers = 0; void prepare(PrepareSpecs specs) { SimpleReadWriteLock::ScopedWriteLock sl(topologyLock); voices.prepare(specs); for (auto& voice : voices) voice.prepare(specs.sampleRate, specs.blockSize); plotModel.prepare(specs.sampleRate); plotSampleRate = specs.sampleRate > 0.0 ? specs.sampleRate : 44100.0; if (auto fd = dynamic_cast<FilterDataObject*>(this->externalData.obj)) fd->setSampleRate(plotSampleRate); sendCoefficientUpdateMessage(); voiceManager.prepare(specs); voiceManager.setActive(1.0); } void reset() { SimpleReadWriteLock::ScopedWriteLock sl(topologyLock); for (auto& voice : voices) voice.reset(); voiceManager.reset(); } void handleHiseEvent(HiseEvent& e) { voiceManager.handleHiseEvent(e); } template <typename T> void process(T& data) { if (auto sl = SimpleReadWriteLock::ScopedTryReadLock(topologyLock)) { static constexpr int NumChannels = getFixChannelAmount(); auto& fixData = data.template as<ProcessData<NumChannels>>(); auto& voice = voices.get(); auto fd = fixData.toFrameData(); while (fd.next()) voice.processFrame(fd.toSpan()); voiceManager.process(data); } } template <typename T> void processFrame(T& data) { if (auto sl = SimpleReadWriteLock::ScopedTryReadLock(topologyLock)) voices.get().processFrame(data); } int handleModulation(double& value) { ignoreUnused(value); return 0; } double getPlotValue(int getMagnitude, double freqNorm) override { if (getMagnitude == 0) return 0.0; const auto frequency = std::clamp(freqNorm, 0.0, 0.5) * plotSampleRate; return plotModel.getMagnitudeAtFrequency(frequency); } void setExternalData(const ExternalData& data, int index) { data::filter_node_base::setExternalData(data, index); ignoreUnused(index); if (auto fd = dynamic_cast<FilterDataObject*>(data.obj)) fd->setSampleRate(plotSampleRate); sendCoefficientUpdateMessage(); } void createExternalModulationInfo(OpaqueNode::ModulationProperties& info) { modulation::ParameterProperties::ConnectionList list; auto addParameterSlot = [&list](int parameterIndex) { modulation::ConnectionInfo slot; slot.connectedParameterIndex = parameterIndex; slot.modColour = HiseModulationColours::ColourId::FX; slot.connectionMode = modulation::ConnectionMode::Parameter; slot.modulationMode = modulation::ParameterMode::ScaleAdd; list.push_back(slot); }; addParameterSlot(2); addParameterSlot(3); addParameterSlot(4); info.fromConnectionList(list); info.setModulationBlockSize(Defaults::modulationBlockSize); } template <int P> void setParameter(double v) { if constexpr (P == 0) { SimpleReadWriteLock::ScopedWriteLock sl(topologyLock); const auto nextShape = (int)std::round(v); applyToVoices( [nextShape](VoiceState& filter) { filter.setType(nextShape); }); updatePlotFromFirstVoice( [this, nextShape] { plotModel.setType(nextShape); }); } else if constexpr (P == 1) { SimpleReadWriteLock::ScopedWriteLock sl(topologyLock); const auto nextSlope = (int)std::round(v); applyToVoices( [nextSlope](VoiceState& filter) { filter.setSlopeMode(nextSlope); }); updatePlotFromFirstVoice( [this, nextSlope] { plotModel.setSlopeMode(nextSlope); }); } else if constexpr (P == 2) { const auto value = (float)v; applyToVoices( [value](VoiceState& filter) { filter.setFrequencyHz(value); }); updatePlotFromFirstVoice( [this, value] { plotModel.setFrequencyHz(value); }); } else if constexpr (P == 3) { const auto value = (float)v; applyToVoices( [value](VoiceState& filter) { filter.setQ(value); }); updatePlotFromFirstVoice( [this, value] { plotModel.setQ(value); }); } else if constexpr (P == 4) { const auto value = (float)v; applyToVoices( [value](VoiceState& filter) { filter.setGainDb(value); }); updatePlotFromFirstVoice( [this, value] { plotModel.setGainDb(value); }); } } void createParameters(ParameterDataList& data) { { parameter::data p("Shape", { 0.0, 6.0, 1.0 }); StringArray names; addTypeLabels(names); p.setParameterValueNames(names); registerCallback<0>(p); p.setDefaultValue((double)Defaults::type); data.add(std::move(p)); } { parameter::data p("Slope", { 0.0, 3.0, 1.0 }); StringArray names; addSlopeLabels(names); p.setParameterValueNames(names); registerCallback<1>(p); p.setDefaultValue((double)Defaults::slopeMode); data.add(std::move(p)); } { parameter::data p("Frequency", { 20.0, 20000.0, 0.01 }); p.setSkewForCentre(1000.0); p.info.textConverter = parameter::pod::TextValueConverters::Frequency; registerCallback<2>(p); p.setDefaultValue(Defaults::frequencyHz); data.add(std::move(p)); } { parameter::data p("Q", { 0.025, 25.0, 0.001 }); p.setSkewForCentre(0.70710678); registerCallback<3>(p); p.setDefaultValue(Defaults::q); data.add(std::move(p)); } { parameter::data p("Gain", { -30.0, 30.0, 0.01 }); p.info.textConverter = parameter::pod::TextValueConverters::Decibel; registerCallback<4>(p); p.setDefaultValue(Defaults::gainDb); data.add(std::move(p)); } } private: static constexpr int getNumTypes() noexcept { return griffin::modules::essentials::eq_filter::EQFilterDesign::getNumTypes(); } template <typename Function> void applyToVoices(Function&& function) { // PolyData iteration follows HISE's poly callback. // Each active voice receives the parameter update in its own DSP state. for (auto& voice : voices) function(voice); } template <typename Function> void updatePlotFromFirstVoice(Function&& function) { // The plot is shared UI state. The first HISE voice owns graph updates // so voices do not compete for the displayed response. if (! voices.isVoiceRenderingActive() || voices.isFirst()) { function(); sendCoefficientUpdateMessage(); } } static void addTypeLabels(StringArray& names) { names.add("Lowpass"); names.add("Highpass"); names.add("Bandpass"); names.add("Notch"); names.add("Bell"); names.add("Low Shelf"); names.add("High Shelf"); } static void addSlopeLabels(StringArray& names) { names.add("12 dB/oct"); names.add("24 dB/oct"); names.add("48 dB/oct"); names.add("96 dB/oct"); } envelope::silent_killer<NV> voiceManager; }; } // namespace project
  • Animated modulation

    General Questions
    23
    0 Votes
    23 Posts
    407 Views
    ustkU

    @dannytaurus Yeah, keeping the colours tidy in your code is easier in the end. Then you can set the component colours from script when needed and everything updates automatically if you adjust something instead of copy/paste in all components...

    I tend to to everything I can in paint routines, the less components in the tree, the happier I am!
    That being said... In order to reduce CPU load, I still tend to keep fixed drawing (bg, mask, etc...) in separate panels so the LAF function job is only constrained to what is really necessary. I also keep all the math constants externally, unlike the example...

    Other issue with the "multiple panel masking technique" is that when you want to move it, it can be very annoying, unless adding them all in an holder panel, which is one more component... 😬

  • Trading DSP's!

    Scripting
    10
    1 Votes
    10 Posts
    223 Views
    C

    @Chazrox Have got a Glitch FX and a Granular Pitch Delay. Would be interested in the pitch and varispeed!

  • The Legato between samplers

    General Questions
    6
    0 Votes
    6 Posts
    171 Views
    David HealeyD

    @Felix-W Break it down. Make a minimal project with one sampler where notes only trigger during legato transitions. Once you get that working you can start to incorporate it into your project.

  • Get, post API Hise language.

    General Questions
    7
    0 Votes
    7 Posts
    106 Views
    Y

    @David-Healey Ok,

    Is it possible to discuss in private?

  • Stop pruning default values from XML?

    General Questions
    4
    0 Votes
    4 Posts
    158 Views
    David HealeyD

    @dannytaurus said in Stop pruning default values from XML?:

    because I'm setting some values in script that happen to be default values.

    Hmm this might be the source of an issue I was having too, I might try it.

  • One shared Script Voice Start Modulator for many Samplers?

    Scripting
    5
    0 Votes
    5 Posts
    150 Views
    observantsoundO

    @David-Healey Yes the Global Modulator Container worked beautifully for this.
    Thanks to your video I've now also understood the global modulator container better.

    Regarding the body + release in one sampler:
    That's what I've tried first, but it's bugged when using together with loop regions.
    It's what I described in this earlier post you commented on:
    https://forum.hise.audio/topic/14799/loud-click-artifact-when-using-releasestart-with-looping-enabled/14?_=1781354181861

    I haven't gotten around to testing it with 48kHz samples yet.
    But by now I've found enough use cases to split apart the sections into dedicated samplers.

  • 0 Votes
    3 Posts
    65 Views
    dannytaurusD

    @chimaera_09 Make the button show/hide a panel. Use the panel to house all your extra controls.

    const pnlSettings = Content.getComponent("pnlSettings"); const btnSettings = Content.getComponent("btnSettings"); btnSettings.setControlCallback(btnSettingsControl); inline function btnSettingsControl(component, value) { pnlSettings.showControl(value); // button shows/hides the panel }

    You can add a button in the panel to close it too:

    const btnSettingsClose = Content.getComponent("btnSettingsClose"); btnSettingsClose.setControlCallback(btnSettingsCloseControl); inline function btnSettingsCloseControl(component, value) { if (value) { pnlSettings.showControl(false); btnSettings.setValue(0); // sets the 'off' state of the button } }
  • 1 Votes
    1 Posts
    50 Views
    No one has replied