PDA

View Full Version : Good architecture/design needed for "sample pipeline"


johnman
10th October 2005, 00:05
Im rewriting my program so it can dynamically create a sample processing pipeline . What i mean by this is that im trying to create a virtual sample pipeline, with one input, and one output. In this pipeline i can add dithering, vst's or resampling or whatever, and i can add them in any order possible, or even multiple times (ass long as subsequent input/ouput are compatible).

Currently this pipeline was pretty much static, so i want to make it more dynamic.To explain this a little here is some code of the most important function : SmplProcAddSmpls. This function is called whenever there are some samples which have to be inserted into the "pipeline":

usage of SmplProcAddSmpls:

ConvertWaveFile()
{
...
for(i=0;i<itCnt && !stopConversion;i++)
{
fread(buf1,bps,nChannels*MAXSMPLSPERITERATION,inFile);
SmplProcAddSmpls(fileProperties, buf1, MAXSMPLSPERITERATION);
}
...
}





This is how it was (a little simplified ofcourse):



SmplProcAddSmpls()
{
if(toFloatingPoint)
{
ConvertRawSmplsToFloats();
}

if(addDithering)
{
DoDither();
}
if(someVstsEnabled)
{
DoVstEffects();
}

if(findPeak)
{
FindPeakOfSmpls();
}


if(SaveSamples())
{
StoreSamplesToDisk();
}


}



The problem with this is that it is static. If i wanted to i.e. reverse the order of "DoDither" and "FindPeakOfSmpls", this is impossible. So i have rewritten it like this:


SmplProcAddSmpls2()
{
for(i=0; i<effectCnt; i++)
{
DoEffect[i]((struct parameters*) p);
}
}


DoEffect[0] can be for example the function ConvertRawSmplsToFloats and DoEffect[1] DoDither etc.
So i created a array of functions, and whenever i want to insert some samples these will go through the functions DoEffect[0] -> DoEffect[effectCnt].
I will change this to recursive functions so that DoEffect[0] will call DoEffect[1], DoEffect[1] will call DoEffect[2] etc etc. But i was thinking about a more elegant way to create a "dynamic sample pipeline". Although i know the syntax of c++, i havent used it very much, and i was thinking there might be a elegeant way to solve this problem in c++ using OO stuff. So my question is: How can i create a dynamic sample pipeline in an elegant way? Or are pointers to functions "the way to go"?

int 21h
10th October 2005, 06:09
Some sort of class factory would be the way to go I'd think. Each filter would be of some generic filter prototype and each child of this generic prototype would register itself with the factory at runtime. Then the factory would be responsible for giving out instances of these filters on demand.

Sort of like a plugin type interface. The function pointers way is the old non-oO way of doing this same thing. I can't really provide any decent examples in C++, but I've done this a few times in C# and Java for things like database abstraction layers and the like. If you google for 'class factory C++ plugin system' you will probably find what you're looking for. (like this: http://www.lunaticsystems.com/index.php?module=articles&func=display&aid=2&ptid=2)

johnman
10th October 2005, 18:44
Thanks for your suggestion :), ill try to get it to work in c++

johnman
19th October 2005, 21:53
I've played a little with c++, but i found out i like c better. Its probabely me, but i think c is more intuitive. So i guess im not to much of a OO kind of guy.

Anyway, i made the sample pipeline in c in a recursive kind of way, and i was wondering how deep the recursion can go. I think this totaly dependend on the code, but i would like to see a rough estimation. Is it in the order of 100's, or maybe 1000's? I think it somehow depends on the stack, but can someone give some more detailes on this?

int 21h
20th October 2005, 06:29
By default, most of the programs for Windows I've seen are compiled with a stack size of 1mb. So a generous estimate is probably in the order of 1000's, but I am willing to bet its more on an order of 100's after other stack usage is taken into account.

johnman
20th October 2005, 12:18
I've have created an endless recursion an im getting 26220 levels deep. When i allocate 10k bytes from the stack at every level, i only get 205 lvls deep. So i guess i should not allocate to much from the stack. So now my questions are:

- how do i enlarge the stacksize? (a quick search didnt bring me the answer)
- is it possible to somehow test if there is any room left in the stack?

EDIT
I looked at the commandline options of mingw, but this didint really help.

int 21h
21st October 2005, 01:10
ld takes stacksize arguments...I've heard by default mingw allocates 32mb to stack. If this is indeed the case, then that would match my initial estimates (if you do the multiplication anyways). If you don't have Visual Studio, you can get the utilty PEDump.exe (http://www.woodmann.com/fravia/exe/PEDUMP.EXE) to tell you. Simply run the command `PEDump path.to/my.exe > dump.txt`. Then look through dump.txt for the line: "stack reserve size 100000".

In Linux, stacksize isn't stored in the binaries so it isn't usually an issue until you get really, really high.