Mehul Solanki
Mehul Solanki

Reputation: 463

How to play multiple audio files in sequence by loop in AVAudioPlayer?

I want to play multiple files by using loop.
I written code below..
Please help me.!!..

soundList = [[NSArray alloc] initWithObjects:@"mySong1.mp3",@"mySong2.mp3",@"mySong3.mp3",@"mySong4.mp3",@"mySong5.mp3",@"mySong6.mp3",@"mySong7.mp3",@"mySong8.mp3",@"mySong9.mp3", nil];
for (i=0; i<=([soundList count] - 1); ) {                
    while(i<[soundList count]){
        NSLog(@"File is : %@",[soundList objectAtIndex:i]);
        mediaPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[soundList objectAtIndex:i] ofType:nil]] error:&error];
        [mediaPlayer setDelegate:self];
        self.lblCurrentSongName.text = [soundList objectAtIndex:i];
        [mediaPlayer prepareToPlay];
        i++;
    }
}

Please give me suggestion .!!..

Upvotes: 3

Views: 5910

Answers (4)

smn khan
smn khan

Reputation: 21

simply do it by using recursion ..

@property (nonatomic, strong) NSArray *arrTrackList;
@property (nonatomic, strong) NSMutableArray *arrAduioQueue;
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
@property (nonatomic) NSUInteger itemIndex;

@end

@implementation PLayMultipleTrackViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.arrTrackList = [NSArray arrayWithObjects:@"apple_ring",@"shukriya_pakistan",@"pakistan_anthem", nil];
    self.itemIndex = 0;
}

- (IBAction)TrackToPlay:(id)sender
{
    self.btnPlayAll.enabled = NO;
    NSString *trackFile = [self.arrTrackList objectAtIndex:self.itemIndex];
    [self AddToPlayList:trackFile];
}

-(void)AddToPlayList:(NSString *)file
{
        [self.arrAduioQueue addObject:file];
        [self playTrack:file];
}

-(void)playTrack:(NSString *)soundFile
{
    NSString *soundFilePath =[[NSBundle mainBundle] pathForResource: soundFile ofType: @"m4r"];
    NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
    self.audioPlayer =[[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
    [self.audioPlayer prepareToPlay];
    [self.audioPlayer setDelegate:self];
    self.audioPlayer.volume = 1.0;
    [self.audioPlayer play];
}

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    [self.arrAduioQueue removeObjectAtIndex:0];
    self.itemIndex++;
    NSUInteger trackListIndex = [self.arrTrackList count];

    if (self.itemIndex < trackListIndex)
    {
        NSString *nextTrack = [self.arrTrackList objectAtIndex:self.itemIndex];
        [self AddToPlayList:nextTrack];
    }
    else
    {
        NSLog(@"PLaylist empty");
    }
}
@end

Upvotes: 0

guenis
guenis

Reputation: 2538

I'm going to give you a guideline doing it, but beware it is not tested code. The code you gave will not work for a number of reasons, 1. you don't call play on avaudioplayer 2. while loop will execute too fast and songs will overlap with each other or since you don't store the reference to previous avaudioplayer it might create trouble (don't know exactly)

NSInteger currentSoundsIndex; //Don't forget to set this in viewDidLoad or elsewhere

//In viewDidLoad add this line
{
...
currentSoundsIndex = 0;
...
}

-(void) playCurrentSong
{
NSError *error;
mediaPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[soundList objectAtIndex:currentSoundsIndex] ofType:nil]] error:&error];
if(error !=nil)
{
   NSLog(@"%@",error);
   //Also possibly increment sound index and move on to next song
}
else
{
self.lblCurrentSongName.text = [soundList objectAtIndex:currentSoundsIndex];
[mediaPlayer setDelegate:self];
[mediaPlayer prepareToPlay]; //This is not always needed, but good to include
[mediaPlayer play];
}

}

//This is the delegate method called after the sound finished playing, there are also other methods be sure to implement them for avoiding possible errors
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
//Increment index but don't go out of bounds
currentSoundsIndex = ++currentSoundsIndex % [soundList count];
[self playCurrentSong];
}

Upvotes: 6

BhushanVU
BhushanVU

Reputation: 3455

first declare

AVAudioPlayer *audioPlayer;

NSMutableArray *audioQueue;

and then use below code

-(void) addToPlayerQueue: (NSString *) file {

    if ( [audioQueue count] == 0 )
    {
        [audioQueue addObject:file];
        [self playSound: file];
    }
    else 
    {
        [audioQueue addObject:file];
    }
}


-(void) playSound : (NSString *) soundFile 
{
    NSURL *soundUrl = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:soundFile ofType:@"caf"]];
    if ( soundUrl ) {
        audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
        [audioPlayer setDelegate:self];
        [audioPlayer setVolume: playerVolume];
        [audioPlayer play];
    }
}



#pragma mark -
#pragma mark AVAudioPlayer Delegate Method

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    NSLog(@"Just got done playing %@", [audioQueue objectAtIndex:0]);
    [audioPlayer release];

    [audioQueue removeObjectAtIndex:0];

    if ( [audioQueue count] > 0 )
    {
        NSString *file = [audioQueue objectAtIndex:0];
        [self playSound:file];
    }
}

Upvotes: 1

Rostyslav Druzhchenko
Rostyslav Druzhchenko

Reputation: 3773

There is may be not most elegant solution but you will find here a common idea. It's a completely working code you can copy/paste it in you project and it should to work. Course you have to change file names for your ones. Let me know if you have any problems with it.

#import "MainViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface MainViewController () <AVAudioPlayerDelegate>

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
@property (nonatomic, strong) NSMutableArray *soundsPathsList;
@property (nonatomic, assign) NSInteger curSoundIdx;

@end


@implementation MainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        NSArray *soundList = [[NSArray alloc] initWithObjects:@"myAudioFile 1", @"myAudioFile 2", @"myAudioFile 3",
                              @"myAudioFile 4", @"myAudioFile 5", @"myAudioFile 6", @"myAudioFile 7",
                              @"myAudioFile 8", @"myAudioFile 9", @"myAudioFile 10", nil];

        self.soundsPathsList = [NSMutableArray new];
        for (NSString *fileName in soundList) {
            NSString *pathToFile = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
            NSURL *url = [NSURL fileURLWithPath:pathToFile];
            [self.soundsPathsList addObject:url];
        }

        [self playNext];
    }
    return self;
}

- (void) playNext {

    if (self.curSoundIdx >= [self.soundsPathsList count]) {
        self.curSoundIdx = 0;
    }

    // destroy player object
    [self.audioPlayer stop];
    self.audioPlayer = nil;

    // create new player object
    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:
                        [self.soundsPathsList objectAtIndex:self.curSoundIdx] error:nil];
    self.audioPlayer.delegate = self;
    [self.audioPlayer play];

    self.curSoundIdx++;
}

#pragma mark - AVAudioPlayerDelegate

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    [self playNext];
}

@end

Upvotes: 0

Related Questions