我想在 iphone 上编写一个简单的音频音序器,但我无法获得准确的时间。最近几天我在 iphone 上尝试了所有可能的音频技术,从 AudioServicesPlaySystemSound 和 AVAudioPlayer 和 OpenAL 到 AudioQueues。
在我最后一次尝试中,我尝试了 CocosDenshion 声音引擎,它使用 openAL 并允许将声音加载到多个缓冲区中,然后在需要时播放它们。这是基本代码:
在里面:
int channelGroups[1];
channelGroups[0] = 8;
soundEngine = [[CDSoundEngine alloc] init:channelGroups channelGroupTotal:1];
int i=0;
for(NSString *soundName in [NSArray arrayWithObjects:@"base1", @"snare1", @"hihat1", @"dit", @"snare", nil])
{
[soundEngine loadBuffer:i fileName:soundName fileType:@"wav"];
i++;
}
[NSTimer scheduledTimerWithTimeInterval:0.14 target:self selector:@selector(drumLoop:) userInfo:nil repeats:YES];
在初始化中,我创建了声音引擎,将一些声音加载到不同的缓冲区,然后使用 NSTimer 建立音序器循环。
音频循环:
- (void)drumLoop:(NSTimer *)timer
{
for(int track=0; track<4; track++)
{
unsigned char note=pattern[track][step];
if(note)
[soundEngine playSound:note-1 channelGroupId:0 pitch:1.0f pan:.5 gain:1.0 loop:NO];
}
if(++step>=16)
step=0;
}
就是这样,它可以正常工作,但是时间不稳定且不稳定。一旦发生其他事情(例如在视图中绘制),它就会不同步。
据我了解声音引擎和 openAL 缓冲区已加载(在 init 代码中),然后准备立即开始alSourcePlay(source);
- 所以问题可能出在 NSTimer 上?
现在应用商店里有几十个音序器应用程序,它们都有准确的时间。即使在 180 bpm 的缩放和绘图完成时,Ig "idrum" 也具有完美的稳定节拍。所以必须有解决办法。
有人知道吗?
提前感谢您的帮助!
此致,
瓦尔基
感谢您的回答。它让我更进一步,但不幸的是没有达到目标。这是我所做的:
nextBeat=[[NSDate alloc] initWithTimeIntervalSinceNow:0.1];
[NSThread detachNewThreadSelector:@selector(drumLoop:) toTarget:self withObject:nil];
在初始化中,我存储下一个节拍的时间并创建一个新线程。
- (void)drumLoop:(id)info
{
[NSThread setThreadPriority:1.0];
while(1)
{
for(int track=0; track<4; track++)
{
unsigned char note=pattern[track][step];
if(note)
[soundEngine playSound:note-1 channelGroupId:0 pitch:1.0f pan:.5 gain:1.0 loop:NO];
}
if(++step>=16)
step=0;
NSDate *newNextBeat=[[NSDate alloc] initWithTimeInterval:0.1 sinceDate:nextBeat];
[nextBeat release];
nextBeat=newNextBeat;
[NSThread sleepUntilDate:nextBeat];
}
}
在序列循环中,我将线程优先级设置得尽可能高,然后进入无限循环。播放完声音后,我计算下一个节拍的下一个绝对时间,并让线程进入睡眠状态,直到此时。
这再次起作用,并且它比我在没有 NSThread 的情况下的尝试更稳定,但如果发生其他事情,它仍然不稳定,尤其是 GUI 的东西。
有没有办法在 iPhone 上使用 NSThread 获得实时响应?
此致,
瓦尔基