Choose a file randomly from Resources folder in iOS - iphone

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?

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

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.

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.

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()

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

Related

mixing of five songs in iphone sdk

In my app I have five buttons and every button have five songs. In the main view there is a star (contains five ends) in the view. When the user drags the button to the end of the star it should play the song. Link this same has four and we want to mix those songs into a file like a ringtone saved it in to a tmp directory. I had tried a lot for this but I'm unable to get an answer to the problem.
The code I'm using is:
- (void) doAudioCallback: (NSTimer *)timer {
NSString *resName1 = #"drum1.aif";
NSString *resName2 = #"drum2.aif";
NSString *resPath1 = [[NSBundle mainBundle] pathForResource:resName1 ofType:nil];
NSString *resPath2 = [[NSBundle mainBundle] pathForResource:resName2 ofType:nil];
NSString *tmpDir = NSTemporaryDirectory();
NSString *tmpFilename = #"MixedoftwoSongs.aif";
NSString *tmpPath = [tmpDir stringByAppendingPathComponent:tmpFilename];
OSStatus status;
if (status == OSSTATUS_MIX_WOULD_CLIP) {
} else {
NSURL *url = [NSURL fileURLWithPath:tmpPath];
NSData *urlData = [NSData dataWithContentsOfURL:url];
NSLog(#"wrote mix file of size %d : %#", [urlData length], tmpPath);
AVAudioPlayer *avAudioObj = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
self.avAudio = avAudioObj;
[avAudioObj prepareToPlay];
[avAudioObj play];
}
}
I think you have to use Perform Selector to delay your each audio
[self performSelector:#selector(yourmethod) withObject:nil afterDelay:0.5];

pathForResource dynamic input

I am trying to write code with dynamic input for pathForResource but I get null value for the directory listing. the files I am using are wav files. Here is the code. I have a.wav file in the project folder. What is wrong here? how can I make this work? Please help.
int alphanum = 97;
NSString *alphastring = [NSString stringWithFormat:#"%i",alphanum];
NSString *path = [[NSBundle mainBundle] pathForResource:alphastring ofType:#"wav"];
AVAudioPlayer *theplayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[theplayer play];

iOS: NSUrl Syntax

I currently have this code that works. I have two questions.
How do I set the directory to "Supporting Files"?
How do I use a variable in the file name? I need it to pull an mp3 of any animal based on a variable.
- (void)playAnimal{
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/Sheep.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = 0;
if (audioPlayer == nil)
NSLog([error description]);
else
[audioPlayer play];
}
I'm very new to Objective-C, so a lot of syntax things are new to me as well as general methods. Thanks for your patience!
Use the following:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Sheep" ofType:#"mp3"]];
NSURL *url = [NSURL fileURLWithPath:path];
When your resources are copied to the bundle, they do not retain their directory structure. Just identify the resource by name and it will find the path for it.
Just as an FYI, the following works, as well:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Sheep.mp3" ofType:#""]];
NSURL *url = [NSURL fileURLWithPath:path];
This may be useful if you have a set of resources logically grouped together in a plist and you are programmatically reading those out. For example:
// reference to a dictionary with the entry 'Sheep.mp3'
NSString *resourceName = [dictionary objectForKey:item1];
NSString *path = [[NSBundle mainBundle] pathForResource:resourceName ofType:#""]];
NSURL *url = [NSURL fileURLWithPath:path];

NSURL, creating pdfs

I'm trying to create some pdfs from pdfs added to my iphone as an exercise for myself in quartz and just getting better with the language. So I have this so far to get the multiple pdfs on my phone:
NSError *error;
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundleRoot error:&error];
NSArray *onlyPDFs = [dirContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self ENDSWITH '.pdf'"]];
How can I convert this to a NSURL object, or an array of NSURL objects? I've tried some different things like URLForResource, initWithString, but I don't think those are correct. Thanks.
You could do something like this to generate an NSURL for each PDF in onlyPDFs:
for (NSString *p in onlyPDFs) {
NSString *name = [p stringByDeletingPathExtension];
NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:#"pdf"];
}

How to save a value in a plist file in iPhone?

I am new to iPhone development. I am using the below code to add the value to the plist but when check the plist after executing the code I don't see any value saved in the plist. Where did I go wrong? The plist I have created is in the resource folder.
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"regvalue.plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:finalPath];
[plistDict setValue:#"hello" forKey:#"choice"];
[plistDict writeToFile:finalPath atomically: YES];
For retrieving the value
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"regvalue.plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:finalPath];
NSString *value;
value = [plistDict objectForKey:#"choice"];
NSLog(#"the value is %#",value);
It gives only null value.
The resources folder is not writeable. You should save it into the documents folder.
Maybe you can find the answer here:
How to write data in plist?
But if you only want save some message in you app, NSUserDefaults is the better way.