1 button, plays 10 sounds?
How can I get a button to play some sounds in on order?
How can I add an extra sound to this action?
-(IBAction)sound1
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"sound1", CFSTR("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
I've had the best luck with AVAudioPlayer - it's a library called AVFoundation you can import through "Build Phases" (first click on the blue xcode project name at top left) and then "Link Binary with Libraries"
Then try this really simple YouTube tutorial to make a button play sound:
http://youtu.be/kCpw6iP90cY
That's the same video I used 2 years ago to create my first sound board. Xcode 5 is a little different but the code will all work.
Ok now you need to create an array of these sounds that will cycle through them. Check out this link from TreeHouse:
https://teamtreehouse.com/forum/creating-an-array-with-mp3-sound-files
If the sounds are name sound0 … soundN, you can just introduce to ivars — one tracks the current index, one defines the number of sounds.
#implementation MyClass {
NSUInteger soundIdx;
NSUInteger soundCount;
}
-(instancetype) init //or any other entry point method like viewDidLoad,....
{
self = [super init];
if (self) {
soundCount = 10;
}
return self;
}
-(IBAction)sound
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) [NSString stringWithFormat:#"sound%lu", soundIdx], CFSTR("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
soundIdx = (++soundIdx) % soundCount;
}
#end
If the sound names do not follow any particular naming convention, you could put them in an array
#implementation MyClass {
NSUInteger soundIdx;
NSArray *soundNames;
}
-(instancetype) init //or any other entry point method like viewDidLoad,....
{
self = [super init];
if (self) {
soundNames = #[#"sound1",#"hello", #"ping"];
}
return self;
}
-(IBAction)sound
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) soundNames[soundIdx], CFSTR("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
soundIdx = (++soundIdx) % [soundNames count];
}
#end
Related
I am trying to play two different files in a queue. One is an intro track and another is a main track.
My Method to setup music playback
-(void)musicPlayBack:(CFStringRef )soundName{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle
, (CFStringRef) soundName, CFSTR ("mp3"), NULL);
SystemSoundID soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, FinishedSoundPlayback, NULL);
AudioServicesPlaySystemSound(soundID);
}
-(void)playIntro:(NSString *)introTrackName{
NSArray *introTracks = [NSArray arrayWithObjects:#"heybaby",#"dumbson",#"heybadass",
#"heydarling",#"heyhoney",#"madam",#"sir", nil];
[self musicPlayBack:(__bridge CFStringRef)([introTracks objectAtIndex:2])];
}
-(void)playNotification:(NSString *)notificationTrackName{
[self musicPlayBack:(__bridge CFStringRef)(notificationTrackName)];
}
-(void)notifyWithSound:(int)batteryCase{
NSArray *mainSoundTracks = [NSArray arrayWithObjects:#"ten",#"twenty",#"twentyfive",#"thirty",
#"fourty",#"fifty",#"sixty",#"seventy",#"seventyfive",
#"eigthy",#"ninty",#"hundred",nil];
[self playIntro:#"someRandomIntro"];
while (introFinished==NO) {
if (introFinished==YES) {
break;
}
}
[self playNotification:[mainSoundTracks objectAtIndex:batteryCase]];
}
This is what i have before #implementation
BOOL introFinished = NO;
static void FinishedSoundPlayback(SystemSoundID mySSID, void* data){
introFinished = YES;
AudioServicesRemoveSystemSoundCompletion (mySSID);
NSLog(#"completion Callback");
}
The problem is FinishedSoundPlayback never gets called.
You registered the system sound under the name "soundId" and you expect callback for "mySSID". This suppose to be the same name. BTW I do not recommend this API for playing music because of its limitation.
I want to play a system sound but I don't hear anything:
- (void) play_system_sound
{
NSLog(#"Play system sound");
SystemSoundID soundID;
NSString *path = [[NSBundle bundleWithIdentifier:#"com.apple.UIKit"] pathForResource:#"Tock" ofType:#"aiff"];
NSLog(#"path = %#", path );
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundID);
AudioServicesPlaySystemSound(soundID);
AudioServicesDisposeSystemSoundID(soundID);
NSLog(#"Play system sound DONE");
}
I don't hear anything. What am I doing wrong?
After AudioServicesPlaySystemSound(soundID) ,don't call AudioServicesDisposeSystemSoundID(soundID) immediately.
Try this :
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle bundleWithIdentifier:#"com.apple.UIKit"] pathForResource:#"Tock" ofType:#"aiff"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundID);
}
-(void)dealloc
{
AudioServicesDisposeSystemSoundID(soundID);
}
- (void)play_system_sound
{
AudioServicesPlaySystemSound(soundID);
}
I don't know if you have solved the problem, but for me, on iOS 7, sometimes the (__bridge CFURLRef) casting won't work, in which case, if you print out the result of (__bridge CFURLRef)[NSURL fileURLWithPath:path], it will be 0x0. This leads to failure of AudioServicesCreateSystemSoundID(). The return value of the function is type of OSStatus. If it fails, the function will return -50, which means one or more parameters are invalid. (If it executes successfully, it returns 0.)
I solved this by using the C style function getting the path of the file:
CFBundleRef mainBundle = CFBundleGetMainBundle ();
CFURLRef soundFileUrl;
soundFileUrl = CFBundleCopyResourceURL(mainBundle, CFSTR("fileName"), CFSTR("wav"), NULL);
AudioServicesCreateSystemSoundID(soundFileUrl, &soundID);
I uploaded a file audio.wav into my supporting files folder.
This is my PlayAudio.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#interface PlayAudio : UIViewController {
}
-(IBAction) PlayIt;
#end
This is my PlayAudio.m after the implementation command
- (IBAction) PlayIt; {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"audio", CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
I then ctrl-clicked from the play button to the First Responder in my view controller and selected PlayIt. I see it's associated with Touch Up Inside.
For some reason I can click the button, but nothing plays. I'm doing this in Storyboard.
You can use NSURL to get the path of your wav file and cast it to CFURLRef, check the following code:
SystemSoundID soundID;
NSURL *soundPath = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"audio" ofType:#"wav"]];
if (AudioServicesCreateSystemSoundID ((CFURLRef)soundPath, &soundID) != kAudioServicesNoError) {
AudioServicesPlayAlertSound(soundID);
}
Note, that if mute button on iphone is enable AudioServicesCreateSystemSoundID function will fail(Vibration can be used in this case:soundID = kSystemSoundID_Vibrate;). If you want to play sound disregarding the mute switch, use AVAudioPlayer api.
I have an app that currently plays a 5 sec sound when a button is pressed within a view controller. I am trying to change this set up to where if I have a tableview, a specific cell is touched and the sound plays. I do not want an action where you select the cell and it pushes to another window to play the sound. I simply want the sound to play on touch of the cell.
Currently for my button set up I had the following to play the sound in my view controller:
In the SoundLibViewController.h
// Identifying UIButton associated with sound file
-(IBAction)CarHorn:(id)sender;
#end
In the SoundLibViewController.m
-(IBAction)CarHorn:(id)sender {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"CarHorn", CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
Unfortunately I can not find any help online to point me in the direction to change my code into incorporate a tableviewcell.
To give an example of what I'm looking to do: You go into your iPhone/iPad and under settings you select "Sounds". Then you choose "Ringtone", which takes you to a list of sounds. If you press the cell related to the sound it plays. THAT is what I want to do.
You need something like this in your UITableViewDelegate
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * soundName = [self.soundNames objectAtIndex: indexPath.row]; // Assuming you have an array of sound names
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef)soundName, CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
I don't have the "[sender resignFirstResponder]" method called, but my keyboard still closes when the done button is pressed. I need it to stay open, even when I click done. How can I go about doing this?
Here's my action that controls the keyboard:
- (IBAction)returnKeyButton:(id)sender {
BOOL guessCorrect = [gameModel checkGuess:guessTextField.text];
guessTextField.text = #"";
if (guessCorrect) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"rightAnswer", CFSTR ("mp3"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
if (gameModel.score == 10) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"win", CFSTR ("mp3"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
[self endGameWithMessage:#"You win!"];
} else {
scrambledWord.text = [gameModel getScrambledWord];
}
}
remainingTime.text = [NSString stringWithFormat:#"%i", gameModel.time];
playerScore.text = [NSString stringWithFormat:#"%i", gameModel.score];
}
First of... to be honest, I have never had the problem you have. I always had to use the resign call to close the keyboard or it would stay open... But, this is what I used for you:
1) Put this in the .h file:
-(IBAction) textFieldDoneEditing : (id) sender;
2) Put this in the .m file:
-(IBAction) textFieldDoneEditing : (id) sender{
[sender resignFirstResponder];
[sender becomeFirstResponder];
}
3) Right click the UITextField in the storyboard and set the Sent Event "Editing Did End" to the textFieldDoneEditing method in the view controller.
Now, whenever the user presses "Return" or "Done", the keyboard will open and close instantaneously. Hope it helps! :)
If it doesn't work, look at my Xcode Project (which does work)... download it here