SNEX External data
-
I'm working on the additive synth with Loris using SNEX
Is there a way to programmatically and dynamically load audio files into a SNEX node via the external data? That way I can pass ratios/gains etc into the node and have everything all integrated nicely
Edit: ah just saw the Add External File Slot, is it related to this?
-
Here's an example using the external audio file slot with script node. Might help you with SNEX.
HiseSnippet 1250.3oc6W8zaaTDEeV6rI0lFAUhdeUN4HEhrgRAoJ.m3XSsnNwJNDUDBEMY2msG4YmY0tylDCBtvkdiy8FeD3J25W.NwWD9F.uYm0Y2E6DRrZpPHbjh76ey627l2+b+PoKDEICIVUNZZ.Prtu8foB03VioLAo6dDq21lE9LI0iIFcDDoH6NMfFEAdDKqxetVIqJqPR97Ge1tTNU3BYrHjikLW3YLelJia+leAiy6P8fiX94z9QM65JEsjbYLBnx10IAT2IzQv9TsZkrIVq11iojgCTTEDQrVYWo2zAikmKL5eLKhcJGzDMHCvCxvtij6oQrlKo0XF2q+rKdDgXY2OKLT1DFdW6dLO1k7yBGuSh.mLKxGOrJUDdkK.uF4gW8bvaAPxJGjVw.oGXOvMjEnxjnwyaY2UnfvgTLrmGJFcIk9AK6VRTCgZae5DnSHRboE0db85a4f+aymTsJF5iTNzXOlrCiCQNehSawHl.1liO+6bIezZYeojWKynHtTUOS+QfpkzOfCWrGUQODFBg.lVTaiKOjM1xYCCBc577FHUBBXCcpk4+s4fXjZrymhBqVQ6hFIHQKLmZec8uYymLLV3pXRgiTruTAGHpsY0uqZkpeeUm+tngCWnLcPJTx4P3BEqSTCuNCqIh8OEB2x4LJOFtTQ70qXJg8UmRjOi007lkSQonqfoNH.DWUdLI8gF+1W1UG404Qo7P8BfPESCAq8fyvhRSVUE68fnIJY.VVNWJGlrK8h4TUwJ.cYep.LFTHsSmZIhXpo4aK7Zqr3lBwGX2mobGuXLVZAXDiT2EXLsYx51sGNDbUY.bE6NO+toyQd2euqnk98SZIfTPXiWG8yCtw8ysJeWz+dk+00+9+qk9uPsTgov1F+WMcJL5SSoT1XrBfX+X+rQln0VkvqS5PYqWXmMAIHDBngvQx9b5zZQT8byCQfukyobo6jAruElerSfAW6p0nl6XpP.7nkY5zp23PUiq+k5PYrBWQrGUExt.uu38e.V16BsRQ2rXPJccMsNYY.H7RH9S7SpvFZZqTgMlIL27s8A04xvIIuQoemXsl4AIJIHexvKZP1gykmqWEgkl5hOLI75K4SCFKELWMKiFyP5N9xXzIov8ozninLtNWePbDN806.w.T4j1hVkOFBiRN30rquM9Gl6uuzCEY2g5hA1o8opw5hH2Ycb21MWe3bXsPxCdDyZaZhRHD80W8jkfKmaZtIIUSgkfkLmZ2ni0Rcobxw52aM3I5yzDuL3Sq55ZXcljGmDbJf3GZOjww0Di1NuJKKHI41GTigbkF4ovh4tBO3hYGXaLo0C67mXVZVPOlH8RYzoG8hBzj9zP7mKngdxp8ynvb8LSy5UkYdVO1AJHPW2Uf2D3bS.JOWcPbUrGtBHycJjasqa9SMucttJ9KW.O.abPl6z+Gb+W8p4u4X8VQ2+yu7k+57t+Ui9kG1T6db2QrcEV0eq89iZNm2ewueyt7M+Q+eK4xul8SYshUj4NFxc+a9518h4JlZbHP8ttauN2eWobhOMoa0xsX9ahdquI7gO0MTdhqYjjt57dIbvdEhjefeE6dZZmFjyRqn0MUI93Bam35pmz+d39eK1l2eIr4CVBadzRXyGtD173kvlOZIr4iuVaz6JuSrR5aFehL521zL1psfhaFjLIf7W75WoOL
-
@d-healey Yeah that should work, i'll test it properly tomorrow, cheers!
-
I'm getting a compilation error when exporting a SNEX node set to External Audio File slot:
c:\users\desktop\hise\hi_dsp_library\node_api\nodes\processors.h(851): error C2338: T must be base class of data: :base (compiling source file ..\..\Source\Main.cpp) [D:\Documents\HISE\Loris Toolbox\DspNetworks\Binaries\Builds\Visual Studio2017\Loris Toolbox_DynamicLibrary.vcxproj]
Compilation works normally until I change the set the node to use the external file slot. Is there any obvious reason this might be happening? are they only able to use embedded data at compilation time?
-
bump :) are snex nodes only able to use embedded data when compiled?
-
@Christoph-Hart need your help with this when you get a moment, it's the last piece of the prototype puzzle
-
@iamlamprey No, they should support dynamic external data - the granulator node was originally written in SNEX.
There are a few things you have to do though - I think you need to define a
static const int NumAudioFiles = 1;
at the top of your SNEX class definition to let the C++ generator know to create a slot (otherwise it won't derive from
data::base
hence your compilation error. -
@Christoph-Hart Yeah I already have that defined, and able to load files and read them into SNEX. Still getting the error when I try compiling the node. I've made a new one, and done the old "comment everything out and slowly add pieces back in" trick, and the culprit is definitely the audio file slot, I'm probably referring the data incorrectly or something
Here's the full node, if it helps:
template <int NV> struct snexModalSynth { /* NOTES 200 sines was about 8% cpu on i7 8700K with Path of Exile open (lol) in a non-compiled SNEX node performance might be a little bit worse with Dyn instead of Span stereo would obviously be 2x polyphony would be more as well... when working with dyns, it must have some data referral be aware, when changing dyn values, it will also overwrite the relative span's data (dyns can have their memory addresses changed) */ SNEX_NODE(snexModalSynth); double sr = 0.0; static const int NumAudioFiles = 1; const int numModes = 128; dyn<float> ratios; span<double, 128> uptimes; span<double, 128> deltas; float tick(int t) { return Math.sin(uptimes[t]); } // Initialise the processing specs here void prepare(PrepareSpecs ps) { sr = ps.sampleRate; } // Reset the processing pipeline here void reset() { for (int i = 0; i < uptimes.size(); i++) { uptimes[i] = 0.0; } } // Process the signal as frame here template <int C> void processFrame(span<float, C>& data) { for (auto& s : data) // For each sample { float original = s; for (int i=0; i < uptimes.size(); i++) // For each partial { s += tick(i); // need to add gains here... uptimes[i] += deltas[i]; } // make sine waves not explode my ears s *= 0.006; s += original; // bring level back up s *= 4; } } // Process the MIDI events here void handleHiseEvent(HiseEvent& e) { for (int i = 0; i < ratios.size(); i++) { const float scaledRatio = ratios[i] * 10.0; const double cyclesPerSecond = e.getFrequency() * scaledRatio; const double cyclesPerSample = cyclesPerSecond / sr; deltas[i] = 2.0 * 3.14159265359 * cyclesPerSample; } } // Use this function to setup the external data void setExternalData(const ExternalData& d, int index) { //refer this data to a dyn d.referBlockTo(ratios, 0); } template <int P> void setParameter(double v) {} template <typename ProcessDataType> void process(ProcessDataType& data) {} };
Sidenote, is it possible to instantiate a Span using another variable as the size parameter? I've been doing it manually so far:
const int numModes = 128; //both of these give errors span<double, numModes> deltas; span<double, int(numModes)> deltas;
-
You can use the
static
keyword to define a compile time constant (theconst
is just a hint to the compiler that you could cast away if you're into that kind of stuff).Another option is to use a preprocessor definition:
static const int NumElements = 12; #define NUM_ELEMENTS 12 span<int, NumElements> x1; span<int, NUM_ELEMENTS> x2
I tried to compile the node and got this error:
static_assert failed due to requirement 'std::is_base_of<scriptnode::data::base, script_fx1_impl::test_node<1>>() || std::is_base_of<scriptnode::data::base, script_fx1_impl::test_node<1>>()' "T must be base class of data::base"
So apparently I've implemented polymorphism in SNEX some time ago and forgot about it, so you need to derive your node from the
data::base
interface class in order to load external files:template <int NV> struct snexModalSynth: public data::base
Apart from that it compiles.
-
@Christoph-Hart awesome, i'll give it a spin on my end when i'm done rendering this unreal engine crap, cheers!
-
yep compiles successfully, thanks again :)
-