我正在使用以下核心图形代码在我录制时绘制音频数据的波形。我为大量代码道歉,但在这里(我发现它here):
//
// WaveformView.m
//
// Created by Edward Majcher on 7/17/14.
//
#import "WaveformView.h"
//Gain applied to incoming samples
static CGFloat kGain = 10.;
//Number of samples displayed
static int kMaxWaveforms = 80.;
@interface WaveformView ()
@property (nonatomic) BOOL addToBuffer;
//Holds kMaxWaveforms number of incoming samples,
//80 is based on half the width of iPhone, adding a 1 pixel line between samples
@property (strong, nonatomic) NSMutableArray* bufferArray;
+ (float)RMS:(float *)buffer length:(int)bufferSize;
@end
@implementation WaveformView
- (void)awakeFromNib
{
[super awakeFromNib];
self.bufferArray = [NSMutableArray array];
}
-(void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize
{
if (!self.addToBuffer) {
self.addToBuffer = YES;
return;
} else {
self.addToBuffer = NO;
}
float rms = [WaveformView RMS:buffer length:bufferSize];
if ([self.bufferArray count] == kMaxWaveforms) {
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// [self.bufferArray removeObjectAtIndex:0];
}
[self.bufferArray addObject:@(rms * kGain)];
[self setNeedsDisplay];
}
+ (float)RMS:(float *)buffer length:(int)bufferSize {
float sum = 0.0;
for(int i = 0; i < bufferSize; i++) {
sum += buffer[i] * buffer[i];
}
return sqrtf( sum / bufferSize );
}
// *****************************************************
- (void)drawRect:(CGRect)rect
{
CGFloat midX = CGRectGetMidX(rect);
CGFloat maxX = CGRectGetMaxX(rect);
CGFloat midY = CGRectGetMidY(rect);
CGContextRef context = UIGraphicsGetCurrentContext();
// Draw out center line
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 1.);
CGContextMoveToPoint(context, 0., midY);
CGContextAddLineToPoint(context, maxX, midY);
CGContextStrokePath(context);
CGFloat x = 0.;
for (NSNumber* n in self.bufferArray) {
CGFloat height = 20 * [n floatValue];
CGContextMoveToPoint(context, x, midY - height);
CGContextAddLineToPoint(context, x, midY + height);
CGContextStrokePath(context);
x += 2;
}
if ([self.bufferArray count] >= kMaxWaveforms) {
[self addMarkerInContext:context forX:midX forRect:rect];
} else {
[self addMarkerInContext:context forX:x forRect:rect];
}
}
- (void)addMarkerInContext:(CGContextRef)context forX:(CGFloat)x forRect:(CGRect)rect
{
CGFloat maxY = CGRectGetMaxY(rect);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
CGContextFillEllipseInRect(context, CGRectMake(x - 1.5, 0, 3, 3));
CGContextMoveToPoint(context, x, 0 + 3);
CGContextAddLineToPoint(context, x, maxY - 3);
CGContextStrokePath(context);
CGContextFillEllipseInRect(context, CGRectMake(x - 1.5, maxY - 3, 3, 3));
}
@end
因此,当我录制音频时,波形绘制变得越来越紧张,有点像具有糟糕帧速率的游戏。我试过联系这段代码的所有者,但没有运气。我从来没有使用核心图形,所以我试图找出性能如此糟糕的原因。性能开始下降大约2-3秒的音频(波形甚至不会填满屏幕)。
我的第一个问题是,每次调用drawRect时,是否会重绘整个音频历史记录?如果你查看drawRect函数(用星号标记),就会有一个名为CGRect x的变量。这似乎会影响绘制波形的位置(如果将其设置为60而不是0,则从x = 60像素而不是x = 0像素开始)。
从我的viewController中,我传入了存储在self.bufferArray属性中的audioData。因此,当循环遍历绘制数据时,似乎它从0开始并且每次调用drawRect时都会向上运行,这意味着对于添加的每个新音频数据,drawRect都会被调用,它重绘整个波形加上新的音频数据。
如果这是问题,有谁知道如何优化这段代码?我尝试在循环之后清空bufferArray,这样它只包含新数据,但是没有用。
如果这不是问题,是否有任何核心图形专家能够找出问题所在?
我还应该提一下,我注释掉了一段代码(用符号标记@@@),因为我需要整个波形。我不希望它在开始时删除波形片段。 iOS Voice Memos应用程序可以保存音频波形而不会降低性能。