无法同时录制/播放AudioQueue和动画

时间:2012-07-11 19:50:15

标签: ios core-graphics core-audio audio-streaming grand-central-dispatch

在我的应用中,我正在尝试在一台设备上录制,传输并在其他设备上播放。我想在录音设备和播放设备上设置声音级别的动画。

我用于录制,播放和动画的大部分代码来自SpeakHere示例应用。

我有两个不同之处:

  • 我有通过网络传输的额外开销。
  • 我试图用和图像(如下所示)进行水平动画,而不是像SpeakHere那样用彩色条带

Animation

我正在单独的调度队列(GCD)上录制和传输,并且用于接收和播放。

  • 我的第一个问题是:当我介绍动画时,接收和播放变得非常慢,而且AudioQueue会静音。
  • 我的下一个问题是为LevelMeter视图设置了清晰的背景。如果我这样做,那么动画就会出现乱码。不确定动画如何连接到背景颜色。

以下是我在SpeakHere示例中的(不那么优雅修改)drawRect的版本。 如果我可能犯过任何错误,请提供建议。

我的理解是,由于UIKit,我不能在这里使用另一个线程来制作动画。如果没有,请纠正我。

- (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<_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 < 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 < 4.) insetAmount = 0.;
        else if (lightVSpace < 8.) insetAmount = 0.5;
        else insetAmount = 1.;

        int peakLight = -1;
        if (_peakLevel > 0.)
        {
            peakLight = _peakLevel * _numLights;
            if (peakLight >= _numLights) peakLight = _numLights - 1;
        }

        for (light_i=0; light_i<_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) && (lightIntensity > 0.)) lightIntensity = 1.;
                }

                lightColor = _colorThresholds[0].color;
                int color_i;
                for (color_i=0; color_i<(_numColorThresholds-1); color_i++)
                {
                    LevelMeterColorThreshold thisThresh = _colorThresholds[color_i];
                    LevelMeterColorThreshold nextThresh = _colorThresholds[color_i + 1];
                    if (thisThresh.maxValue <= 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 > 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);
}

1 个答案:

答案 0 :(得分:1)

您的绘图可能太慢,这可能会影响对音频队列回调的实时响应要求。

但是,由于您主要绘制一堆静态图像,因此您可能需要考虑将每个点放在各自的图像视图中。您可以通过隐藏和取消隐藏子视图来控制显示的点数,而不需要任何drawRect代码。