0

在我的应用程序中,我试图在一台设备上录制、传输并在另一台设备上播放。我想为录音设备和播放设备上的声级设置动画。

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

我有两个不同之处:

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

动画片

我在一个单独的调度队列(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);
}
4

1 回答 1

1

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

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

于 2012-07-11T20:06:38.733 回答