RS-MET
RS-MET copied to clipboard
cleaning up redundant code
i just started to get rid of some code that is (for historical reasons) present in both rosic and rapt. i want to keep only the (templatized) rapt versions. that's a quite big clean up task, so i'll do it step by step incrementally (or should i say decrementally?) on the side. just for info. if some rosic function or class disappears, look for the replacement function in rapt
ok thanks!
moved a lot of code already into the attic: rosic\legacy\MovedToRAPT feels like a spring-cleaning. still lots of grunt work to do. having these double structures is the main thing that holds me back from straightening out the API inconsistencies - so when i'm done, i'm in a better position to actually (finally) offer a clean(er) API :-)
What is an example of cleaner API?
what's the difference between these and which one should I use?:
LOWPASS_IIT, // lowpass via impulse invariant transform
HIGHPASS_MZT, // highpass via matched-Z transform
LOWPASS_BLT, // lowpass via bilinear transform
HIGHPASS_BLT, // highpass via bilinear transform
you removed OnePoleStereo, are you creating a generic class for any number channels?
new mac error MetaControlledParameter::SetValue symbol not found for RAPT::rsClip<double,double>
the impulse-invariant transform discretizes the analog prototype filter in such a way, that the digital impulse response is equal to what you would get when you just sample the analog impulse response. this is most suitable for time domain work. the matched-z transform uses the same formula also for the zeros of the filter (not only the poles) - it's not impulse invariant anymore but it's the natural generalization of IIT for filters that have zeros. the bilinear transform preserves the relationship between magnitude and phase of the analog filter. it features this sort of frequency-warping/cramping of frequencies near the nyquist limit. what to use - i think, if the filter is to be used for frequency domain work and you also have oversampling, than BLT is probably the standard way to go
have a look at the files rosic/basics/rosic_TemplateInstantiations.h/cpp. there, i have now consolidated all the template instantiations. there's also this:
class rsOnePoleFilterStereo : public RAPT::rsOnePoleFilter<rsFloat64x2, double>
{
public:
inline void getSampleFrameStereo(double *inL, double *inR, double *outL, double *outR)
{
rsFloat64x2 tmp = getSample(rsFloat64x2(*inL, *inR));
*outL = tmp[0];
*outR = tmp[1];
}
};
this is now the stereo version of the one pole filter (parameters are still standard doubles but the signal is the SIMD 2-doubles-vector type). it should use the same cpu load as the mono version (i didn't measure in this case, but i once measured the same thing for EngineersFilter where it indeed worked)
new mac error MetaControlledParameter::SetValue symbol not found for RAPT::rsClip<double,double>
ok - i inlined the function and dragged it into the header file. that should fix it
error is still there and there is two other errors that I didn't mention earlier, commenting them out solved the problem:
duplicate explicit instantiation of RAPT:rsOnePoleFilteR<double, double> and RAPT::rsOnePoleFilter<rsFloat64x2, double>
You'll get this error when you build ToolChain on mac, but the Clip error is unique to RaPG.
comment out? what? where? if you exactly know how to fix it, can you just do it and send me a pull request? working on mac is always such a pita over here (slow, unresponsive, not my main dev machine, etc.)
When I say comment out, i mean comment out the class instantiation is rosic_TemplateInstantiations.cpp, that's not a solution, only a temporary fix... or maybe it is the solution? I dunno.
If I knew how to fix it, I would.
you mean, like this:
template class RAPT::rsOnePoleFilter<double, double>;
//template class RAPT::rsOnePoleFilter<rsFloat64x2, double>;
template class RAPT::rsSmoothingFilter<double, double>;
yes, except BOTH OnePoleFilters are throwing errors.
so in my synthesizers, I should use IIT/MZT.
you are using oversampling there, right? so the blt warping issue is probably not a big deal. so for a synth filter, i'd probably use BLT. IIT is nice for envelope generators/followers, i.e. time domain stuff. ....but actually, it probably doesn't make a big difference anyway
...now I understand what you mean by time vs frequency.
going to do this from now on so that if you change things again like this, I can just rename the function in one place.
oh no wonder we are getting errors with OnePoleFilter, did you mean to make the <rsFloat64x2,double> version the SAME NAME as the <double,double> version?
edit: wait im confused, you're just creating multiple instantiations of the class. So I'll try this:
yes - such things like making thin wrappers are generally a good idea - especially when dealing with an API that has not yet stabilized
robin, make up your mind! lol
yes yes yes....i know - that's what i mean with cleaning up the API...well...one of those things. there are still many other inconsistencies as well
OMGODD ardfodiufhndjh!!! I can't compile my function aliases because you already have them in MoreMath.h and since they are .h files they cause unresolved / undefined / already defined errors.
Sitting here trying to figure wtf is going on, damn Visual Studio doesn't tell you where the error is coming from.
I may have to invent my own names for functions or maybe ill try namespacing.
MoreMath.h? ...that's an ages old file that is not used anymore...is it even included somewhere? i don't think so. that's actually supposed to be dead code that's just still sitting there...just in case i may want for some unimaginable reason look at it again
ardfodiufhndjh!!!
How do you put things in namespaces without the namespace syntax? You have whole .h files in namespaces or something. Do you have a .h file with namespace {} and then you include .h files inside those brackets?
it's because the file that includes them wraps the namespace around the include statements, like in rapt/Math/Math.h:
namespace RAPT
{
#include "Misc/LinearAlgebra.h"
#include "Misc/Statistics.h"
#include "Misc/CurveFitting.h"
// ....blah blah blah....
f*** I've tried everything. Namespacing, not namespacing, using RAPT directly. inlining, not inlining, function definitions C++11 style, C++98 style, keeping the definition in .h, putting definition in cpp, still getting unresolved external symbols.
Using RAPT directly is working, need to get rid of the errors then try defining a function one at a time.
should i take a look myself? if so, which project should i attempt to build?
build Chaosfly, my functions are defined at the top of basic.h which is in ElanSynthLib/SynthesizerComponents/
Try swithing RAPT::rsPitchToFreq to pitchToFreq or elan::pitchToFreq, line 48 of ChaosflyCore.cpp
ok - i see. you are getting a lot of name clashes. i'll try to fix...
ok - done. chaosfly builds again. maybe there will be more problems popping up when building other projects. i will try to get rid of jura_MiscTools.h and directly use RAPT functions in my jura code instead
hah! there's even a "ToDo" comment for this already in the file...
still can't use elan::pitchToFreq in Chaosfly... just going to use RAPT, let's figure this out another time.
edit: but it's working in RhythmAndPitchGenerator. 😕
you mean this:
void ChaosflyCore::setOctaveOffset(double v)
{
frequency = elan::pitchToFreq(elan::freqToPitch(incomingFreq) + tuneOffset + (octaveOffset = v*12));
//....
}
...compiles without problems here
Could you put a jassert check or automatic conversion to acceptable XML variable for parameter names? Here's exampel code. Basically, no spaces, some special characters are bad( &< >'"/
), and cannot begin with a number, so if it begins with a number you can add an underscore at the beginning, or throw an error.
String convertToAcceptableXMLVariable(String s)
{
s = s.replaceCharacters("&<\' \"/>", "_______");
for (const auto & c :{ '0','1','2','3','4','5','6','7','8','9' })
{
if (s[0] == c)
{
s = "_"+s;
break;
}
}
return s;
}
ok, i could be convinced to include a jassert check in Parameter::setName. i think, (silently) "auto-correcting" what client code gives me would be somehow bad. juce XmlElement has the function isValidXmlName ...but that works for xml tag names, but parameters use attributes, so we have to write some isValidXmlAttributeName function ourselves. i tried to find an authoritative source for what is legal in xml attribute names and what's not. ...i only found this, so far: http://www.informit.com/articles/article.aspx?p=27865&seqNum=11 ...it's a start, but maybe not a definitive authority. i actually wonder why juce::XmlElement doesn't have such a function already. looks like an obvious omission
ok, done:
bool isValidXmlAttributeName(const juce::String& s)
{
int N = s.length();
if(N == 0)
return false;
if(!isLetter(s[0]))
return false;
for(int i = 1; i < N; i++)
if(!isLetterOrDigit(s[i]))
return false;
return true;
}
...not sure, if it might be too strict (i.e. may trigger false alert for actually valid names). it accepts only names that contain only letters and digits and start with a letter.
I'm having a bit of trouble with the new onepolefilters. Explosions, nans, infs. Here's one example:
ok, done:
bool isValidXmlAttributeName(const juce::String& s) { int N = s.length(); if(N == 0) return false; if(!isLetter(s[0])) return false; for(int i = 1; i < N; i++) if(!isLetterOrDigit(s[i])) return false; return true; }
...not sure, if it might be too strict (i.e. may trigger false alert for actually valid names). it accepts only names that contain only letters and digits and start with a letter.
you need to allow for underscore
you need to allow for underscore
ok, it should accept underscores now.
how can i reproduce the NaNs?
run chaosfly, play a midi note. Happens right away.
it just plays a sine'ish tone here. edit: your inputSignal
variable is already nan
Do you know why all my plugins fail au validation? made a thread: https://forum.juce.com/t/auvaltool-fail-format-errors-cannot-perform-render-tests/29800
Did you change something in your library that would cause this that I need to know about? ToolChain does not fail.
--------------------------------------------------
RENDER TESTS:
ERROR: Format errors. Cannot perform render tests
* * FAIL
--------------------------------------------------
AU VALIDATION FAILED: CORRECT THE ERRORS ABOVE.
--------------------------------------------------
Program ended with exit code: 255
You shouldn't be getting a sine, you should be getting silence. Chaosfly can't be working differently on your computer. Ensure you're not using an old dll build.
not using a dll - i'm running the standalone version. freshly built with freshly updated repo
are you using an init patch with oversampling 1? looks like oversampling 1 produces silence, oversampling 2 works
Did you change something in your library that would cause this that I need to know about? ToolChain does not fail.
well, i mean, i'm changing things here or there all the time (especially recently in my attempts to clean up the codebase) but from the top of my head, nothing that should break client code at runtime. since when does this occur?
are you using an init patch with oversampling 1?
looks like it. oversampling is at 1 (but it does produce sound). i guess, your version probably loads a hidden settings file in the background. for example, the standalone build apparently has created the file C:\Users\Rob\AppData\Roaming\Chaosfly.settings on my machine. edit: just deleted it, and started chaosfly again and it got recreated
radar generator passes auval. really frustrating not knowing what is going on, can't find any help online.
god wtf... ok I replaced all the code in my radar generator project with RaPG code (chaosfly and RaPG both fail, RaPG is a copy of Chaosfly project and edited), auvaltool passes.
Next step is to just copy my radar generator project, use that as a template for plugins moving forward. What on earth is going on....... the code is not the problem, what is?
maybe something in the settings in the jucer file? dunno, but that would be the next obvious place to look
I looked at everything I could think of, even jucer file. Hmm... what if I'm using the wrong au type? I'll try that. If that isn't it, f*** it!
i've tried searching for a reference for the error messages to figure out what the "ERROR: Format errors." wants to say - but no avail. apple's documentation seems to suck
Yep! That was it. "aumu" (kAudioUnitType_MusicDevice) succeeded. Wow, wasted an entire day figuring this out, precious time lost.
I got an inf from OnePoleFilter LOWPASS_BLT for setting the cutoff to 55096.
run RaPG set Amp/Fitler env to +1 Increase envelope decay to max You should get an inf, and the audio sounds terrible as you approach that.
Looks like a safe max for filter cutoff is samplerate * 0.5
Looks like a safe max for filter cutoff is samplerate * 0.5
oh - yes - that could well be. we were talking about this issue already recently here: https://github.com/RobinSchmidt/RS-MET/issues/233#issuecomment-422988391 i guess, i should figure out the limiting behavior of all my filter coefficient formulas and include that info into the api documentation. i don't really want to introduce safeguards at that level of the library, because they always have a cpu hit and sometimes they are not needed. in this case, if i'm not mistaken, you could switch to the IIT based design formula...(there are already some such comments in the code of rsFirstOrderFilterBase::coeffsLowpassIIT). or introduce a safeguard yourself at a higher level
That was it. "aumu" (kAudioUnitType_MusicDevice) succeeded. Wow, wasted an entire day figuring this out, precious time lost.
is this a setting in the jucer file or where do you set this? ....yeahh....i know.....this is frustrating....big reason why i prefer to stick to developing my math/dsp/algorithms stuff rather than sorting out all the pesky platform idiosyncrasies, making sure everything builds everywhere, create installers, bla bla bla - costs so much time and is totally uncreative
don't limit it, put debug-only asserts like jassert, this is helpful so that I can see where my plugin is setting cutoff too high by catching it in the act. Same goes for this, put a debug assert, don't do if statement.
also for setting samplerate, if a plugin is setting a samplerate of 0, that should be a red flag to fix something, so no need for if statement, put in debug assert:
(I put in samplerate as a quick test to see if limiting cutoff to half samplerate is safe)
That was it. "aumu" (kAudioUnitType_MusicDevice) succeeded. Wow, wasted an entire day figuring this out, precious time lost.
is this a setting in the jucer file or where do you set this? ....yeahh....i know.....this is frustrating....big reason why i prefer to stick to developing my math/dsp/algorithms stuff rather than sorting out all the pesky platform idiosyncrasies, making sure everything builds everywhere, create installers, bla bla bla - costs so much time and is totally uncreative
it is a setting in jucer, yes, the au type
you need to allow for underscore
fuck! why didn't anyone tell me that:
the rules for XML element names are also the rules for XML attribute names
https://docstore.mik.ua/orelly/xml/xmlnut/ch02_04.htm
which implies, i actually can use XmlElement::isValidXmlName for attributes also
don't limit it, put debug-only asserts like jassert, this is helpful so that I can see where my plugin is setting cutoff too high by catching it in the act. Same goes for this
yep - for the shelving gain, i agree - but for the cutoff freq, i think i actually can invoke l'Hospital's rule at the singularity ....although....i'm not really sure, if that is really the most reasonable thing to do. i guess, we may then see aliasing in the sense of: you request a cutoff of sr/2 + x
and the filter will get an actual cutoff of sr/2 - x
...i think that what be what the BLT formula would do, when requesting cutoffs above the nyquist limit....sooo limiting is perhaps the more reasonable way to deal with that. i'll set up an experiment to figure these things out exactly
There may be a problem building x86 Win32, can you see if OnePoleFilter builds for you in Win32?
ahhh...this again... yeah - i think i know how to fix this....some grunt work - scheduled for tuesday (when i have plumbers in the house and therefore can't focus on creative work anyway)
oh - this was actually just a small change (i'm done and the plumbers are not even here yet...what to do then?...haha). i expected having to make that change in far more places, but just one was sufficient. this thing occurs when you instantiate a template with rsFloat64x2 as template parameter and try to compile for 32 bit. the cure is to pass function parameters by (const) reference instead of by value. currently, we only instantiate rsOnePoleFilter with rsFloat64x2 for the signal type. as soon as we want rsFloat64x2 also for the parameter type (if we want different cutoffs for the two channels, for example), i'll have to make the same change also to setCutoff, etc.
at some point, i should probably consistently use const reference parameters everywhere in rapt. but that would indeed be a lot of grunt work and a considerable code uglification.
this should be moved to discussion or closed