title: Unable to record/play AudioQueue and animate simultaneously
body: <p>In my app, I am trying to record on one device, transmit it and play it back on an other device. I want to animate the sound levels on both the recording device and the Playback device.</p>
  
  <p>Most of the code I have used for recording, playing back and animation is from the <a href="http://developer.apple.com/library/ios/#samplecode/SpeakHere/Introduction/Intro.html" rel="nofollow noreferrer">SpeakHere</a> sample App. </p>
  
  <p>I have two differences though:</p>
  
  <ul>
  <li>I have the additional overhead of transmitting over the network.</li>
  <li>I an trying to do the horizontal animation with and image(shown below) instead of the colored bands as in SpeakHere</li>
  </ul>
  
  <p><img src="https://i.stack.imgur.com/lJv8a.png" alt="Animation"></p>
  
  <p>I am recording and transmitting on a separate dispatch queue(GCD) and the same for receiving and playing back.</p>
  
  <ul>
  <li>My first problem is: when I introduce the animation, the receiving and playback becomes very slow and the AudioQueue goes silent.</li>
  <li>My next problem is with setting a clear background to the LevelMeter view. If I do that then the animation is garbled. Not sure how the animation is connected to the background color.</li>
  </ul>
  
  <p>Below is my version of (not so elegantly modified) drawRect from the SpeakHere example. 
  Please advice on any mistakes I may have made.</p>
  
  <p>My understanding is that I cannot use another thread here for the animation because of UIKit. If not, please correct me.</p>
  
  <pre><code>- (void)drawRect:(CGRect)rect
  {
          //();
      CGContextRef cxt = NULL;
      cxt = UIGraphicsGetCurrentContext();
  
      CGColorSpaceRef cs = NULL;
      cs = CGColorSpaceCreateDeviceRGB();
  
      CGRect bds;
  
  
      if (_vertical)
      {
          CGContextTranslateCTM(cxt, 0., [self bounds].size.height);
          CGContextScaleCTM(cxt, 1., -1.);
          bds = [self bounds];
      } else {
          CGContextTranslateCTM(cxt, 0., [self bounds].size.height);
          CGContextRotateCTM(cxt, -M_PI_2);
          bds = CGRectMake(0., 0., [self bounds].size.height, [self bounds].size.width);
      }
  
      CGContextSetFillColorSpace(cxt, cs);
      CGContextSetStrokeColorSpace(cxt, cs);
  
      if (_numLights == 0)
      {
          int i;
          CGFloat currentTop = 0.;
  
          if (_bgColor)
          {
              [_bgColor set];
              CGContextFillRect(cxt, bds);
          }
  
          for (i=0; i&lt;_numColorThresholds; i++)
          {
              LevelMeterColorThreshold thisThresh = _colorThresholds[i];
              CGFloat val = MIN(thisThresh.maxValue, _level);
  
              CGRect rect = CGRectMake(
                                       0, 
                                       (bds.size.height) * currentTop, 
                                       bds.size.width, 
                                       (bds.size.height) * (val - currentTop)
                                       );
  
              [thisThresh.color set];
              CGContextFillRect(cxt, rect);
  
              if (_level &lt; thisThresh.maxValue) break;
  
              currentTop = val;
          }
  
          if (_borderColor)
          {
              [_borderColor set];
              CGContextStrokeRect(cxt, CGRectInset(bds, .5, .5));
          }
  
      } 
      else 
      {
          int light_i;
          CGFloat lightMinVal = 0.;
          CGFloat insetAmount, lightVSpace;
          lightVSpace = bds.size.height / (CGFloat)_numLights;
          if (lightVSpace &lt; 4.) insetAmount = 0.;
          else if (lightVSpace &lt; 8.) insetAmount = 0.5;
          else insetAmount = 1.;
  
          int peakLight = -1;
          if (_peakLevel &gt; 0.)
          {
              peakLight = _peakLevel * _numLights;
              if (peakLight &gt;= _numLights) peakLight = _numLights - 1;
          }
  
          for (light_i=0; light_i&lt;_numLights; light_i++)
              {
                  CGFloat lightMaxVal = (CGFloat)(light_i + 1) / (CGFloat)_numLights;
                  CGFloat lightIntensity;
                  CGRect lightRect;
                  UIColor *lightColor;
  
                  if (light_i == peakLight)
                  {
                      lightIntensity = 1.;
                  } 
                  else 
                  {
                      lightIntensity = (_level - lightMinVal) / (lightMaxVal - lightMinVal);
                      lightIntensity = LEVELMETER_CLAMP(0., lightIntensity, 1.);
                      if ((!_variableLightIntensity) &amp;&amp; (lightIntensity &gt; 0.)) lightIntensity = 1.;
                  }
  
                  lightColor = _colorThresholds[0].color;
                  int color_i;
                  for (color_i=0; color_i&lt;(_numColorThresholds-1); color_i++)
                  {
                      LevelMeterColorThreshold thisThresh = _colorThresholds[color_i];
                      LevelMeterColorThreshold nextThresh = _colorThresholds[color_i + 1];
                      if (thisThresh.maxValue &lt;= lightMaxVal) lightColor = nextThresh.color;
                  }
  
                  lightRect = CGRectMake(
                                         0., 
                                         bds.size.height * ((CGFloat)(light_i) / (CGFloat)_numLights), 
                                         bds.size.width,
                                         bds.size.height * (1. / (CGFloat)_numLights)
                                         );
                  lightRect = CGRectInset(lightRect, insetAmount, insetAmount);
  
                  if (_bgColor)
                  {
                      [_bgColor set];
                      CGContextFillRect(cxt, lightRect);
                  }
  
                  UIImage* image = [UIImage imageNamed:@"Pearl.png"];
                  CGImageRef imageRef = image.CGImage;
  
  
                  if (lightIntensity == 1.)
                  {
                      CGContextDrawImage(cxt, lightRect, imageRef);
  
                      [lightColor set];
                      //CGContextFillRect(cxt, lightRect);
                  } else if (lightIntensity &gt; 0.) {
                      CGColorRef clr = CGColorCreateCopyWithAlpha([lightColor CGColor], lightIntensity);
                      CGContextSetFillColorWithColor(cxt, clr);
                      //CGContextFillRect(cxt, lightRect);
                      CGContextDrawImage(cxt, lightRect, imageRef);
  
                      CGColorRelease(clr);
                  }
  
                  if (_borderColor)
                  {
                      [_borderColor set];
                      CGContextStrokeRect(cxt, CGRectInset(lightRect, 0.5, 0.5));
                  }
  
                  lightMinVal = lightMaxVal;
              }       
      }
  
      CGColorSpaceRelease(cs);
  }
  </code></pre>