2010-11-23 5 views
1

나는 녹음 응용 프로그램을위한 에뮬레이트 된 아날로그 VU 미터를 만들었고 모든 것이 제대로 연결되고 한 가지 측면을 제외하고는 기대했던대로 작동합니다. VU 미터가 작동중인 watch this 13-second video이라면 바늘이 모든 곳에서 튀어 나와 실제 VU 미터에서 실제로 발생하지는 않습니다. 내가 찾고있는 예를 보려면 Apple의 "음성 메모"앱을 사용해보십시오.현실적인 아날로그 VU 미터의 오디오 레벨 미터링을 부드럽게 할 수 있습니까?

내 논리는 지금까지 쉽게 : 기본적으로

#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을 얻으려면 AudioQueuemAveragePower을 사용하고 있으며 currentDB이 호출 될 때마다 쿼리합니다. 어떻게 이것을 부드럽게 할 수 있습니까?

+0

radianAngleForValue : needleValue : method를 나와 공유 하시길 바랍니다. VU 미터를 작동 시키려고하는데, 작동하지 않습니다. –

+0

각도는 고객님의 구현에 따라 매우 다양합니다. 바늘 길이와 눈금에 따라 달라 지므로 값을 표시하기 위해 만든 이미지로 결정됩니다. 필자는 여러 가지 방정식을 풀고 설정에서이 함수에 필요한 값을 검색하기 위해 종이로 작업하는 데 시간이 걸렸다. 이 링크는 스스로 설정하는 방법을 결정하는 데 유용했습니다. http://neolit123.blogspot.com/2009/03/designing-analog-vu-meter-in-dsp.html#hcon – coneybeare

+0

감사합니다. 내가 알아낼 수있게 도와 줘. 잠들지 않는 주말, 여기와! 지금 당장은 바늘이 옆으로 움직이는 VU 미터를 엉뚱한 방법으로 구현 했습니다만, 나는 그런 것처럼 보이지만 실제로 VU 미터가 필요합니다. –

답변

2

내가 제안하는 한 가지는 이것을 바꾸는 것입니다. 두 번째 5 배 업데이 트를 말한다

#define VU_METER_FREQUENCY 1.0/5.0 

는 문제는 내가 사과 샘플의 0.2 초를 개최한다 생각, 그래서 당신이 정말로 따라서 미터가 정말가는 곳마다 다음되지 않고, 소리의 평균을 받고 있다는 것입니다 의 소리보다 더 낮은 평균의 소리.

이 설정은 1.0/60 (60hz)만큼 높을 수 있다고 생각합니다.

미터를 매끄럽게 만드는 것은 조금 까다 롭습니다.

다음과 같이 할 수 있습니다.

  1. 7-8 값을 포함하는 배열을 만듭니다.
  2. 읽을 때마다 배열에 추가하고 7 번째 값을 팝합니다 (예 : 마지막 7 개의 값만 유지).
  3. 배열의 평균을 찾습니다 (배열/요소의 수를 요소의 수로 나눕니다). 배열.
  4. 표시이 평균.

그래서 파이프를 채우고, 당신은 충전을 중지하면 그것은 비어와 바늘이 천천히 아래로 떨어질 것를위한 시간이 좀 걸릴 것 같은 그 조금.

또는 바늘 만 매 사이클마다 너무 많이 떨어질 수 있습니다.

바늘 스윙이 0 (가장 낮은 값)과 1 (가장 높은 값이 먼 쪽)이라고합시다. 20hz (20x 1 초)로 샘플링한다고 할 수 있습니다.

위치를 업데이트 할 때마다 바늘이 ​​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; 
+0

샘플 배열을 사용하여 예외를 필터링하고, 큰 점프를 억제하기 위해 MIX, MAX 메서드로 매끄럽게 구현했습니다. 아래의 CADisplayLink를 사용하여 약 60HZ 재생 빈도를 얻었으며 UIView 애니메이션을 완전히 없앴습니다. – coneybeare

2

위키 백과에 따르면 VUMeter의 동작은 ANSI 사양 C16.5-1942에 정의되어 있습니다. 바늘의 최대 상승 및 하강 시간은 300mSec이며 그 기간 동안의 평균 음량입니다.

바늘 각으로 1 각형의 로우 패스 필터를 사용하여 각 속도를 대략적으로 측정하고 CADisplayLink 기반의 drawRect 애니메이션을 사용하여 프레임별로 수동으로 미터에 애니메이션을 적용합니다. 보기 애니메이션이 동일한 응답을 제공하지 않을 수도 있습니다.

+0

더하기 CADisplayLink의 경우 1입니다. Didnt는 그것에 대해 알고있다. – coneybeare