在我的应用程序中,我试图在一台设备上录制、传输并在另一台设备上播放。我想为录音设备和播放设备上的声级设置动画。
我用于录制、播放和动画的大部分代码都来自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);
}