|
07-04-2016, 04:13 AM
|
#1
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Slow refreshing timer to process
Have a way to define an additional timer with 30-40 refresh per seconds to save resources for processing no audio data like midi, lfo, env etc. Something like @block section in EEL with samplesblock of samples per refresh.
I know can be used ProcessDoubleReplacing with timer inside
Code:
ProcessDoubleReplacing(double** inputs, double** outputs, int samples) {
// Mutex is already locked for us.
for (int s = 0; s < samples; ++s) {
if (crtsample>samplesblock) {
///////////////// process ==>> @block
crtsample=0;
}
crtsample++;
}
}
But to use this timer inside a process with 44100 cycles per seconds take a lot of resources with no reason.
|
|
|
07-04-2016, 11:20 PM
|
#2
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
If you want to mimic JSFX behaviour, then I believe this is how it more or less works:
Code:
void ProcessDoubleReplacing(double** inputs, double** outputs, int samplesblock)
{
const double srate = GetSampleRate();
// @block
// Insert @block code here.
for (int i = 0; i < samples; ++i)
{
double spl0 = inputs[0][i], spl1 = inputs[1][i];
// @sample
// Insert @sample code here.
outputs[0][i] = spl0;
outputs[1][i] = spl1;
}
}
However, how many times @block is called depends on sample rate and samplesblock (just like in JSFX), so it doesn't necessarily have a 30..40 Hz refresh rate.
|
|
|
07-05-2016, 07:08 AM
|
#3
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Thanks, this is great
One more question I see you get srate value in ProcessDoubleReplacing, I suppose is constant and do not change after plugin loading, so can get this outside from ProcessDoubleReplacing. I test on the constructor to call GetSampleRate() and get an error. In this way is safe ?
Code:
VSTCLASS::VSTCLASS(IPlugInstanceInfo instanceInfo): IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo) {
TRACE;
srate=0;
void VSTCLASS::OnParamChange(int id) { //// this maybe called before Reset()
IMutexLock lock(this);
if (srate<1) {
srate = int(GetSampleRate());
}
|
|
|
07-05-2016, 08:43 AM
|
#4
|
Human being with feelings
Join Date: Apr 2012
Posts: 279
|
Set your samplerate var in the Reset() function.
Reset() is called if the sample rate is changed by the host.
Since Reset() is also called on other occasions it would be useful to check if samplerate changed before e.g. doing lots of calculations all the time.
You could do it like this:
Code:
double SAMPLERATE = 44100;
void MYPLUG::Reset(){
if (mOldSR != mSampleRate) {
SAMPLERATE = mSampleRate; // mSampleRate is a protected IPlugBase member and contains the actual sample rate
//
// do some other sr related stuff here
//
mOldSR = mSampleRate;
}
}
|
|
|
07-06-2016, 03:57 AM
|
#5
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Quote:
Originally Posted by stw
Set your samplerate var in the Reset() function.
Reset() is called if the sample rate is changed by the host.
Since Reset() is also called on other occasions it would be useful to check if samplerate changed before e.g. doing lots of calculations all the time.
|
Good to know
|
|
|
07-06-2016, 04:00 AM
|
#6
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Tale I use your WDL version. I see GetTime() is not available in your version and cannot see how to take playing state, like playing /recording.
Please give me a solution to take this info.
|
|
|
07-07-2016, 04:45 AM
|
#7
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Solved get playing /recording problem in Tale version with:
Code:
/////// h file
int GetPlaying();
/////// cpp file
int IPlugVST::GetPlaying()
{
int res=0;
VstTimeInfo* pTI = GetTimeInfo(mHostCallback, &mAEffect);
if (pTI) {
if (pTI->flags & kVstTransportPlaying) res = 1;
if (pTI->flags & kVstTransportCycleActive) res = 2;
if (pTI->flags & kVstTransportRecording) res = 3;
}
return res;
}
In IPlugVST.h and IPlugVST.cpp Hope noting forgot kVstTransportChanged flag It seems to be useless.
|
|
|
07-21-2016, 11:36 AM
|
#8
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Quote:
Originally Posted by Tale
If you want to mimic JSFX behaviour, then I believe this is how it more or less works:
Code:
void ProcessDoubleReplacing(double** inputs, double** outputs, int samplesblock)
{
const double srate = GetSampleRate();
// @block
// Insert @block code here.
for (int i = 0; i < samples; ++i)
{
double spl0 = inputs[0][i], spl1 = inputs[1][i];
// @sample
// Insert @sample code here.
outputs[0][i] = spl0;
outputs[1][i] = spl1;
}
}
However, how many times @block is called depends on sample rate and samplesblock (just like in JSFX), so it doesn't necessarily have a 30..40 Hz refresh rate.
|
Unfortunately I test this side:
Code:
// @sample
// Insert @sample code here.
not called by 44100 (GetSampleRate()) per seconds. It is called unpredictable, much faster, depend by how fast processor goes through for (int i = 0; i < samples; ++i) loop, in blocks by samplesblock.
That can be safe calculated only refresh of ProcessDoubleReplacing function by GetSampleRate()/samplesblock per sec.
Testing this code, process ==>> @rate is not called by 50ms
Code:
/// in constructor
int milsec=50;
rate=int(0.5+srate*milsec/1000);
/// in ProcessDoubleReplacing function
if (crtsample>rate) {
///////////////// process ==>> @rate
timerStop();
debugPrint(3, timerElapse(), GetSampleRate()/samplesblock, GetSampleRate());
timerStart();
crtsample=0;
}
crtsample++;
I cannot see how to make faster lfo.
|
|
|
07-21-2016, 12:16 PM
|
#9
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by SaschArt
Unfortunately I test this side:
Code:
// @sample
// Insert @sample code here.
not called by 44100 (GetSampleRate()) per seconds. It is called unpredictable, much faster, depend by how fast processor goes through for (int i = 0; i < samples; ++i) loop, in blocks by samplesblock.
|
Quoting/repeating myself:
Quote:
Originally Posted by Tale
However, how many times @block is called depends on sample rate and samplesblock (just like in JSFX), so it doesn't necessarily have a 30..40 Hz refresh rate.
|
There are many reasons why this works this way: The CPU always executes everything as fast as possible, the host probably has many more plug-ins it needs to run within the current audio block, etc.
Quote:
Originally Posted by SaschArt
I cannot see how to make faster lfo.
|
Well, it shouldn't be too hard to code an LFO (or audio oscillator) that can basically run at any rate. This is is what I usually do:
Code:
// In your header:
double mPhase, mPeriod;
// In your constructor:
mPhase = 0.0;
// In Reset():
const double lfoRate = 5.0; // Hz
mPeriod = lfoRate / GetSampleRate();
// In the sample loop in ProcessDoubleReplacing():
double lfoOutput = sin(2*M_PI * mPhase);
mPhase += mPeriod;
mPhase -= (int)mPhase;
This should work for 0.1 Hz, for 100 Hz, and even for 1000000 Hz (aliasing aside).
|
|
|
07-21-2016, 02:03 PM
|
#10
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
I hope will explain clearly
The problem is internal loop refresh which is not 44100 (I mean GetSampleRate()), next loop content is called much faster because the loop have no sleep, so depend only by CPU, not by communication plugin-host. See the logs from DebugView:
VSTHost test:
Reaper test:
From this testing it appears there it's a large pause between finishing process loop and the next call of ProcessDoubleReplacing() so is discontinuous, cannot make continuous lfo based on discontinuous process.
Tested with internal plugin timer too with same results, so problem is not communication from plugin to DebugView.
I will test your lfo code graphically, thanks.
|
|
|
07-21-2016, 02:52 PM
|
#11
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
You seem to think that realtime audio is actually generated in realtime, but it really is not. In fact, both the host and your plug-in are always rendering offline at high speed. The host buffers the output from your plug-in, and sends it to the audio driver, which will play the audio in realtime.
It may seem that this makes things "discontinuous", but it really does not. Your plug-in will generate e.g. 1024 samples, then it will do nothing for a (very!) short time, and then it will generate the next 1024 samples. The result will be a continuous block of 1024 + 1024 = 2048 samples, no gaps or anything.
This does mean that if you want to time anything, you should count samples in ProcessDoubleReplacing() rather than to try to actually time anything using the OS clock or whatever other realtime method.
|
|
|
07-21-2016, 03:09 PM
|
#12
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
The original poster should probably explain exactly in detail what he is trying to do in the plugin...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
07-22-2016, 02:34 AM
|
#13
|
Human being with feelings
Join Date: Aug 2013
Posts: 236
|
Quote:
Originally Posted by Tale
You seem to think that realtime audio is actually generated in realtime, but it really is not. In fact, both the host and your plug-in are always rendering offline at high speed. The host buffers the output from your plug-in, and sends it to the audio driver, which will play the audio in realtime.
It may seem that this makes things "discontinuous", but it really does not. Your plug-in will generate e.g. 1024 samples, then it will do nothing for a (very!) short time, and then it will generate the next 1024 samples. The result will be a continuous block of 1024 + 1024 = 2048 samples, no gaps or anything.
This does mean that if you want to time anything, you should count samples in ProcessDoubleReplacing() rather than to try to actually time anything using the OS clock or whatever other realtime method.
|
Thanks a lot Tale for your time and explanation, that is. In my mind was that the LFO necessarily have to be in realtime. So lfoOutput from your code can be used into the loop, as VST virtual time, and is not available in controls graphic with real time refresh of 24 fps.
Xenakios need to make LFO for plugin parameters, must understand well before make it.
|
|
|
07-22-2016, 03:04 AM
|
#14
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by SaschArt
need to make LFO for plugin parameters, must understand well before make it.
|
For your own plugin? That will be possible in the ways Tale explained it, you will just have to arrange things so that updating the GUI fully in sync isn't a critical thing to have. (Since you can't really force GUI updates from the audio thread to happen at exact times.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 12:31 PM.
|