3

I have one thousand .mp3 files in my Resources folder within an iOS 4.2 XCode project.

For now I can select one file from the folder ( and play it ) with the following code in my .m file: ( Given the file name of "AFile.mp3" )

   -(IBAction)playSound {

        NSString *path = [[NSBundle mainBundle] pathForResource:@"AFile"ofType:@"mp3"];

        AVAudioPLayer* theAudio =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];

        theAudio.delegate = self;
        [theAudio play];
}

I'd like to be able to have the code choose an .mp3 randomly, play it, then select another file and play them all until they have all been played at least once. I assume I will need to use an NSArray, but am uncertain on how to proceeed.

I changed the code to the following, and am not getting any errors when I run this in the iOS Simulator. No File appears to be played when I run it though? When I launch the app, it quits, but does not log any errors in the Debugger..

Updated code:

-(IBAction)playSound {

NSArray *array = [[NSBundle mainBundle] pathsForResourcesOfType:@".mp3" inDirectory:@"Resources"];
NSString *randomPath = [array objectAtIndex:arc4random() % [array count]];

AVAudioPlayer* theAudio =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: randomPath] error: NULL;
    theAudio.delegate = self;
    [theAudio play];

}

How can an I set up a simple array of the 1000 .mp3 files, and have the method play one at random?

cit
  • 2,465
  • 5
  • 28
  • 36
  • Where does `arrayURLWithPath:` come from? – Abizern Jan 03 '11 at 14:20
  • @iPortable Thanks again. When I run now though, the line int rndm = arc4random() % [array count]; issues this in the GDB: Program received signal : "EXC_ARITHMETIC" – cit Jan 04 '11 at 13:46
  • then NSLog() your *array it seems that no values are in there. –  Jan 04 '11 at 13:49
  • Thanks .. I was doing that and did find the array was empty.. I might pose a separate question as to why unless you see something amiss in the first line of the method? There are definitely mp3 files in the /Resources folder... Not sure why the are not being added to the array... – cit Jan 04 '11 at 14:10
  • I changed Resources to '.' and that seemed to fix the issue. – cit Jan 04 '11 at 16:20

5 Answers5

3
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc]initWithContentsofURL: [NSURL arrayURLWithPath:array] error:NULL];

should be:

AVAudioPlayer* theAudio=[[AVAudioPlayer alloc]initWithContentsofURL: [NSURL URLWithString:[array objectAtIndex:11]] error:NULL];

therefore the number '11' is a random file path. To get randomness you can use this:

int randomNumber = random()%1000; // random number between 0 and 1000

and then use randomNumber instead of 11

To play each file only one time you can play let's say song number four one time and then remove this item from your array. The next time you generate a random number use 999 instead of 1000 and so on till it gets to 1.

//EDIT: try following:

-(IBAction)playSound {

    NSArray *array = [[NSBundle mainBundle] pathsForResourcesOfType:@".mp3" inDirectory:@"Resources"];
    int rndm = arc4random() % [array count];
    if (rndm<0) rndm*=-1;
    NSString *randomPath = [array objectAtIndex:rndm];

    AVAudioPlayer* theAudio =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: randomPath] error: NULL;
    theAudio.delegate = self;
    [theAudio play];

}
  • URLWithString: or fileURLWithPath: I don't know what functions you are calling internally –  Jan 03 '11 at 14:34
  • Thanks, I incorporated your suggestion, but am still not having success...see edit above. – cit Jan 03 '11 at 17:14
  • yep as I thought (and therefore i used random() instead of arc4random()). you can get negative numbers in arc4. save your random number separately and check if its negative: int rm = arc4random(); if (rm<0) rm *= -1; –  Jan 03 '11 at 17:29
  • The current solution doesn't seem to account for playing each file once. Why not add something along the lines of a recursive function (which can take an array of unplayed files) and passing the next iteration something like `[[NSMutableArray arrayWithArray:array] removeObject:randomPath];`? – Kyle Lacy Jan 05 '13 at 11:09
3

Use this snippet. from a previous SO answer

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self ENDSWITH '.jpg'"]];

then get the array count.. and use random to get the random integer number and file.

Community
  • 1
  • 1
k-thorat
  • 4,873
  • 1
  • 27
  • 36
  • 1
    I see a " directoryContentsAtPath is deprecated " warning when I run this code in 4.2.1. – cit Jan 03 '11 at 22:15
1

Well, if you already have a reference to the array on which you would like to retrieve a random element from, then it's dead simple:

NSString *randomPath = [array objectAtIndex:arc4random_uniform([array count])];

Also, arc4random() is much better than rand()

Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
1

Ok after looking into the apple documents here is the error. Somehow the even if we specify a custom directory it seems to be only for reference. The other mistake that I have found is that we only need to specify the extension without the "."

NSArray *audioPathArray = [[NSBundle mainBundle] pathsForResourcesOfType:@"mp3" inDirectory:nil];

NSLog(@"%d",[audioPathArray count]);

NSString *path = [audioPathArray objectAtIndex:arc4random() % [audioPathArray count]];

NSURL *randomPath = [[NSURL alloc]initFileURLWithPath:path]; 

AVAudioPlayer *theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:randomPath error:NULL];


[theAudio play];

This is what worked for me. Hope it helps you out.

0

Got it working on my project

When you import the Resources folder to your project select "Create folder references for any added folders". This will actually maintain the directory structure in your [NSBundle mainBundle].

You can then pull the contents like so:

NSString * bundlePath = [NSBundle mainBundle] bundlePath];
NSString * resourceFolderPath = [NSString stringWithFormat:@"%@/Resources", bundlePath];
NSArray * resourceFiles = [[NSFileManager defaultManager] directoryContentsAtPath:resourceFolderPath error:nil];

resourceFiles should contain a list of the contents of your Resources directory.

NSInteger randomFileIndex = arc4random() % [resourceFiles count];
NSString * randomFile = [resourceFiles objectAtIndex:randomFileIndex];
lorean
  • 2,150
  • 19
  • 25