我通过将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尊重我在音频编辑器中添加的沉默,而不是通过编程方式填充数据而添加的沉默?
答案 0 :(得分:0)
声音数据不仅仅是数据。它是一个AIF文件,它还包含一个标题,用于定义内容的长度。 AVAudioPlayer显然正在查看标题,而不是缓冲区的长度。