Doug Null
Doug Null

Reputation: 8327

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;
}

Upvotes: 2

Views: 3302

Answers (2)

Doug Null
Doug Null

Reputation: 8327

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!

Upvotes: -1

Mick MacCallum
Mick MacCallum

Reputation: 130222

This can be achieved quite easily in AVQueuePlayer. You don't have to handle completion or anything, you just give it the AVPlayerItems that you want to play in sequence and call play. Here's an example:

#import <AVFoundation/AVFfoundation.h>


//AVPlayerItem *item1 = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"myFileName" ofType:@"m4a"]]];

EDIT: Use this instead

AVPlayerItem *item1 = [[AVPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[[NSString alloc] initWithFormat:@"2"] ofType:@"mp3"]]];

AVQueuePlayer *player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:item1, nil]];

[player play];

Just as an addition, this can also be achieved with items from the users iPod library using a MPMusicPlayerController queued from the didPickMediaItems delegate method of MPMediaPickerController

- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
    MPMusicPlayerController *player = [MPMusicPlayerController applicationMusicPlayer];
    [player setQueueWithItemCollection:mediaItemCollection];
    [player play];
}

Upvotes: 3

Related Questions