録音アプリ用にエミュレートされたアナログ VU メーターを作成しましたが、すべてが適切に接続され、1 つの側面を除いて期待どおりに動作しています。この13 秒間の VU メーターの動作のビデオを見ると、実際の VU メーターで発生するものとは異なり、針がいたるところで跳ねていることがわかります。私が探しているものの例として、Apple の「Voice Memos」アプリを試してみてください。
これまでの私の論理は簡単です。
#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
が呼び出されるmAveragePower
たびにクエリを実行しています。currentDB
どうすればこれを滑らかにできますか?