title: Realtime audio application, improving performance
body: <p>I am currently writing a C++ real time audio application which roughly contains:</p>
  
  <ul>
  <li>reading frames from a buffer</li>
  <li>interpolating frames with the hermit interpolation <a href="https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da">here</a></li>
  <li>filtering ever frame with two biquad filters (and updating their coefficients every frame)</li>
  <li>a 3 band crossover containing 18 biquad calculations </li>
  <li>a FreeVerb algorithm from the STK libary <a href="https://ccrma.stanford.edu/software/stk/classstk_1_1FreeVerb.html" rel="nofollow noreferrer">here</a></li>
  </ul>
  
  <p>I think this should be handable for my PC but I get some buffer underflows every so often so I would like to improve the performance of my application. I have a bunch of question I hope you can answer me. :)</p>
  
  <p><strong>1) Operator Overloading</strong></p>
  
  <p>Instead of working directly with my flaot samples and doing calculations for every sample, 
  I pack my floats in a <code>Frame</code> class which contains the left and the right Sample. The class overloads some operators for addition, subtraction and multiplication with <code>float</code>.</p>
  
  <p>The filters (biquad mostly) and the reverb works with floats and doesn't use this class but the hermite interpolator and every multiplication and addition for volume controll and mixing uses the class. </p>
  
  <p>Does this has an impact on the performance and would it be better to work with left and right sample directly? </p>
  
  <p><strong>2) std::function</strong></p>
  
  <p>The callback function from the audio IO libary PortAudio calls a std::function. I use this to encapsulation everything related to PortAudio. So the "user" sets his own callback function with std::bind</p>
  
  <pre><code>std::bind(  &amp;AudioController::processAudio, 
              &amp;(*this), 
              std::placeholders::_1, 
              std::placeholders::_2));
  </code></pre>
  
  <p>Since for every callback, the right function has to be found from the CPU (however this works...), does this have an impact and would it be better to define a class the user has to inherit from?</p>
  
  <p><strong>3) virtual functions</strong></p>
  
  <p>I use a class called <code>AudioProcessor</code> which declares a virtual function:</p>
  
  <pre><code>virtual void tick(Frame *buffer, int frameCout) = 0;
  </code></pre>
  
  <p>This function always processes a number of frames at once. Depending on the drive, 200 frames up to  1000 frames per call.
  Within the signal processing path, I call this function 6 time from multiple derivated classes. I remember that this is done with lookup tables so the CPU knows exactly which function it has to call. So does the process of calling a "virtual" (derivated) function  has an impact on the performance?</p>
  
  <p>The nice thing about this is the structure in the source code but only using inlines maybe would have an performance improvement.</p>
  
  <p>These are all questions for now. I have some more about Qt's event loop because I think that my GUI uses quite a bit of CPU time as well. But this is another topic I guess. :)</p>
  
  <p>Thanks in advance!</p>
  
  <hr>
  
  <p>These are all relevant function calls within the signal processing. Some of them are from the STK libary.
  The biquad functions are from STK and should perform fine. This goes for the freeverb algorithm as well.</p>
  
  <pre class="lang-cpp prettyprint-override"><code>// ################################ AudioController Function ############################
  void AudioController::processAudio(int frameCount, float *output) {
      // CALCULATE LEFT TRACK
  
      Frame * leftFrameBuffer = (Frame*) output;
  
      if(leftLoaded) { // the left processor is loaded
          leftProcessor-&gt;tick(leftFrameBuffer, frameCount);   //(TrackProcessor::tick()
      } else {
          for(int i = 0; i &lt; frameCount; i++) {
              leftFrameBuffer[i].leftSample  = 0.0f;
              leftFrameBuffer[i].rightSample = 0.0f;
          }
      }
  
      // CALCULATE RIGHT TRACk
  
      if(rightLoaded) { // the right processor is loaded
          // the rightFrameBuffer is allocated once and ensured to have enough space for frameCount Frames
          rightProcessor-&gt;tick(rightFrameBuffer, frameCount); //(TrackProcessor::tick()
      } else {
          for(int i = 0; i &lt; frameCount; i++) {
              rightFrameBuffer[i].leftSample  = 0.0f;
              rightFrameBuffer[i].rightSample = 0.0f;
          }
      }
  
      // MIX
      for(int i = 0; i &lt; frameCount; i++ ) {
          leftFrameBuffer[i] = volume * (leftRightMix * leftFrameBuffer[i] + (1.0 - leftRightMix) * rightFrameBuffer[i]);
      }
  }
  
  // ################################ AudioController Function ############################
  
  void TrackProcessor::tick(Frame *frames, int frameNum) {
      if(bufferLoaded &amp;&amp; playback) {
          for(int i = 0; i &lt; frameNum; i++) {
              // read from buffer
              frames[i] =  bufferPlayer-&gt;tick();
  
              // filter coeffs
              caltulateFilterCoeffs(lowCutoffFilter-&gt;tick(), highCutoffFilter-&gt;tick());
  
              // filter
              frames[i].leftSample = lpFilterL-&gt;tick(hpFilterL-&gt;tick(frames[i].leftSample));
              frames[i].rightSample = lpFilterR-&gt;tick(hpFilterR-&gt;tick(frames[i].rightSample));
          }
      } else {
          for(int i = 0; i &lt; frameNum; i++) {         
              frames[i] = Frame(0,0);
          }
      }
  
      // Effect 1, Equalizer
      if(effsActive[0]) {
          insEffProcessors[0]-&gt;tick(frames, frameNum);
      }
      // Effect 2, Reverb
      if(effsActive[1]) {
          insEffProcessors[1]-&gt;tick(frames, frameNum);
      }
  
      // Volume
      for(int i = 0; i &lt; frameNum; i++) {
          frames[i].leftSample  *= volume;
          frames[i].rightSample *= volume;
      }
  }
  
  // ################################ Equalizer ############################
  
  void EqualizerProcessor::tick(Frame *frames, int frameNum) {
      if(active) {
          Frame lowCross;
          Frame highCross;
  
          for(int f = 0; f &lt; frameNum; f++) {
  
              lowAmp = lowAmpFilter-&gt;tick();
              midAmp = midAmpFilter-&gt;tick();
              highAmp = highAmpFilter-&gt;tick();
  
              lowCross =  highLPF-&gt;tick(frames[f]);
              highCross = highHPF-&gt;tick(frames[f]);
  
              frames[f] = lowAmp * lowLPF-&gt;tick(lowCross) 
                        + midAmp * lowHPF-&gt;tick(lowCross) 
                        + highAmp * lowAPF-&gt;tick(highCross);
          }
      }
  }
  
  // ################################ Reverb ############################
  // This function just calls the stk::FreeVerb tick function for every frame
  // The FreeVerb implementation can't realy be optimised so I will take it as it is.
  
  void ReverbProcessor::tick(Frame *frames, int frameNum) {
      if(active) {
          for(int i = 0; i &lt; frameNum; i++) {
              frames[i].leftSample = reverb-&gt;tick(frames[i].leftSample, frames[i].rightSample);
              frames[i].rightSample = reverb-&gt;lastOut(1);
          }
      }
  }
  
  // ################################ Buffer Playback (BufferPlayer) ############################
  
  Frame BufferPlayer::tick() {
      // adjust read position based on loop status
      if(inLoop) {
          while(readPos &gt; loopEndPos) {
              readPos = loopStartPos + (readPos - loopEndPos); 
          }
      }
  
      int x1  = readPos;
      float t = readPos - x1;
  
      Frame f = interpolate(buffer-&gt;frameAt(x1-1), 
                            buffer-&gt;frameAt(x1),
                            buffer-&gt;frameAt(x1+1),
                            buffer-&gt;frameAt(x1+2),
                            t);
  
      readPos += stepSize;;
      return f;
  }
  
  // interpolation:
  Frame BufferPlayer::interpolate(Frame x0, Frame x1, Frame x2, Frame x3, float t) {
      Frame c0 = x1;
      Frame c1 = 0.5f * (x2 - x0);
      Frame c2 = x0 - (2.5f * x1) + (2.0f * x2) - (0.5f * x3);
      Frame c3 = (0.5f * (x3 - x0)) + (1.5f * (x1 - x2));
      return (((((c3 * t) + c2) * t) + c1) * t) + c0;
  }
  
  
  inline Frame BufferPlayer::frameAt(int pos) {
      if(pos &lt; 0) {
          pos = 0;
      } else if (pos &gt;= frames) {
          pos = frames -1;
      }
  
      // get chunk and relative Sample
      int chunk = pos/ChunkSize;
      int chunkSample = pos%ChunkSize;
  
      return Frame(leftChunks[chunk][chunkSample], rightChunks[chunk][chunkSample]); 
  }
  </code></pre>