Search code examples
iphoneiosaudioxcode4

How to easily play back to back .m4a files programmatically on an iOS iPhone app


How can I play more than one .m4a file consecutively?

Presently, my function starts playing one, using AudioServicesPlaySystemSound etc., uses AudioServicesAddSystemSoundCompletion to select a callback, and then returns. When the sound is done, the callback lets my software continue.

This is a LOT of coding whenever there is back to back sound.

Can my software start a .m4a playing, and SOMEHOW wait for it to complete, waiting waiting for its callback to set a flag? Can I use pthread software to do a wait loop with a multitasking pause?

Here's my code so far...

// Restore game_state to continue game after playing sound file. int game_state_after_sound; void play_sound_file_done ( SystemSoundID ssID, void calling_class ) { printf("\n play_sound_file_done."); // Sound is now done, so restore game_state and continue to manage_game from where left off: game_state = game_state_after_sound; [ (GeController)calling_class manage_game]; }

// Plays sound_file_m4a and returns after playing has completed.
-(void) play_sound_file: (NSString *) sound_file_m4a
{
    printf("\n play_sound_file '%s' ", [sound_file_m4a UTF8String] );
    NSString *soundPath = [[NSBundle mainBundle] pathForResource:sound_file_m4a ofType:@"m4a"]; 
    SystemSoundID soundID; 

    AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID); 
    AudioServicesPlaySystemSound (soundID); 
    AudioServicesAddSystemSoundCompletion ( soundID, NULL, NULL, play_sound_file_done, (void*)self ); 

    game_state_after_sound = game_state;
    game_state =  DELAY_WHILE_PLAYING_SOUND;
}

********************************** AVPlayer work-in-progress...

But this produces no sound.

#import <AVFoundation/AVFfoundation.h> 

-(void) play_queued_sounds: (NSString *) sound_file_m4a
{
    printf("\n queue_sound_file: '%s' ", [sound_file_m4a UTF8String] );

    AVPlayerItem *sound_file = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:sound_file_m4a ofType:@"m4a"]]]; 
    AVQueuePlayer *player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:sound_file, nil]];  

    [player play]; 

    return;
}

Solution

  • I could not get the AVQueuePlayer solution to work.

    GREAT SOLUTION: For each sound to play, spin up a thread that awaits then locks a mutex, then does AudioServicesPlaySystemSound. Just spin up a thread for each successive sound to play, and use the pthread mutex to delay each successive thread until the AudioServicesAddSystemSoundCompletion function unlocks the mutex. Works like a champ.

    This is 21st century embedded programming: Throw threads at the problem!