Thread: Good architecture/design needed for "sample pipeline"

  1. #1
    Registered User
    Join Date
    Mar 2005
    Posts
    76

    Good architecture/design needed for "sample pipeline"

    Im rewriting my audio 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:
    Code:
    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):

    Code:
    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:

    Code:
    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"?

  2. #2
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    you could try something with a an abstract Effect class?

    say you have a Sample class that you want to transform

    Code:
    // shown inline for clarity
    class Effect
    {
    protected:
        Effect(Sample& sample)
        : m_sample(sample)
        { }
    
        virtual void DoEffect(void) = 0;
    
        Sample& m_sample;
    };
    
    class DitherEffect : public Effect
    {
    public:
        DitherEffect(Sample& sample)
        : Effect(sample)
        { }
    
        void SetDitherParam(int d)
        {
             // set some params
        }
    
        virtual void DoEffect(void)
        {
             // do some sample dithering here
        }
    
    private:
        // dither params
    };
    then put the effect objects in a heterogenous list like this

    Code:
    std::list<boost::shared_ptr<Effect> > effectList;
    
    //create new dither
    DitherEffect* pDither = new DitherEffect();
    pDither->SetDitherParam(666);
    // put on list
    effectList.push_back(pDither);
    
    VstEffect* pVst = new VstEffect();
    pVst->SetVstParam(666);
    effectList.push_back(pVst);
    
    // go through list and apply each effect
    std::for_each(effectList.begin(), effectList.end(),
                          mem_fun(Effect::DoEffect());
    you could then read in some sort of script with each effect and params and create the correct effect class for each. Hope that helps

    note: that code is off the top of my head, so probably has a few syntax errors!
    Last edited by ChaosEngine; 10-09-2005 at 07:18 PM.

  3. #3
    Registered User
    Join Date
    Mar 2005
    Posts
    76
    Thanx , that was just the thing i was looking for. Ill play a little with c++ to see if i can get it to work.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 51
    Last Post: 02-09-2009, 05:35 PM
  2. Good principles needed.
    By elninio in forum C++ Programming
    Replies: 15
    Last Post: 07-20-2008, 10:33 PM
  3. In a game Engine...
    By Shamino in forum Game Programming
    Replies: 28
    Last Post: 02-19-2006, 11:30 AM
  4. linked list recursive function spaghetti
    By ... in forum C++ Programming
    Replies: 4
    Last Post: 09-02-2003, 02:53 PM