在IOS核心音频中,如何找到文件播放器音频单元的真实当前播放头位置?

Posted

技术标签:

【中文标题】在IOS核心音频中,如何找到文件播放器音频单元的真实当前播放头位置?【英文标题】:In IOS core audio, how do you find the true current play head position of a file player audio unit? 【发布时间】:2012-07-31 17:27:12 【问题描述】:

我有一个程序,它使用文件播放器音频单元来播放、暂停和停止音频文件。我完成此操作的方法是初始化文件播放器音频单元以在零位置播放文件,然后当用户按下暂停按钮时,我停止 AUGraph,捕获当前位置,然后使用该位置作为开始位置当用户按下播放按钮时。一切正常,但是每 3 或 4 次我点击暂停然后播放,这首歌在我点击暂停之前开始播放半秒到整秒。

我不知道为什么会这样,你们有什么想法吗?这是我的代码的简化版本。

//initialize AUGraph and File player Audio unit
...
...
...

//Start AUGraph 
...
...
...

// pause playback
- (void) pauseAUGraph 

//first stop the AuGrpah
        result = AUGraphStop (processingGraph);

// get current play head position        
        AudioTimeStamp ts;
        UInt32 size = sizeof(ts);

        result = AudioUnitGetProperty(filePlayerUnit, 
                                      kAudioUnitProperty_CurrentPlayTime, kAudioUnitScope_Global, 0, &ts, 
                                      &size);
        //save our play head position for use later
        //must add it to itself to take care of multiple presses of the pause button
        sampleFrameSavedPosition = sampleFrameSavedPosition + ts.mSampleTime; 


        //this stops the file player unit from playing
        AudioUnitReset(filePlayerUnit, kAudioUnitScope_Global, 0); 
        NSLog (@"AudioUnitReset - stopped file player from playing");

    //all done    



// Stop playback

- (void) stopAUGraph 
        // lets set the play head to zero, so that when we restart, we restart at the beginning of the file. 

          sampleFrameSavedPosition = 0;
        //ok now that we saved the current pleayhead position, lets stop the AUGraph
        result = AUGraphStop (processingGraph);

【问题讨论】:

音频文件是什么格式的? 好吧,我不是音频压缩方面的专家,但文件往往被压缩成块,当你寻找它时,它可能会转到最近的块而不是实际位置。如果我遇到任何更明确的问题,我会发布答案。 有人解决了吗?我遇到了同样的问题。我正在使用 60 fps 的 displaylink 播放与音频单元播放的音频的 currentTime 同步的节拍器。我注意到 0.05 秒的延迟非常明显 嗨@Beleg你能告诉我如何在播放歌曲期间以秒为单位获取时间吗?即 0,1,2 .... 秒。我想在播放器中以秒为单位显示时间 【参考方案1】:

您可能应该使用数据包计数而不是时间戳,因为您只想暂停和播放音乐,而不是显示时间信息。

有关使用此方法的示例,请参阅 BufferedAudioPlayer。

【讨论】:

所以你建议使用渲染回调而不是文件播放器音频单元并计算数据包而不是使用时间戳?今晚我会试一试。 是的。我在不止一个项目中成功地使用了它。 Audiograph (github.com/tkzic/audiograph) 是另一个采用相同方法的示例。该项目还附带一本非常好的手册。【参考方案2】:

这可能是由于您的代码存在四舍五入问题:

例如,如果您每次按下暂停按钮时,您的计时器都会在实际暂停时间前 0.5/4 秒记录,您仍然会看到所需的结果。但是在再重复四次之后,您创建的空间量是 0.5/4 乘以 4,这是您似乎正在经历的半秒。

因此,我会特别注意您使用的对象类型,并确保它们不会不恰当地四舍五入。尝试使用double float 作为您的采样时间以尝试缓解该问题!

希望这是清晰和有帮助的! :)

【讨论】:

我使用 float64 将 audioTimeStamp.mSampletime 存储到 sampleFrameSavedPosition 中,因此不应该有任何舍入错误。我确实注意到,当我通过设置 ScheduledAudioFileRegion.mStartFrame 启动 AuGraph 备份时,ScheduledAudioFileRegion.mStartFrame 是 UInt32 而不是 float64,当我测试我的程序并打印 mSampleTime 的值时所说的总是一个整数,所以它不应该母校。 那么理论上,如果你所有的类型都是整数,它甚至不应该输出分数。你有没有尝试每次都输出头部位置,看看是否加起来?

以上是关于在IOS核心音频中,如何找到文件播放器音频单元的真实当前播放头位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何播放特定频率和框架的声音未找到音频单元问题

如何在音频单元扩展(实时进程)中为音频文件播放分配内存?

如何在 iOS 的 AUGraph 中添加两个 I/O 音频单元?

如何在应用程序中使用音频单元

如何消除来自使用 iOS 中音频单元的套接字的音频中的噪音?

如何在 iOS 中调整音频平衡