Do not use rack::settings::sampleRate

Hello,

I went through some debugging those days to fix a reported problem with the tCLK of OrangeLine SWING. Took me quite some time to find out what happened.

OrangeLine used rack::settings::sampleRate to get the engines sample rate, which is suboptimal. First, it does not reflect changes on the engines samplerate while running. Second and worse, was a side effect of the introduction of ‘Auto’ in the Engines Sample rate menu (what I like).

rack::settings::sampleRate shows up with 0 in this case and broke some of OrangeLines timing calculations.

Using the correct method APP->engine->getSampleRate (), the problem was fixed. Now SWING and OrangeLine modules no longer behave strange after changing the engines sample rate while running and SWING has a tCLK again also when using ‘Auto’.

I am bringing this up here because the usage of rack::settings::sampleRate didn’t come out of thin air, but copied from some example code I found on internet. So I might not be the only Rack developer who used this method.

So every developer should check his code for the use of rack::settings::sampleRate and use APP->engine->getSampleRate () instead. Maybe this fixes also some of the lately reported instabilities.

Regards,

Dieter (OrangeLine)

11 Likes

THANK YOU
. . . THANK YOU
. . . . . . THANK YOU

I’ve had a nasty Venom bug in my preferred DC blocker algorithm for over 6 months, preventing me from using it. The DC blocker would work fine on some machines, and not at all on others, and it was not platform specific. I was forced to resort to a DC blocker algorithm that did not take into consideration sampleRate, (or oversampling level), which was far from ideal.

It was infuriating - I could not reproduce the problem on any of my machines. The code is so simple, it didn’t seem like it could have a problem. I was almost convinced I had a bad pointer elsewhere in my code that was trouncing memory.

Now I can finally use a proper algorithm!

6 Likes

Unbelievably great catch, @Stubs!

@DaveVenom, wonderful news. I remember when you put out that bug report and it’s been (heh) bugging me intermittently since then. So nice to have an answer and a resolution!

1 Like

Guess I got lucky that I ran into the usage of the APP->engine->getSampleRate() method first when looking for sample rate handling.

Although the very first sample rate related method I ran into was actually the Module::onSampleRateChange one, which comes with all the information you need :wink:

1 Like

2025-04-24 Update: I installed a bugged version of my plugin and set the VCV sample rate to Auto, and indeed I was finally able to reproduce the bug on my machine! Just as described by @Stubs, rack::settings::sampleRate reported 0 for the sample rate, causing a division by zero error, and of course output failure. I’ve now got a fixed version of Venom in my development branch!

Thanks again!

8 Likes

Perhaps this (informative) post should be re-titled “don’t use xxx improperly”? Surely that API is fine for its intended purpose of driving a UI? Sounds like it’s just not safe to use it in a module?

1 Like

It’s not designed to be used from a module. The value is a float that gets stored as a JSON number for Rack’s settings. The actual sample rate you would want to use in a module is the internal one that Rack’s engine uses, which of course gets updated in real-time.

In other words you want this one:

and not this one:

1 Like

More than just use that method to access sample rate. If you use sample rate for pre-computing information, you must override onSampleRateChange() so that you can update your precomputed data when the sample rate is changed for any reason.

1 Like

Indeed. I was just showing where the two different values come from in the source, which maybe where the original mix-up occurred. The APP macro was introduced in the v1 API.

I use it in Rainbow to update the UI periodically.

void onSampleRateChange() override {
	frameRate = APP->engine->getSampleRate() / 60;
}

Also, in most modules I just use args.sampleRate from the args that is passed to my module’s process method. It is always correct and up-to-date!

[EDIT: I meant to reply to the thread, not @Steve_Russell]

If you’re precomputing lookup tables, that may be something better done from the callback, rather than process. Presumably this callback occurs on the UI thread, because it’s usually in response to user action. Of course, it’s no issue if you use it directly in process computations. Depends on what you’re using the sample rate for.

I always assumed that it comes from the engine thread?

Good point - I haven’t checked (ya got me :-). It might, because it can also come from making changes on your interface. Or, it might come from either depending on the source.