iphone - 将 UIView 动画速度与音频播放同步

标签 iphone ios animation uiview

我有一个垂直的单像素 View ,我想在表示正在演奏的音符的网格上移动。根据歌曲的 BPM(每分钟节拍数),动画应该变慢或变快。音符彼此挤压在一起,宽度为 25 像素。

我现在这样做的方法是每次通过 x 个样本时将 View 向右移动 1px:

int bpm = 90;
int interval = (44100 * 60.0f / song.bpm) / 25.0f; // = 1176
// sample rate=44100 multiplied by 60 (seconds) divided by number of pixels

因此,在 BPM=90 的情况下,每播放 1176 个样本,我将 UIView 移动 1px。这工作得很好,但如果 BPM 高于 180,就会给我带来问题。此时, View 落后于播放的音乐,当 BPM 上升到 240 时, View 会偏离。

我如何使用 Views 的内置动画功能来实现这一点,并根据我在上面发布的计算来确定动画速度?我想在音乐开始播放后开始播放动画,所以我不这样做不需要逐像素手动移动它。

最佳答案

如果我没理解错的话,你想要做的是:

  1. 绘制静态背景图像。
  2. 在从左向右移动的那个上面画一条垂直线。
  3. 将线路的 x 位置与音频播放时间同步。

有两个问题需要解决:

  • 绘画表现
  • 音频同步

要获得正确的绘图性能,需要考虑两种实现方式:

  1. 使用 Core Animation 层和动画(比 2 更容易实现。)
  2. 使用 OpenGL 绘制整个 View (可能比 1 快一点,延迟少一点。)

在 OpenGL 中实现 View 的代码太多,无法作为示例发布,但这里是核心动画选项的代码:

// In the UIViewController:

- (CALayer *)markerLayer
{
    static NSString *uniqueName = @"com.mydomain.MarkerLayer";
    for (CALayer *layer in self.view.layer.sublayers) {
        if ([layer.name isEqualToString:uniqueName])
            return layer;
    }

    CALayer *markerLayer = [CALayer layer];
    markerLayer.backgroundColor = [UIColor whiteColor].CGColor;
    markerLayer.name = uniqueName;
    markerLayer.anchorPoint = CGPointZero;
    [self.view.layer addSublayer:markerLayer];
    return markerLayer;
}

- (void)startAnimationWithDuration:(NSTimeInterval)duration
{
    [CATransaction begin];
    [CATransaction setDisableActions:YES];

    CALayer *markerLayer = [self markerLayer];

    markerLayer.bounds = (CGRect){.size = {1, self.view.bounds.size.height}};
    markerLayer.position = CGPointZero;
    [CATransaction commit];

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];
    animation.fromValue = @0.0f;
    animation.toValue = [NSNumber numberWithFloat:self.view.bounds.size.width];
    animation.duration = duration;
    [markerLayer addAnimation:animation forKey:@"audioAnimation"];
}

音频同步在很大程度上取决于您播放它的方式,例如使用 AVFoundation 或 Core Audio。要获得精确的同步,您需要来自音频引擎的某种回调,告诉您播放现在的确切位置或播放开始的时间。

也许在您开始播放音频之前立即调用 startAnimationWithDuration: 就足够了,但这似乎有点脆弱并且取决于音频框架的延迟。

关于iphone - 将 UIView 动画速度与音频播放同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12046940/

相关文章:

iphone - MPMoviePlayerController 代码在 iPhone(运行 4.3)上播放视频,但不能在 iPodTouch(运行 4.2)上播放视频

iphone - 未显示启用应用内购买

ios - 在结构类上查看为 var

jquery - 将动画添加到自举 Accordion 中,同时保持适当的加减号

javascript - 使用 javascript 和 CSS 在曲线上制作 sin 和 cos 动画

iphone - bundle 访问中的sqlite db路径?

iphone - 在模拟器中重置 ALAssetsLibrary 的权限

ios - 如何在游戏中创建不同的状态,即 gameStatePlaying

iphone - UIWebView 中的字体显示不正确

javascript - IE-11 贬低了与时间相关的功能。用什么代替 t :seq in IE 11 to switch the images