2010-11-23 7 views
1

Я построил эмулированный аналоговый счетчик VU для приложения для записи и все правильно подключилось и работаю так, как я ожидаю, за исключением одного аспекта. Если вы нажмете watch this 13-second video измерителя VU, вы увидите, что игла отскакивает повсюду, и на самом деле это не так, как в реальном измерителе VU. Для примера того, что я ищу, попробуйте приложение Apple Voice Memos и посмотрите.Мог ли я умереть с помощью аналогового измерителя уровня звука для более реалистичного аналогового измерителя 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 анимации с ослабления, что является предпочтительным, чтобы игла выше. Я ищу способ скорректировать это как-то, чтобы обеспечить более гладкую иглу, и мой бенчмарк был как можно ближе к аналоговому VU Meter от Apple. Чтобы получить needleValue, я использую AudioQueue's mAveragePower и запрашивая его каждый раз, когда вызывается currentDB. Как я могу сгладить это?

+0

Надеюсь, вы не возражаете поделиться своим radianAngleForValue: needleValue: метод со мной. Я пытаюсь заставить мой счетчик VU работать, но он просто не сработает. Я тоже не буду возражать против вас;) – 2011-03-24 04:57:58

+0

Угол очень специфичен для вашей собственной реализации. Это зависит от длины и масштаба иглы, которая определяется изображением, которое вы создаете для отображения значений. Мне потребовалось некоторое время, чтобы разобраться на бумаге, чтобы решить множество уравнений, необходимых и получить значения, необходимые для этой функции в моей настройке. Эта ссылка была ценна при определении того, как настроить ее для себя: http://neolit123.blogspot.com/2009/03/designing-analog-vu-meter-in-dsp.html#hcon – coneybeare 2011-03-24 19:33:43

+0

Спасибо, что, вероятно, помогите мне понять это. Беспощадные выходные, здесь я прихожу! На данный момент у меня есть дерьмовая реализация измерителя VU с иглой, которая движется вбок, хотя мне это нравится, мне нужна реальная сделка с измерителем VU. – 2011-03-24 23:34:00

ответ

2

Одна вещь, которую я предлагаю, это изменить это.

#define VU_METER_FREQUENCY 1.0/5.0 

Это говорит обновление 5 раз в секунду, проблема в том, что я думаю, что яблоко будет держать 0.2S образцов, так что вы действительно получаете в среднем звуков, поэтому счетчик не очень следующие максимумы и минимумы звуков, но более низкого среднего.

Я думаю, что эта настройка может достигать 1,0/60 (60 Гц).

Как сделать измерительный прибор гладким, то есть немного обманом.

Вы могли бы сделать что-то вроде этого.

  1. Создайте массив, содержащий значения 7-8.
  2. Каждый раз, когда вы получаете чтение, добавьте его в массив и введите 7-е значение (например, удерживайте только последние семь значений.
  3. Найдите среднее значение массива (суммируйте массив/разделите на количество элементов в массиве.
  4. Display это среднее.

Таким образом, ее немного, как заполнение трубы, и как только вы перестанете заполнение потребуется некоторое время для того, чтобы опорожнить и игла будет медленно падать вниз.

ИЛИ вы можете позволить только игле падать только за каждый цикл.

Допустим, что игольчатые качели будут 0 (минимальное значение) и 1 (наибольшее значение с правой стороны справа). Позволяет также сказать, что вы пробуете 20hz (20x раз в секунду).

Каждый раз, когда вы обновляете положение, разрешайте игле подниматься, указывая 0.1 значения max и падение только 0,05 значения.

вы можете сделать что-то подобное и поиграть со значениями, чтобы сделать его приятным и гладким.

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

ИЛИ

Вы просто переместите измеритель со скоростью пропорционально расстоянию между каждым значением (это должно сгладить это красиво), и на самом деле близок к реальному метру с пружиной толкающей против иглы, которая питание от электромагнита.

currentMeterValue += (newValue - currentMeterValue)/4.0; 
2

Согласно Википедии, поведение VUMeter определено в спецификации ANSI C16.5-1942. Ожидается, что продолжительность полного и спада иглы составит 300 мсек, усредняя громкость в течение этой продолжительности.

Я попробовал бы 1-полюсный фильтр нижних частот на угол иглы, чтобы приблизиться к этой угловой скорости, и анимировать счетчик вручную по кадру с помощью анимации drawRect, основанной на CADisplayLink. Просмотр анимации может не дать такой же отзывчивости.

 Смежные вопросы

  • Нет связанных вопросов^_^