基于音量反馈的UIImageView动画

Posted

技术标签:

【中文标题】基于音量反馈的UIImageView动画【英文标题】:UIImageView animation based on volume level feedback 【发布时间】:2015-06-16 10:11:00 【问题描述】:

我需要创建一个具有自定义模式的音频级别可视化工具。我将图像设置为png。 我现在的做法是这样的

1) 获取麦克风的音频电平

2) 根据音量大小将相关图片加载到 UIImageView 中。

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

图像视图

- (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"];



但输出并不像真正的可视化动画那样流畅。最好的方法应该是什么?分享有更好的方法来做到这一点。

几张图片

【问题讨论】:

这听起来可能和这个问题一样:***.com/questions/2834573/… 为什么每次在设置图像属性之前都将图像设置为零(imgViewRecordAnimation.image = nil;)? 【参考方案1】:

如果您觉得图像变化看起来很生涩,最好在它们上应用动画。顺便说一句,您不需要将nil 设置为imgViewRecordAnimation.image,因为您一直在设置正确的图像,这会引入不必要的延迟。您也可以将所有 if 语句都设置为 else if,否则每次执行所有 if 语句。

要找到解决方案,您只需点击@MileAtNobel 发布的链接即可。或者,如果您不想做太多代码更改,您可以在 backgroundColor 属性上应用简单的动画。您也可以删除计时器,检查下面的代码,看看代码是否运行良好。我也尝试过优化相似的代码,希望能提高性能。

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

【讨论】:

感谢回答,但还是一样,不像普通的图像动画那样流畅 在这种情况下,您应该查看找出卷需要多长时间。在开始之前和结束之后获取时间戳(如我的代码中所述)并查看时差,我认为您的音量逻辑需要更多时间,这就是动画不流畅的原因。【参考方案2】:

好的,我不会给你一个直接的解决方案,但会尝试提出一个解决方案,你必须尝试。 因此,与其更改 imageView 的图像,不如编写一个自定义控件。 创建视图的子类。覆盖drawrect方法。在这种情况下,您可以根据控制值绘制所需的图案,也可以绘制图像本身。但建议使用第一种方法。 与更改图像相比,自定义绘图更流畅。 请尝试一下,让我知道它有效。

【讨论】:

以上是关于基于音量反馈的UIImageView动画的主要内容,如果未能解决你的问题,请参考以下文章

在 iOs 中调用按钮 setBackgroundImage 后 UIImageView 位置发生变化

如何取消基于UIView块的动画?

将 UIImageView 添加到 UIButton

为啥 uiimageview 的 contentmode 不起作用?

图像未绑定到UIImageView

使用 CGAffineTransform 使用 UIViewContentModeTop 缩放 UIImageView