views:

156

answers:

4

hi i have a soundboard its just a screen with about 8 buttons. each individual button will have its own sound which will be played upon button press There are a couple of ways i could play the sound, such as using SystemSound or AVAudioPlayer system sound so far seems have the quickest response times, avaudioplayer is quite slow, it cant keep up if the user taps on the buttons really fast, i created an audio player for each sound which was quite messy. this is how im playing the sounds at the moment the .h file

@interface MainScreenViewController : UIViewController <AVAudioPlayerDelegate, UITabBarControllerDelegate> {
 AVAudioPlayer *player;
 CFURLRef  keNURL;
 SystemSoundID    keNObject;
 //KE LOUD
 CFURLRef  keLURL;
 SystemSoundID    keLObject;
 //GE NORMAL
 CFURLRef  geNURL;
 SystemSoundID    geNObject;
 //GE LOUD
 CFURLRef  geLURL;
 SystemSoundID    geLObject;
 //NA NORMAL
 CFURLRef  naNURL;
 SystemSoundID    naNObject;
 //NA LOUD
 CFURLRef  naLURL;
 SystemSoundID    naLObject;
 //RA
 CFURLRef  raURL;
 SystemSoundID    raObject;
 //DAGGA CLICK
 CFURLRef  daCURL;
 SystemSoundID    daCObject;
 //TILLI CLICK
 CFURLRef  tiCURL;
 SystemSoundID    tiCObject;

}
@property (nonatomic, retain) AVAudioPlayer *player;
@property (readwrite)    CFURLRef        keNURL;
@property (readonly)    SystemSoundID    keNObject;
@property (readwrite)    CFURLRef        keLURL;
@property (readonly)    SystemSoundID    keLObject;
@property (readwrite)    CFURLRef        geNURL;
@property (readonly)    SystemSoundID    geNObject;
@property (readwrite)    CFURLRef        geLURL;
@property (readonly)    SystemSoundID    geLObject;
@property (readwrite)    CFURLRef        naNURL;
@property (readonly)    SystemSoundID    naNObject;
@property (readwrite)    CFURLRef        naLURL;
@property (readonly)    SystemSoundID    naLObject;
@property (readwrite)    CFURLRef        raURL;
@property (readonly)    SystemSoundID    raObject;
@property (readwrite)    CFURLRef        daCURL;
@property (readonly)    SystemSoundID    daCObject;
@property (readwrite)    CFURLRef        tiCURL;
@property (readonly)    SystemSoundID    tiCObject;
}

then the actions that play the individual sounds

then the .m file, after importing the .h file and the right frame works and synthesizing all the variables, write the code for the action and this is whats in the individual actions.

-(IBAction)geSound{
 AudioServicesPlaySystemSound (self.geNObject);
}

i just wanted to know if systemsound is the way forward for me to create a soundboard. thanks especially when the user will tap on the board really fast alternating between beats. . if not what is the best way to play the sound which responds really well?

+4  A: 

Speaking from experience, AVAudioPlayer works quite well at playing multiple sounds at the same time or very quickly one after the other. The best way to use it is to just create one method that you feed in an NSString to play some sound with the name held in that NSString... in that way, you will create a new player for each sound file that you play. Be careful about releasing the allocated players though unless you know you are finished with them.

Unless you have very large sound files which might take a short second to buffer (you'll have to figure out for yourself if you can live with any latency or not), I've never had any issues with it being slow. If it's slow, you're probably doing something against Apple's recommendations in regards to decoding certain files (i.e. for multiple sounds at once, Apple recommends the CAF format since it is hardware decoded versus software decoded): http://developer.apple.com/iphone/library/documentation/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html

Update

Here is how I encode my files with a shell script. Put this in a file called batchit.sh in it's own directory. Then place whatever .WAV files you want to encode as a .CAF file in that directory. Open up the Terminal on your Mac, cd to that directory and type sh batchit.sh and let it do it's thing. It will batch convert all the files... Here's the code:

for f in *; do
if  [ "$f" != "batchit.sh" ]
then
    /usr/bin/afconvert -f caff -d ima4 $f 
    echo "$f converted"
fi
done

Here is a sample project... http://www.megaupload.com/?d=5NP6FHR1

Notice I didn't do anything in the audioPlayerDidFinishPlaying method which is a delegate method of AVAudioPlayer. You will need to add code to properly release the players after each is finished playing (hey, I can't do all the work for you :) so that all the memory is allocated correctly. Otherwise you will eventually run out if you indefinitely keep creating players without releasing them. Since it seems like you're having a rough day.. see below for a big hint.

That's all the help I can give though. You gotta learn & earn the rest

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {

    // do something here if you want.. you know like maybe release the old players by uncommenting the line below :)

    //[player release];

}
iWasRobbed
thank you so much for your response.what i did before was create an audio player for each individual osund fileand then typed [sound1 play];upon button clickand when i tapped away on the buttons some sometimes the sounds missed playing and so onand sometimes they did play. they are very short sounds.its like a drum soundboard.anyway so the code you have provided isnt that a bit too much to execute everytime i click on one of the buttons to play the sound?specially when the user will be tapping away on the soundboard?
Pavan
What file format were the files in? Were they a .caf file or a .mp3 or .wav, etc? That makes a big difference as far as being slow to play. If you make them a .caf you shouldn't have any issues and I've had 10+ sounds playing very quickly at the same time or one after the other with no issues. Make sure when you create the sound file that you remove all dead silence at the beginning of the sound file so the actual sound starts right away. Remember also that once you create a single player, that player gets re-used each time the sound is played unless you release it.
iWasRobbed
ok ive converted all sounds to caf files, it reduces the file size from 630 kb to about 12 kb, which is fantastic as i thought this was definitely the cause of my application playing the sounds upon fast button presses with lag. I thought id also switch over to AVAudioPlayer for one of my buttons as a test as playing the caf files with systemsound didnt work.Now when i tap a long on the button the sound still plays with lag,even slower than it did when i was using systemsound.WHATS GOING ON? i really want this to work.
Pavan
Is that on the device or on the simulator? The very first sound always seems to take a while to buffer on the simulator, but it's fine after that. I might just write a quick example for you and post it somewhere, check back later today or tonight
iWasRobbed
no its on the device im talking aboutand yes if you can that will be awesome.Basically this is how ive done it now that ive implemented AVAudioPlayer. I contacted a guy that made a similar application, and he told me he used avaudio player aswell. and when i run his application after downloading it from the appstore it runs sooo smoothly. no delay whatsoever.the application is called "Dhol nut". for free.Anyway ove tried various things like below:
Pavan
Pavan
This is a video of something im trying to dohttp://www.youtube.com/watch?v=1w4b07Tf8TUsee theres no delay, i contacted the person and he didnt tell me much all he told me was that he used AVAudioPlayer.
Pavan
By the way, if you want real complex beats, hit the looped button twice and you'll start another instance of the loop on top of the current one :)
iWasRobbed
Thank you for your upload. It has helped me realise one thing. That there is something wrong with my sounds. i dont know what it is. but when i replace a few of your sounds with mine, just to make a comparison of our sound delay on your app. your sounds play fine but my sounds dont. there is some random delay/lag. I dont understand whats going on.-_-'' im going to shoot my laptop
Pavan
Thank you for your upload. It has helped me realise one thing. That there is something wrong with my sounds. I think its because even though i dont have any silence at the beginning of my sound i do however have silence after my sound that lasts 3 seconds. it might be that.The final thing id like to ask as your application clearly works. Thank you, id like to ask why it is that your sounds stop playing after i tap coninuosly for about a minute or so??is there something wrong with deallocation of memory or what?
Pavan
OMG im going to blow up. Here are the sounds im trying ti play and tell me what you can do. ive tweaked it so that these sounds are very short its the same bit rate as your files AND YET AGAIN IT PLAYS WITH a LAG?! here are the filesDOWNLOAD THESE TWO SOUND FILES AND PLEASE INCORPORATE IT IN YOUR PROJECT and change the soundclip names in your .m file from handclap to loudGe etcand youll see what im talking about
Pavan
can someone please help me im pulling my eyeballs out :(
Pavan
Pavan, See my updated post for how I encode the files into an `IMA4` caf file which is a compressed version. Relax man, this is all part of learning what not to do :)
iWasRobbed
P.S. Silence at the end of your sounds has nothing to do with lag. Unless of course it's on your loops and then yeah, you wanna make sure the loop sounds good (which the one I included doesn't, but it works for this example).
iWasRobbed
P.S.S. Heed my comment in the updated posted about releasing old players, or you'll eventually run out of memory
iWasRobbed
im sorry, i didnt tell you that i have already put in the required[theAudio release]; and theAudio = nil; code.basically in a simplified way thats what ive doneeverytime the delegate method gets called it should execute the code that ive written inside to release the audio players.However to my surprise it still does the same thing. after a while it still runs out of memory.
Pavan
So essentially this is another problem which i will worry about some other time, but if i can get the sounds to play the way your sounds are THEN THAT WOULD BE GREAT. so right now im following your updated post. Much appreciated. thanks for your quick replies it helps to keep me calm! LOL
Pavan
Pavan.. all you need to do is call `[player release];` in that delegate method. Use my sample project, add that piece of code in, and you're set. (Please mark this answer as closed by clicking the check mark which also gives me points for helping) :)
iWasRobbed
Thank you so much! thats what it was. It was the way my sound was converted. ima4 Definitely helped.Its amazing how the sounds are playing properly now.is there anyway id be able to get your contact info? if you could email me that would be great on [email protected] in advance iwasrobbed. And thank you for your patience and your fast replies, and for your updated post.
Pavan
so what was wrong with my audio? as far as i can see they were still .caf....??? and how did you know that THATS what would slve the problem? i just wanna know what your thinking process was.if you could send meyour email contact to me email that would be great on [email protected]
Pavan
Not all caf files are created equal :) I know because I've been in your situation before
iWasRobbed
thanks ive solved the problem now. Ive used OpenAL and that works exactly the way i wanted it to. thanks for all your help with converting the files and so on. i appreciate it very much
Pavan
A: 

you could create AVAudioPlayer for each sound and then just pause/play it.

ive tried that, and it still plays the sound slow. it plays it slower than systemsound now. There is no silence at the beginning of the file.it only a 1 second file.can anyone help me please?
Pavan
A: 

Have you tried playing back each sound in its own thread? You could try a basic NSOperation

Joost Schuur
his problem lies in how he's encoding the sound files. the frameworks are doing what they are supposed to, but he just needs to encode them correctly and it'll work.
iWasRobbed
Thats exactly what it was. Thanks for your updated post, i followed your conversion to ima4 and it worked like a charm.how did you know that it was because of my sounds because theyre still .caf
Pavan
+1  A: 

USE OPEN AL! OMG WOW as soon as i use open al implementing all the methods and instantiating everything. The sound plays sooo fast. what i mean is ABSOLUTELY LOW LATENCY IS WHAT I WAS AFTER AND THATS WHAT I GOT ah wow its working brilliantly I managed to get everything working. Use these tutorials it will help as they have helped me: http://benbritten.com/2008/11/06/openal-sound-on-the-iphone/ and especially the next link im going to post. Thanks to this link i was able t create a soung manager that would be able to play all the sounds i want in any class i am in. http://www.71squared.com/2009/05/iphone-game-programming-tutorial-9-sound-manager/

i suggest everyone to use openAL for low latency on demand sound. specially for games when you need to make sure sound is played there and then when you want it to.

Pavan