COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 07-04-2016, 04:13 AM   #1
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default 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.
SaschArt is offline   Reply With Quote
Old 07-04-2016, 11:20 PM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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.
Tale is offline   Reply With Quote
Old 07-05-2016, 07:08 AM   #3
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

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());
	}
SaschArt is offline   Reply With Quote
Old 07-05-2016, 08:43 AM   #4
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 279
Default

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;
  }
}
stw is offline   Reply With Quote
Old 07-06-2016, 03:57 AM   #5
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Quote:
Originally Posted by stw View Post
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
SaschArt is offline   Reply With Quote
Old 07-06-2016, 04:00 AM   #6
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

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.
SaschArt is offline   Reply With Quote
Old 07-07-2016, 04:45 AM   #7
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

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.
SaschArt is offline   Reply With Quote
Old 07-21-2016, 11:36 AM   #8
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Quote:
Originally Posted by Tale View Post
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.
SaschArt is offline   Reply With Quote
Old 07-21-2016, 12:16 PM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by SaschArt View Post
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 View Post
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 View Post
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).
Tale is offline   Reply With Quote
Old 07-21-2016, 02:03 PM   #10
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

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.
Attached Images
File Type: gif process.gif (33.5 KB, 331 views)
File Type: gif process2.gif (31.3 KB, 359 views)
SaschArt is offline   Reply With Quote
Old 07-21-2016, 02:52 PM   #11
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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.
Tale is offline   Reply With Quote
Old 07-21-2016, 03:09 PM   #12
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

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.
Xenakios is offline   Reply With Quote
Old 07-22-2016, 02:34 AM   #13
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Quote:
Originally Posted by Tale View Post
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.
SaschArt is offline   Reply With Quote
Old 07-22-2016, 03:04 AM   #14
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by SaschArt View Post
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.
Xenakios is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 12:31 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.