How to put sounds in an array? - iphone

I have 10 sounds, and it would be easier for me to put them into an array. However I'm new to Obj C.
Here is the code so far, this is just for 1 sound. I could copy and paste it 10 times. But if all 10 sounds are in an array I'll be able to do more functions with the sounds.
- (IBAction)oneSound:(id)sender; {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Vocal 1" ofType:#"mp3"];
if (oneAudio) [oneAudio release];
NSError *error = nil;
oneAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
if (error)
NSLog(#"%#",[error localizedDescription]);
oneAudio.delegate = self;
[oneAudio play];
}
thanks

Heres one way,
NSMutableArray *soundArray = [NSMutableArray arrayWithCapacity:10];
[soundArray addObject:oneAudio];
.
.
.
[soundArray addObject:tenAudio];
or you could also put the paths to the audio content into the Array and instantiate them when required.

Take the file paths of the arrays, make them into strings, add THOSE to the array, and access them only when needed, or else you'll be using up a lot of memory.

Related

How to play audio songs one after other which is placed in resources folder in iphone

I am new to iphone.I am working on audio player here i am struck in the middle because i am facing some issue that is here in my project i have 2 directories in resource folder.In each directory i have 6mp3 audio files.So my issue is when user gives the path to the 3rd mp3 song in first directory in resources folder from that we have to play continuous all the songs like 4th,5th,6th mp3files also which is placed in that directory in resources folder.here is my code for this
NSString *chapterString =#"3";
NSString *string = [[NSBundle mainBundle]pathForResource:chapterString ofType:#"mp3" inDirectory:#"raj"];
NSLog(#"string is %#",string);
url = [NSURL fileURLWithPath:string isDirectory:YES];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
If any body know this please help me..
Put all the songs in an array
Initialize a global variable suppose x
Write the following AVAudioPlayer Delegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
if (x<([_downloadedSongArray count]-1))
{
x=x+1;
[self loadSong];
}
}
- (void)loadSong
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
_audioDocumentsDirectory = [paths objectAtIndex:0];
_audioDocumentsDirectory = [_audioDocumentsDirectory stringByAppendingPathComponent:#"Songs"];
NSString *selectedSong = [_downloadedSongArray objectAtIndex:x];
_sharerDownloadedString=selectedSong;
selectedSong = [selectedSong stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
_audioDocumentsDirectory = [_audioDocumentsDirectory stringByAppendingPathComponent:selectedSong];
url = [NSURL fileURLWithPath:_audioDocumentsDirectory];
[_audio stop];
_audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[_audio prepareToPlay];
[_audio play];
[Utility setPlaying:YES];
[_audio setDelegate:self];
}
Where _downloadedSongArray is an array where all song are. And loadSong is a method which load next/prev song from an array based on index and assign to the AVAudioPlayer.
You could get the contents of the directories into an Array via NSFileManager, upon finishing song x..play the next song in the array, song y.

MASSIVE AVAudioPlayer Memory Leaks

I am using AVAudioPLayer to do the audio for my game. I have the following code in a method in a seperate class, which is called every time I want the 'boing' sound to play. Problem is, it leaks huge amounts of memory, to the point where the game becomes unplayable. Now i'm not releasing any of the pointers in the method, because at the time I only had one. But now I have 10 of these methods.
What is the best way to release the pointers in tis case? (Yes, I have tried releasing straight after [boing play];, this solves the leak (obviously) but the sound dosen't play so theres no point.
-(void)playBoing {
int x = (arc4random()%3)+1;
NSString *path = [NSString stringWithFormat:#"/boing_0%i.aif", x];
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
resourcePath = [resourcePath stringByAppendingString:path];
AVAudioPlayer *boing = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:nil];
boing.delegate = self;
boing.volume = 1;
[boing play];
}
It's possible there's a better solution, but I've had similar problems where releasing right away killed my process. This is the solution I took. Again, there may be better out there, but for a quick fix, it should do the trick.
In your header file, create the following:
AVAudioPlayer *boing;
Then in -(void)playBoing, do as you did, but change
AVAudioPlayer *boing = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:nil];
to
if (boing != nil) {
boing = nil;
[boing release];
}
boing = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:nil];
This should ensure that there's only one instance of boing allocated at a time

I need to create an audio player with 4-5 melodies

I am new in Iphone SDK programming
I need to create audio player but without array. Melodies have names "sound1, sound2, sound3..."
My code here:
NSUInteger x;
for (x=1; x<=tuneNums; x++)
{
path = [[NSBundle mainBundle] pathForResource:#"sound%d" ofType:#"wav"];
if([[NSFileManager defaultManager] fileExistsAtPath:path])
{
aSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
[aSound setNumberOfLoops:0];
aSound.delegate = self;
[aSound prepareToPlay];
}
}
All button I have and work great, but only with one mellody:( But how release 4-5 melodies i dont know :(
P.S. Forgive me for my english I'm just out of Siberia
You are allocating an AVAudioPlayer on each cycle, and you get only one 'melody' because that's the one allocated in the last cycle.
As 7KV7 pointed out, you should allocate one AVAudioPlayer when the user presses a button, play the corresponding audio file, and then release/recreate it when another button is pressed.
Something like:
- (void)button1Pressed:(id)sender {
// release the current player
if(aSound) {
[aSound release], aSound = nil;
}
// create a new player with the first file
aSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
[aSound setNumberOfLoops:0];
aSound.delegate = self;
[aSound prepareToPlay];
}
How to determine which audio file to play when a button is pressed is up to you. If you are going to have only four audio files, the simplest way is to have a fixed number of buttonPressed selectors (e.g. button1Pressed, button2Pressed) and associate them to your four buttons.
if i got you right you should add the method-
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
[player release];
}
and don't forget to set your view controller as the player delegate.
aSound.delegate=self;

Whats the simplest way to play a looping sound?

What is the simplest way to play a looping sound in an iPhone app?
Probably the easiest solution would be to use an AVAudioPlayer with the numberOfLoops: set to a negative integer.
// *** In your interface... ***
#import <AVFoundation/AVFoundation.h>
...
AVAudioPlayer *testAudioPlayer;
// *** Implementation... ***
// Load the audio data
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"sample_name" ofType:#"wav"];
NSData *sampleData = [[NSData alloc] initWithContentsOfFile:soundFilePath];
NSError *audioError = nil;
// Set up the audio player
testAudioPlayer = [[AVAudioPlayer alloc] initWithData:sampleData error:&audioError];
[sampleData release];
if(audioError != nil) {
NSLog(#"An audio error occurred: \"%#\"", audioError);
}
else {
[testAudioPlayer setNumberOfLoops: -1];
[testAudioPlayer play];
}
// *** In your dealloc... ***
[testAudioPlayer release];
You should also remember to set the appropriate audio category. (See the AVAudioSession setCategory:error: method.)
Finally, you'll need to add the AVFoundation library to your project. To do this, alt click on your project's target in the Groups & Files column in Xcode, and select "Get Info". Then select the General tab, click the + in the bottom "Linked Libraries" pane and select "AVFoundation.framework".
The easiest way would be to use an AVAudioPlayer set to an infinite number of loops (or finite if that's what you need).
Something like:
NSString *path = [[NSBundle mainBundle] pathForResource:#"yourAudioFileName" ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *_player = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
[file release];
_player.numberOfLoops = -1;
[_player prepareToPlay];
[_player play];
This will simply loop whatever audio file you have specified indefinitely.
Set the number of loops to any positive integer if you have a finite number of times you want the audio file to loop.
Hope this helps.
Cheers.

AVAudioPlayer only initializes with some files

I'm having trouble playing some files with AVAudioPlayer. When I try to play a certain m4a, it works fine. It also works with an mp3 that I try. However it fails on one particular mp3 every time (15 Step, by Radiohead), regardless of the order in which I try to play them. The audio just does not play, though the view loading and everything that happens concurrently happens correctly. The code is below. I get the "Player loaded." log output on the other two songs, but not on 15 Step. I know the file path is correct (I have it log outputted earlier in the app, and it is correct). Any ideas?
NSData *musicData = [NSData dataWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[song filename] ofType:nil]]];
NSLog([[NSBundle mainBundle] pathForResource:[song filename] ofType:nil]);
if(musicData)
{
NSLog(#"File found.");
}
self.songView.player = [[AVAudioPlayer alloc] initWithData:musicData error:nil];
if(self.songView.player)
{
NSLog(#"Player loaded.");
}
[self.songView.player play];
NSLog(#"You should be hearing something now.");
Sorry for entering the party so late. Just want to post a tip so that It will be useful for any person referring this in the future.
A small correction to shaggy frog's answer. The correct usage would be:
NSError *anError = nil;
anAVAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:someURL] error:&anError];
if (!anAVAudioPlayer) {
NSLog(#"localizedDescription : %#", [anError localizedDescription]);
}
NSData *musicData = [NSData dataWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[song filename] ofType:nil]]];
Here, is musicData nil for the problem case?
Also:
self.songView.player = [[AVAudioPlayer alloc] initWithData:musicData error:nil];
You shouldn't pass nil for methods that take an NSError object. Likely it will shed more light on your problem if you use it correctly:
NSError* error = nil;
self.songView.player = [[AVAudioPlayer alloc] initWithData:musicData error:&error];
if (error)
{
NSLog(#"Error with initWithData: %#", [error localizedDescription]);
}