views:

95

answers:

1

I have an audio app in the store. It works fine with versions of the iPhone OS before iOS 4.0. I am working on a new version, starting by bringing the app into compliance with the new iOS multitasking capabilities. (I have iOS 4.0 on my iPhone, and have upgraded to the latest xCode and SDK.)

The result has been a show-stopper.

o When I install the app on the iPhone and run in the debugger, or start the app after the iPhone was powered down, the app acts just fine - playing audio as I push buttons, or restarting audio from "state" that was saved the previous time the app was run.

o If I try to push the Home button and then restart the app from the background, the audio - a and mix of 1-n audio streams - comes out with a stuttering sound that only I could recognize.

o If - while the audio is cleanly - I call the iPhone, I can either answer or decline the call. In both cases the app comes back cleanly, playing as it should.

Note that I am not trying to play anything while in background mode. I simply want to shut things off and bring them back when asked.

Technology: All of the audio logic uses RemoteIO. (I have plans for someday doing some fairly sophisticated signal processing.)

Please excuse the pseudo code narrative - some of the real code is pretty extensive.

MainViewController:

o viewDidLoad - nothing special

o didBecomeActive set self as audio session delegate; set the AudioSessionCategory to MediaPlayback; set the AudioSessionActive; create a Player (see below); restart any sounds that were previously playing;

o willResignActive save the state of what was playing; stopAllSounds; stop the player; set the audio session inactive;

o didEnterBackground - nothing (method is registered, but no content.)

o willEnterForeground - nothing (method is registered, but no content.)

Overview of Player - my class: The Player is a singleton. I make sure that the singleton instance is destroyed, and a new one created, in didBecomeActive. Instantiating the singleton actually starts the AudioUnit.

constructor setupRemoteIO; start AudioOutputUnitStart; stop AudioOutputUnitStop; player callback the usual stuff;

>

Here are some methods from my MainViewController:

(void)willResignActive:(NSNotification *)note {
    [ self saveState ];
    [ [ NaturePlayer getInstance ] stopAllSounds ];
    [ [ NaturePlayer getInstance ] stop ];
    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive: NO error: &activationError]; 
    [NaturePlayer destroy];

}

- (void)didBecomeActive:(NSNotification *)note {
    [ self setupAudioSession ];

    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError]; 
    [ self restartSounds ];
    [ self setViewState ];
}

- (void)didEnterBackground:(NSNotification *)note {
    int xxx = 1;
}

- (void)willEnterForeground:(NSNotification *)note {
    int xxx = 1;
}

- (void) applicationWillTerminate: (NSNotification*) notification {
    int xxx = 1;
}

Here is a method from the NaturePlayer:

/**
 * Stop the playback process.
 */
void NaturePlayerDelegate::stop() {
    if (isPlaying_) {
        AudioOutputUnitStop(outputUnit_);
        isPlaying_ = FALSE ;        
    }

}

I checked: stop() is being called, and in turn calls AudioOutputUnitStop(); Also checked: The doc on AudioOutputUnitStop says it blocks until all activity has completed.

A: 

Hard to say without more details on the audio code. But I suggest you might want to examine your Player object teardown code to make sure the audio unit and the audio session are completely stopped (buffer callback thread drained) before releasing stuff.

hotpaw2
hotpaw2, thanks for the feedback. So far, no luck. You suggested seeing some code might help. So here are methods from a) the MainViewController, and b) the Player.
wjs