我可以平滑音频电平测量以获得更逼真的模拟VU表吗?

时间:2010-11-23 04:09:02

标签: iphone audio recording smoothing metering

我已经为录音应用程序构建了一个模拟的模拟VU表,并且除了一个方面外,所有内容都正常连接并按照我的预期方式工作。如果您正在使用VU表的watch this 13-second video,您将看到针头在整个地方反弹,并不是真正的VU表中会发生什么。有关我正在寻找的示例,请尝试Apple“语音备忘录”应用程序并查看。

到目前为止我的逻辑很容易:

#define VU_METER_FREQUENCY                                      1.0/5.0

- (void)someMethod {
    _updateTimer = [NSTimer 
                    scheduledTimerWithTimeInterval:VU_METER_FREQUENCY
                    target:self 
                    selector:@selector(_refresh) 
                    userInfo:nil 
                    repeats:YES];
}

- (void)_refresh {  
    // if we have no queue, but still have levels, gradually bring them down
    if (_delegate == nil) {
        CFAbsoluteTime thisFire = CFAbsoluteTimeGetCurrent();
        // calculate how much time passed since the last draw
        CFAbsoluteTime timePassed = thisFire - _peakFalloffLastFire;
        needleValue = needleValue - timePassed * VU_METER_LEVEL_FALL_OFF_PER_SECOND;
        if (needleValue < VU_METER_MIN_DB) {
            needleValue = VU_METER_MIN_DB;
            TT_INVALIDATE_TIMER(_updateTimer);
        }
        _peakFalloffLastFire = thisFire;
    } else {
        prevNeedleValue = needleValue;
        needleValue = [_delegate currentDB];
    }
    [self updateNeedle];
}

- (void)updateNeedle {
    [UIView beginAnimations:nil context:NULL]; // arguments are optional
    [UIView setAnimationDuration:VU_METER_FREQUENCY];
    [UIView setAnimationCurve:(needleValue > prevNeedleValue ? UIViewAnimationCurveEaseOut : UIViewAnimationCurveEaseIn)];
    CGFloat radAngle = [self radianAngleForValue:needleValue];
    self.needle.transform = CGAffineTransformMakeRotation(radAngle);
    [UIView commitAnimations];
}

基本上,我设置一个计时器在VU_METER_FREQUENCY运行,并使用UIView动画更新针旋转,并使用优先保持针更高的缓动。我正在寻找一种方法来调整它以提供更平滑的针,我的基准测试尽可能接近Apple的模拟VU仪表。要获得needleValue,我使用AudioQueue的{​​{1}}并在每次调用mAveragePower时查询它。我怎么能顺利度过这个?

2 个答案:

答案 0 :(得分:2)

根据维基百科,VUMeter的行为在ANSI规范C16.5-1942中定义。针的完全上升和下降时间应该是300毫秒,平均响度超过该持续时间。

我会尝试在针角上使用1极低通滤波器来近似该角速率,并使用基于CADisplayLink的drawRect动画逐帧手动设置仪表的动画。查看动画可能无法提供相同的响应。

答案 1 :(得分:2)

我建议改变这一点。

#define VU_METER_FREQUENCY    1.0/5.0

那说更新5倍一秒,问题是我认为苹果将保持0.2秒的样本,所以你真的得到了声音的平均值,因此仪表并没有真正跟随声音的高点和低点但是更低的平均值。

我认为此设置可以高达1.0 / 60(60hz)。

至于使仪表平稳,这有点小问题。

你可以这样做。

  1. 创建一个包含7-8个值的数组。
  2. 每次读取数据时,将其添加到数组中并弹出第7个值(例如,只保留最后七个值。
  3. 查找数组的平均值(将数组/除以数组中元素的数量。
  4. 显示此平均值。
  5. 所以它有点像填充管道,一旦你停止填充,它将需要一些时间来清空,针将慢慢下降。

    或者你只能让针在每个周期都掉下来。

    让我们说针摆动是0(最低值)和1(最右边的最高值)。 让我们再说你以20hz(每秒20次)的样品。

    每次更新位置时,只允许针头上升,最大值为0.1,而值仅为0.05。

    你可以做这样的事情,并使用这些值来使它变得美观和流畅。

    if newValue>currentMeterValue
       currentMeterValue = Min(currentMeterValue + 0.1, newValue);
    else
       currentMeterValue = Max(currentMeterValue - 0.05, newValue);
    

    OR

    您只需按照与每个值之间的距离成比例的速度移动仪表(这应该很好地平滑)并且实际上接近真实的仪表,弹簧推动由电磁铁驱动的针。

       currentMeterValue += (newValue - currentMeterValue)/4.0;