ios - 如何在到达音频结尾之前阻止AVAudioPlayer重复播放?

标签 ios audio avaudioplayer nsdata

通过将numberOfLoops属性设置为-1,我正在使用AVAudioPlayer播放循环声音。而且我想以编程方式控制循环速率,因此我要像这样加载音频数据:

NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"Click" ofType:@"aif"];
NSMutableData *soundData = [NSMutableData dataWithContentsOfFile:soundFilePath];

然后在初始化音频播放器之前更改其长度:
int loopDuration = .5; // seconds
int desiredDataLength = loopDuration * 2 * 44100; // this assumes 16-bit mono data
[soundData setLength:desiredDataLength];
NSLog(@"data: %@", soundData); // this shows the data after our length change
AVAudioPlayer soundPlayer = [[AVAudioPlayer alloc] initWithData:soundData error:NULL];
soundPlayer.numberOfLoops = -1;
[soundPlayer play];

如果我将loopDuration设置为小于原始文件的持续时间,则此方法非常有效-多余的数据将被截断并且循环以所需的速度播放。但是,如果我设置的loopDuration长于原始文件,则循环播放得太快-每次迭代仅持续与原始文件的持续时间一样长的时间。

我可以从NSLog行中确认soundData正在被填充到正确的长度。我以为AVAudioPlayer可能会忽略数据中的尾随0,并在看到所有0时重新启动循环,因此,我尝试简单地将其填充一些值,而不是简单地设置数据长度:
NSData *filler = [@"1234" dataUsingEncoding:NSASCIIStringEncoding];
while (desiredDataLength > [soundData length]) {
    [soundData appendData:filler];
}

但是循环仍然在原始文件数据停止的位置重新开始。作为健全性检查,我尝试将声音数据加倍...
    [soundData appendData:soundData];

...然后将numberOfLoops设置为4并播放数据。我原本希望听到8次声音,但只听4次!但是,如果我记录soundData,我可以看到它的长度已加倍。

似乎在循环机制中内置了某种智能,可以使循环在其认为应该的时候重启,而不是在到达数据末尾时重启。是否有人了解真正发生的事情以及如何解决该问题以获得期望的结果?

更新:我发现,如果我在音频编辑器中打开原始声音文件并在两端添加静音,以使它们足够长以达到最慢的循环速度,则AVAudioPlayer会按需处理它们。但是当我查看NSLog输出时,我看到该数据也以全0结尾。为什么AVAudioPlayer尊重我在音频编辑器中添加的静音,却不尊重我通过编程填充数据而添加的静音?

最佳答案

声音数据不仅是数据。这是一个AIF文件,其中还包含一个定义内容长度的 header 。 AVAudioPlayer显然是在查看 header ,而不是缓冲区的长度。

关于ios - 如何在到达音频结尾之前阻止AVAudioPlayer重复播放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9039972/

相关文章:

javascript - 更高效的 decodeAudioData()?

将 WAV 转换为 base64

iphone - 播放声音文件时出现故障 "AudioQueueObject::IONodeConnection::_AcquireHardwareCodec: failed (' hwiu')"

ios - AVAudioPlayer 不播放长音?

swift - forResource 为零

ios - 如何在播放音乐文件期间让动画在精确点工作?

ios - 如何检测 NSString 是否包含 NSTextAttachment 图像?

ios - Swift coreData 上下文无法保存

ios - 我应该只为 UIAppearance 子类化吗

ios - 如何从点击位置获取 UITextView 中文本的范围值?