Question

J'ai construit un compteur analogique VU émulé pour une application d'enregistrement et ont tout accroché correctement et travailler comme je l'attends, sauf pour un aspect. Si vous regarder cette vidéo de 13 secondes du VU-mètre en action, vous verrez que l'aiguille rebondit partout dans le lieu et n'est pas vraiment ce qui se passerait dans un vrai VU-mètre. Pour un exemple de ce que je cherche, essayer l'application Apple « Mémos vocaux » et voir.

Ma logique est tellement facile:

#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];
}

Fondamentalement, la configuration I d'une minuterie de fonctionner à VU_METER_FREQUENCY et mettre à jour la rotation de l'aiguille en utilisant une animation UIView avec l'assouplissement qui est préférentiel pour maintenir l'aiguille supérieure. Je cherche un moyen de régler cette certaine façon de fournir une aiguille plus lisse, avec mon point de référence étant le plus près possible de l'analogique d'Apple VU-mètre. Pour obtenir le needleValue, je me sers de AudioQueue de mAveragePower et l'interrogation chaque currentDB temps est appelé. Comment puis-je lisser cela?

Était-ce utile?

La solution

Une chose que je suggère est en train de changer cela.

#define VU_METER_FREQUENCY    1.0/5.0

Cette mise à jour dit 5x une seconde, la question est que je pense que Apple va tenir 0.2s d'échantillons, de sorte que vous obtenez vraiment une moyenne des sons, d'où le compteur ne suit pas vraiment les hauts et les bas des sons, mais plus d'un moyen plus faible.

Je pense que ce paramètre peut aller aussi haut que 1.0 / 60 (60 Hz).

pour rendre le compteur lisse, qui est un peu Tricker.

Vous pourriez faire quelque chose comme ça.

  1. Créer un tableau qui contient les valeurs 7-8.
  2. chaque fois que vous obtenez une lecture, l'ajouter au tableau et de la pop la valeur 7 (par exemple, maintenir que les sept dernières valeurs.
  3. Calculer la moyenne de la matrice (la matrice somme / division par le nombre d'éléments dans le tableau.
  4. Afficher cette moyenne.

est un peu comme le remplissage d'un tuyau, et une fois que vous cessez de remplir il faudra un certain temps pour qu'il vide et l'aiguille va lentement tomber.

ou vous ne pouvait permettre à l'aiguille de tomber tant que chaque cycle.

permet de dire que les sautes d'aiguilles de 0 (valeur la plus faible) et 1 (valeur la plus élevée du côté de la main droite). Disons aussi vous échantillon à 20Hz (20x fois par seconde).

Chaque fois que vous mettez à jour la position de l'aiguille ne permet de monter dire 0,1 d'une valeur maximale et qui ne relèvent que de la valeur 0,05.

vous pouvez faire quelque chose comme ça et jouer avec les valeurs pour l'obtenir agréable et lisse.

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

ou

Vous déplacez simplement le compteur à une vitesse proportionnelle à la distance entre chaque valeur (cela devrait lisser bien) et en fait être près de mètre réel avec un ressort poussant contre l'aiguille qui est alimenté par un électro-aimant.

   currentMeterValue += (newValue - currentMeterValue)/4.0;

Autres conseils

Selon Wikipedia, le comportement d'un vumètre est défini dans les spécifications dans C16.5-1942 de ANSI. L'aiguille plein essor et le temps chute est censé être 300 ms, le volume de la moyenne sur cette durée.

I tenterait un filtre passe-bas 1 pôle sur l'angle de l'aiguille pour se rapprocher que la vitesse angulaire, et animer le compteur manuellement sur une base trame par trame en utilisant une animation basée drawRect CADisplayLink. Voir l'animation pourrait ne pas donner la même réactivité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top