I’m trying to get smooth audio playback for an app that needs to play samples back in rapid succession. I was hoping Cocos2d and CocosDenshion would make this possible, as AVAudioPlayer doesn’t work because of lag issues, but I’m still getting problems — the “16th notes” as emulated here end up sounding swung.
Am I going to have to go with RemoteIO or something like that? What’s the easiest way to get the precision timing of playing sounds in iOS that I’ll need for the project?
Or, is using the CDAudioEngine playSound: function not the most efficient way I could be doing things with CocosDenshion?
To load engine:
[CDAudioManager sharedManager];
while ([CDAudioManager sharedManagerState] != kAMStateInitialised) {
[NSThread sleepForTimeInterval:0.1];
NSLog(@"Not init yet...");
}
CDSoundEngine *sse = [CDAudioManager sharedManager].soundEngine;
NSArray *defs = [NSArray arrayWithObjects:
[NSNumber numberWithInt:16],nil];
[sse defineSourceGroups:defs];
[[CDAudioManager sharedManager].soundEngine setSourceGroupNonInterruptible:0 isNonInterruptible:TRUE];
NSLog(@"Loading sound: %i",[sse loadBuffer:1 filePath:@"bass drum.wav"]);
[[CDAudioManager sharedManager] setResignBehavior:kAMRBStopPlay autoHandle:YES];
[[CDAudioManager sharedManager] setMode:(kAMM_MediaPlayback)];
The thread code to test the playback (basically the Metronome sample app, editted to use the CocosDenshion playback):
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Give the sound thread high priority to keep the timing steady.
[NSThread setThreadPriority:1.0];
BOOL continuePlaying = YES;
CDSoundEngine *sse = [CDAudioManager sharedManager].soundEngine;
while (continuePlaying) { // Loop until cancelled.
// An autorelease pool to prevent the build-up of temporary objects.
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
[sse playSound:1 sourceGroupId:0 pitch:1.0f pan:0.0f gain:1.0f loop:NO];
withObject:nil waitUntilDone:NO];
NSDate *curtainTime = [[NSDate alloc] initWithTimeIntervalSinceNow:0.125f];
NSDate *currentTime = [[NSDate alloc] init];
// Wake up periodically to see if we've been cancelled.
while (continuePlaying && ([currentTime compare:curtainTime] != NSOrderedDescending)) {
if ([soundPlayerThread isCancelled] == YES) {
continuePlaying = NO;
}
[NSThread sleepForTimeInterval:0.005];
[currentTime release];
currentTime = [[NSDate alloc] init];
}
[curtainTime release];
[currentTime release];
[loopPool drain];
}
[pool drain];
RemoteI0
this has some info on why
http://atastypixel.com/blog/developing-loopy-part-2-implementation/