Is there a way to programmatically invoke the keypad "click" sound? My app has a custom keypad (built out of UIButtons) and I'd like to provide some audio feedback when the user taps on the keys. I tried creating my own sounds in Garageband, but wasn't happy with any of my creations. If there isn't a standard way to invoke the key click, can anyone point me to a library of sounds that might have such a gem?
The simplest way I've found is to extract Tock.aiff (the keyboard sound) from the iPhone Simulator and package it with your app, then play it using AudioServicesPlaySystemSound()
at the appropriate time. On my machine, simply typing Tock.aiff into Spotlight turns up the file, but if you have to go looking for it, it's in the simulator version of UIKit.framework.
From what I can tell, the click sound isn't available to apps. I haven't seen anything in audio session services that is relevant. AudioServicesPlaySystemSound()
looks promising, but there doesn't appear to be any system sound ID for the click sound (a closer look at the headers may turn up something). You could always loop over a call to AudioServicesPlaySystemSound(i)
and see if anything plays. The iPhone software restore images probably have the sound, but it's probably not licensed for general use. Jailbreaking an iPhone to get at the tasty click sound doesn't need to be mentioned.
For (creative commons) sounds, check out the Freesound Project.
For the future, perhaps request that Apple expose system sounds other than the alert sound for use with AudioServicesPlaySystemSound()
.
No need to copy the file into your own app - you should be able to get it directly from the UIKit framework:
CFURLRef soundFileURLRef = CFBundleCopyResourceURL(
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.UIKit")),
CFSTR ("Tock"),CFSTR ("aiff"),NULL);
This is what I made out of it aSquared's comment:
NSString *path = [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] pathForResource:@"Tock" ofType:@"aiff"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
AudioServicesPlaySystemSound(soundID);
AudioServicesDisposeSystemSoundID(soundID);
Using 0x450 as the SystemSoundID works for me (and at the correct volume - just playing the built-in Tock.aiff was too loud). No idea how portable that is - this is on an iPod Touch 3rd gen.
Still doesn't respect the preference for tick on/off.
Maybe a bit late ...
But in MrMage last post, if you do AudioServicesDisposeSystemSoundID(soundID);
straight after AudioServicesPlaySystemSound(soundID);
then you won't hear a thing as you're discarding the system sound right after creating it.
You have to let it finish playing first.. Only call AudioServicesDisposeSystemSoundID to cancel the sound before it finishes
AudioServicesPlaySystemSound(soundID);
AudioServicesDisposeSystemSoundID(soundID);
then you won't hear a thing as you're discarding
the system sound right after creating it.
You have to let it finish playing first..
Only call AudioServicesDisposeSystemSoundID to cancel the sound before it finishes
But HOW would you: play the sound now... let it fully finish... then correctly dispose of it?
(Don't you just love it when someone says: You've done it all wrong... you have to do it this other way... but I'm not going to tell you HOW to do it correctly.)
You do not have to dispose of the sound object right away. Keep a pointer to that sound object in a property, and dispose of it only when you are about to play another sound before re-creating it.
And of course finally dispose of the SystemSoundID object in dealloc.