UIImageView animation based on volume feedback

I have a requirement to create a sound level visualizer with a custom template. I have an image set as png. My current approach is similar to this

1) Get the microphone sound level

2) Load the appropriate image into the UIImageView based on the volume level.

// audio level timer self.levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.001 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES]; 

Imageview

 - (void)levelTimerCallback:(NSTimer *)timer { [self.audioRecorder updateMeters]; const double ALPHA = 0.05; double peakPowerForChannel = pow(10, (0.05 * [self.audioRecorder peakPowerForChannel:0])); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; //NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [self.audioRecorder averagePowerForChannel:0], [self.audioRecorder peakPowerForChannel:0], lowPassResults); if (lowPassResults > 0.0 && lowPassResults <= 0.05){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim1"]; } if (lowPassResults > 0.06 && lowPassResults <= 0.10){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim2"]; } if (lowPassResults > 0.11 && lowPassResults <= 0.15){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim3"]; } if (lowPassResults > 0.16 && lowPassResults <= 0.20){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim4"]; } if (lowPassResults > 0.21 && lowPassResults <= 0.25){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim5"]; } if (lowPassResults > 0.26 && lowPassResults <= 0.30){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim6"]; } if (lowPassResults > 0.31 && lowPassResults <= 0.35){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim7"]; } if (lowPassResults > 0.36 && lowPassResults <= 0.40){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim8"]; } if (lowPassResults > 0.41 && lowPassResults <= 0.45){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim9"]; } if (lowPassResults > 0.46 && lowPassResults <= 0.50){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim10"]; } if (lowPassResults > 0.51 && lowPassResults <= 0.55){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim11"]; } if (lowPassResults > 0.56 && lowPassResults <= 0.60){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim12"]; } if (lowPassResults > 0.61 && lowPassResults <= 0.65){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim13"]; } if (lowPassResults > 0.66 && lowPassResults <= 0.70){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim14"]; } if (lowPassResults > 0.71 && lowPassResults <= 0.75){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim15"]; } if (lowPassResults > 0.76 && lowPassResults <= 0.80){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim16"]; } if (lowPassResults > 0.81 && lowPassResults <= 0.85){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim17"]; } if (lowPassResults > 0.86 && lowPassResults <= 0.90){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim18"]; } if (lowPassResults > 0.86){ imgViewRecordAnimation.image = nil; imgViewRecordAnimation.image = [UIImage imageNamed:@"anim19"]; } } 

But the result is not as smooth as a real visualizer animation. What should be the best approach? Share the best ways there.

Multiple images

enter image description here

enter image description here

enter image description here

+6
source share
2 answers

If you feel that the image changes look jerky, you better apply animation to them. By the way, you do not need to install nil in imgViewRecordAnimation.image , because you are setting the right image after all the time that will lead to an unnecessary delay. You can also do all if else statements if, otherwise, every time all if statements are executed.

Getting started, you can simply follow the link sent by @MileAtNobel. Or, if you do not want to make a lot of code changes, you can apply a simple animation in the backgroundColor property. You can also delete the timer, check the code below and see if the code works. I also tried to optimize the code with close similarities, hope this improves performance.

 BOOL flagToContinue ; //assign NO to this flag to stop updating the images -(void)levelTimerCallback { NSLog(@"Volume Logic Begins") ;//Volume level logic begins [self.audioRecorder updateMeters]; const double ALPHA = 0.05; double peakPowerForChannel = pow(10, (0.05 * [self.audioRecorder peakPowerForChannel:0])); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults ; NSLog(@"Volume Logic ends") ;//Volume level logic ends [UIView animateWithDuration:0.001f delay:0.0f options: UIViewAnimationOptionCurveLinear animations:^{ mgViewRecordAnimation.backgroundColor = [UIColor colorWithPatternImage:[NSString stringWithFormat:@"anim%d", (int)ceil(lowPassResults * 20)]]; } completion:^(BOOL finished) { if(finished && flagToContinue) [self levelTimerCallback]; }]; } 
+3
source

Well, I will not give you a direct solution, but I will try to offer a solution that you will have to try. So instead of changing the imageView image, write a custom control. Subclass the view. Override the drawrect method. In this case, you can draw the desired template depending on the control value or you yourself draw the image. But the first approach is recommended. Custom drawing is smooth compared to changing the image. Please try and let me know that this works.

+2
source

Source: https://habr.com/ru/post/989203/


All Articles