1

i'm new in Objective C, i'm developing an app that play sound on touch event of an uibutton. When i touch the button, it change is image and audio starts to playing. When audio is finish to play, i want to put the original image of uibutton. How can i do that? How can i catch the event of the audio that is finish? i'm using that code:

- (SystemSoundID) createSoundID: (NSString*)name
{
    NSString *path = [NSString stringWithFormat: @"%@/%@",
    [[NSBundle mainBundle] resourcePath], name];              
    NSURL* filePath = [NSURL fileURLWithPath: path isDirectory: NO];
    SystemSoundID soundID;
    AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
    return soundID;
} 

In

viewDidLoad

i call

freq = [self createSoundID: @"freq.wav"];

and in function that is called on button's touch i use:

AudioServicesPlaySystemSound(freq);

How can i do? Thank you!

Jayyrus
  • 12,961
  • 41
  • 132
  • 214

2 Answers2

2

Not sure if it's possible with the AudioService API but you can use AVAudioPlayer instead and assign a delegate that implements the AVAudioPlayerDelegate protocol and does something when audioPlayerDidFinishPlaying:successfully: is called.

Remember to add the AVFoundation framework.

Example:

In your interface definition:

#import <AVFoundation/AVFoundation.h>

...

@inteface SomeViewController : UIViewController <AVAudioPlayerDelegate>

...

@propety(nonatomic, retain) AVAudioPlayer *player;

In your implementation:

@synthesize player;

...

// in some viewDidLoad or init method
self.player = [[[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:NULL] autorelease];
self.player.delegate = self;

...

- (void)pressButton:(id)sender {
  // set play image
  [self.player stop];
  self.player.currentTime = 0;
  [self.player play];
}

...

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
   // set finish image
}

...

# in some dealloc or viewDidUnload method
self.player = nil;
Mattias Wadman
  • 11,172
  • 2
  • 42
  • 57
  • There is a problem, when i touch button, it waits a second or two to play and change image :/ – Jayyrus Sep 28 '11 at 14:14
  • Do you create the `AVAudioPlayer` each time you play the sound? you can also try to call `prepareToPlay` after create to preload the sound data. You should probably try to reuse the same `AVAudioPlayer` instance each time. – Mattias Wadman Sep 28 '11 at 14:28
  • You added `[self.player prepareToPlay];` after `AVAudioPlayer` alloc/init? didn't make any difference? – Mattias Wadman Sep 28 '11 at 16:12
  • Weird as `AVAudioPlayer` should play asynchronously. Maybe add some logging with time and see what method call that takes time? – Mattias Wadman Sep 28 '11 at 16:16
  • Is this in the simulator or on a real device? i know that `AVAudioPlayer` is quite slow in the simulator some times. – Mattias Wadman Sep 28 '11 at 16:17
  • Sorry, i was saying of your back post, not this! :) it works very good! :) but now i have another problem, sorry: my button is a white square with a figure inside. when i click the background of button change the color in gray in the millisec it change image, what can i do to resolve it? :) thanks you very much! – Jayyrus Sep 28 '11 at 16:26
  • You should probably open another question about that. Can't really understand the question, you don't want the button to grey for a little while or the image changes to slow? – Mattias Wadman Sep 28 '11 at 16:41
  • scuse me, but my only good program language is java, i'm new in objective c. so i make another question for the button's color. My problem still is that image changes slowly only on the first touch, in the others work more fast.. – Jayyrus Sep 28 '11 at 16:49
  • Ok good. Maybe the problem with the image is that you don't preload the image? it could probably take some time the first time for `[UIImage imageNamed:...]` to load the image, on the second call the image is probably cached. So call `[UIImage imageNamed:...]` in some init or load method and keep a reference to it. – Mattias Wadman Sep 28 '11 at 16:56
  • done! So.. i load image in viewDidLoad : - (void)viewDidLoad { [super viewDidLoad]; imageOpen = [UIImage imageNamed:@"aperto.jpg"]; imageClosed = [UIImage imageNamed:@"chiuso.jpg"]; but my problem still exists.. when button is clicked it runs : - (IBAction)launchDialog { [bottone setImage:imageClosed forState: UIControlStateNormal]; if(self.player.playing==TRUE){ [self.player stop]; } self.player.currentTime = 0; [self.player play]; } – Jayyrus Sep 28 '11 at 17:16
  • So the problem is that after you click the button and launchDialog is called it takes some time until the button is changed to the imageClosed image? – Mattias Wadman Sep 28 '11 at 18:22
  • sorry, i forgot to tell you before, that i ask another question about the other problem, the color of image background.. Using this: [bottone setImage: imageOpen forState: UIControlStateNormal]; [bottone setImage: imageOpen forState: UIControlStateHighlighted]; [bottone setImage: imageOpen forState: UIControlStateDisabled]; [bottone setImage: imageOpen forState: UIControlStateSelected]; All the problem are solved! :) sorry and still thanks you :) – Jayyrus Sep 28 '11 at 18:35
0

It is possible with the AudioService API, you want to use AudioServicesAddSystemSoundCompletion.

Tim Kokesh
  • 879
  • 7
  • 10