how to generate random noise without making function calls?

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

hi, i've read in the sticky, that you should keep function calls outside of the processReplacing() function, but i don't know how i would do that now.

i just modified the again.dll (my first succesful sound woot(thanks to everyone that helped))

the only things that are different is this function at the top of the again.cpp:

Code: Select all

#include <time.h>

#define RANDoMAX   int(0xFFFFFFFF*0.5f)

float GenerateRandomNumber( void ) 
	{ 
	   /* Change this for different random sequences. */ 
		static unsigned long randSeed = time(NULL); 
	   randSeed = (randSeed * 196314165) + 907633515; 
	   return float(randSeed); 
	} 
and the process and double process functions:

Code: Select all

//-----------------------------------------------------------------------------------------
void AGain::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames)
{
    float* in1  =  inputs[0];
    float* in2  =  inputs[1];
    float* out1 = outputs[0];
    float* out2 = outputs[1];

    while (--sampleFrames >= 0)
    {
		fGain = GenerateRandomNumber()/float(RANDoMAX); 
        fGain -= 1.0f; 
        (*out1++) = (*in1++) * fGain;
        (*out2++) = (*in2++) * fGain;
    }
}

//-----------------------------------------------------------------------------------------
void AGain::processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames)
{
    double* in1  =  inputs[0];
    double* in2  =  inputs[1];
    double* out1 = outputs[0];
    double* out2 = outputs[1];
	double dGain = fGain;

    while (--sampleFrames >= 0)
    {
		fGain = GenerateRandomNumber()/float(RANDoMAX); 
        fGain -= 1.0f; 
        (*out1++) = (*in1++) * dGain;
        (*out2++) = (*in2++) * dGain;
    }
}
so how would i fix that to work without the function call. is that where these "virtual" functions come in??
also. again no longer works as a gain plugin. just outputs white noise.
Last edited by laserbeak on Sat Nov 10, 2007 4:28 pm, edited 1 time in total.

Post

laserbeak wrote: so how would i fix that to work without the function call. is that where these "virtual" functions come in??
Not virtual function (that has to do with overriding in a class hierarchy) but you maybe
an inline function will help you.

Chances are quite good that if you compile with even mild optimization turned on,
functions that can be inlined will be anyway.

Post

cool thanks.

Post

If you're using MSVC, you can use the __forceinline prefix (put __forceinline before the float GenerateRandomNumber( void ) ).

EDIT: To clarify, there's notthing wrong with function calls in processReplacing, however you want to avoid any function calls per sample. I have separate functions (and/or classes) that do various things, and then during processReplacing, I simply call them, giving them the buffer they're supposed to use, as well as how many samples (sampleFrames).
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

When inlining the above function, make sure it's in the header file, not the cpp. Otherwise it won't get inlined.
Sascha Eversmeier [formerly digitalfishphones]
TOURAGE DSP
croquesolid drum processor- mix real drums fast & focused

Post

sascha wrote:When inlining the above function, make sure it's in the header file, not the cpp. Otherwise it won't get inlined.
It will if Whole Program Optimization/Link-time Code generation is enabled (/GL), and it might be even without, depending on circumstances.
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

I profile with VTune occasionally, which made me to switch off /GL in some projects or files. Both my compilers (vcc & icc) work better without at times. But I hand-tune every function anyway, so I got countless of .h files and got used to them.
Sascha Eversmeier [formerly digitalfishphones]
TOURAGE DSP
croquesolid drum processor- mix real drums fast & focused

Post

no function calls per sample? what the...?! That kind of thinking is straight from the nineties and will only hinder good object oriented design.

We have these things called optimising compilers these days.

about inlining,

I found out xcode/gcc won't inline at all unless one does the functions in headers, but with Microsoft VC++ compiler there is no way to reliably control inlining. even force_inlines get treated as suggestions. Rest assured the MS compiler will do a decent job anyway.

Intel compiler on the other hand creates the most optimised DSP binaries whatever the case may be.

Post

whats the diff between a function call in processReplacing and a function call per sample?

and i bet that intel compiler costs some big money! :shock:

Post

laserbeak wrote:whats the diff between a function call in processReplacing and a function call per sample?
A function in processReplacing doesn't necessarily mean it's being process per sample.
The processReplacing function is called once per buffer call from the host (for instance each 512 samples) and performs 'hefty' stuff only in the big while () loop, as with the Steinberg examples. You are free to divide the while () loop into sub chunks, so that a function operates on, say, 32 samples. This has the advantage of conditionals (e.g. if (bFilterActive) doFilter (...);) being called on each chunk, as opposed to every sample. But even if you call a function only every 32 samples or so, it would be bad if it weren't inlined, supposed the code isn't too large in size.

laserbeak wrote: and i bet that intel compiler costs some big money! :shock:
But a VC++ package (pro, at least) does cost, money, anyway. It's a non-issue if your boss pays for those tools, for sure :D
Sascha Eversmeier [formerly digitalfishphones]
TOURAGE DSP
croquesolid drum processor- mix real drums fast & focused

Post

sascha wrote:
laserbeak wrote:whats the diff between a function call in processReplacing and a function call per sample?
A function in processReplacing doesn't necessarily mean it's being process per sample.
The processReplacing function is called once per buffer call from the host (for instance each 512 samples) and performs 'hefty' stuff only in the big while () loop, as with the Steinberg examples. You are free to divide the while () loop into sub chunks, so that a function operates on, say, 32 samples. This has the advantage of conditionals (e.g. if (bFilterActive) doFilter (...);) being called on each chunk, as opposed to every sample. But even if you call a function only every 32 samples or so, it would be bad if it weren't inlined, supposed the code isn't too large in size.
oh i see. there's a lot i haven't discovered then :)(as if there were any doubt)
sascha wrote:
laserbeak wrote: and i bet that intel compiler costs some big money! :shock:
But a VC++ package (pro, at least) does cost, money, anyway. It's a non-issue if your boss pays for those tools, for sure :D
yeah i think i want a boss now :hihi:

Post

Kingston wrote:no function calls per sample? what the...?! That kind of thinking is straight from the nineties and will only hinder good object oriented design.

We have these things called optimising compilers these days.
(1) What I meant was actual function calls, that set up a stack frame, do its thing, then destroys the stack frame, etc. ...
(2) How in the world does block processing hinder object oriented design?
(3) The compiler is smarter than myself in many ways but it won't be smarter than me when it comes to shortcuts and tricks I can take to precalculate things like filter coefficients etc.
(4) What if you have effect slots with arbitrary effects? Which of the two will obviously be faster?

Code: Select all

IEffect* eff = effectSlots[slot];

for(uint i = 0; i < sampleFrames; i++) {
    *buffer = eff->processSample(*buffer);
    buffer++;
}

Code: Select all

IEffect* eff = effectSlots[slot];

eff->processBuffer(buffer, sampleFrames);
It is impossible for the compiler to optimize that, and it will incur a virtual function call per sample - and that hurts.
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

It's important to understand that (to my knowledge) no compiler will be able to 'optimize' accesses to such function arguments as pointer to structure or reference to structure:

Code: Select all

inline void process( CChannel& Data, int l, double* p )
{
    while( l > 0 )
    {
        Data.y += ( *p - Data.y ) * Data.c;
        *p = Data.y;
        p++;
        l--;
    }
}
The problem is, compiler does not know for sure where it should or should not put the intermediate values into the structure.

To get an optimized code you should write this way: (this code can be unrolled by a compiler without a problem)

Code: Select all

inline void process( CChannel& Data, int l, double* p )
{
    const double c = Data.c;
    double y = Data.y;

    while( l > 0 )
    {
        y += ( *p - y ) * c;
        *p = y;
        p++;
        l--;
    }

    Data.y = y;
}
Image

Post

best thread title ever.
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

Aleksey Vaneev wrote:It's important to understand that (to my knowledge) no compiler will be able to 'optimize' accesses to such function arguments as pointer to structure or reference to structure
Really? I didn't expect that. I'll have to investigate the assembly output later ... thanks for the tip!
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post Reply

Return to “DSP and Plugin Development”