Stopping sound in Xcode - objective-c

Hi all,
Please look at the code below, i want to be able to stop the sound when the same button is clicked, another button is clicked and even when going back to the home screen. Not sure what to do here,
FoxViewController.m
#import "FoxViewController.h"
#import <AVFoundation/AVAudioPlayer.h>
AVAudioPlayer *newPlayer_Fox;
#interface FoxViewController ()
#end
#implementation FoxViewController
-(IBAction) Fox;
{
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: #"new"ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
[newPlayer play];
}
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
FoxViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
AVAudioPlayer *newPlayer;
#interface FoxViewController : UIViewController
-(IBAction)Fox;
#end
Your help is much appreciated, Justin.

Maintain one flag say BOOL soundPlay as global variable in FoxViewController.h file
Now in FoxViewController.m's viewDidLoad method
soundPlay = TRUE;
Action button will be like this:
-(IBAction) Fox;
{
if(soundPlay){
soundPlay = FALSE; //made false for next time another condition will be used.
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: #"new"ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
[newPlayer play];
}
else
{
if([newPlayer isPlaying])
{
[newPlayer stop];
}
}
}
For stopping sound in background add this method if not added
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//stop background sound
if([newPlayer isPlaying])
{
[newPlayer stop];
}
}

Summarizing, the sentence to STOP the sound file is:
AudioServicesDisposeSystemSoundID (soundFileObject);
Explanation (Important to understand):
I have a table view with 18 different sound files. When user select a row must sound the corresponding file and when select another row, it must STOP the previous sound and play other.
All this stuff it is necessary:
1) Add to your project "AudioToolbox.framework" inside "Build Phases", inside "Link Binary With Libraries"
2) In header file (in my project it calls "GenericTableView.h") add these sentences:
#include <AudioToolbox/AudioToolbox.h>
CFURLRef soundFileURLRef;
SystemSoundID soundFileObject;
#property (readwrite) CFURLRef soundFileURLRef;
#property (readonly) SystemSoundID soundFileObject;
3) In implement file (in my project it calls "GenericTableView.m") add these sentences:
#synthesize soundFileURLRef;
#synthesize soundFileObject;
And inside your "Action" implementation or in my case, in:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
//
// That is the question: a way to STOP sound file
//
// -----------------------------------------------------------------------
// Very important to STOP the sound file
AudioServicesDisposeSystemSoundID (soundFileObject);
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// In my project "rowText" is a field that save the name of the
// corresponding sound (depending on row selected)
// It can be a string, #"Alarm Clock Bell" in example
// Create the URL for the source audio file.
// URLForResource:withExtension: method is new in iOS 4.0.
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:rowText withExtension:#"caf"];
// Store the URL as a CFURLRef instance
self.soundFileURLRef = (CFURLRef) [soundURL retain];
// Create a system sound object representing the sound file.
AudioServicesCreateSystemSoundID (soundFileURLRef,&soundFileObject);
AudioServicesPlaySystemSound (soundFileObject);
[soundURL release];
}
4) Finally, in the same implement file (in my project it calls "GenericTableView.m"):
- (void)dealloc {
[super dealloc];
AudioServicesDisposeSystemSoundID (soundFileObject);
//CFRelease (soundFileURLRef);
}
I must to comment "CFRelease (soundFileURLRef)" because the App ends unexpectedly when user leaves the table view.
All this code is proportioned by Apple. In this link you can find even a sample code to test directly in your iPhone simulator.
https://developer.apple.com/library/ios/samplecode/SysSound/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008018-Intro-DontLinkElementID_2

Related

Impossible to play a video with AVPlayer

I've been through all the posts in StackOverflow but I can't get a full example of how to get a video from the bundle and reproduce it in a controller.
I've tried many things but my screen appeared blank or black.
In the last amend, my video remains like this:
no error is thrown on the log. This is my code:
.h (please ignore the name of the controller, it will be finally a camera)
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <AVKit/AVKit.h>
#interface NativeCameraViewController : UIViewController
#end
.m
#import "NativeCameraViewController.h"
#interface NativeCameraViewController ()
#property (nonatomic, retain) AVPlayerViewController *avPlayerViewcontroller;
#end
#implementation NativeCameraViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view = self.view;
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"video" ofType:#"mov"];
NSURL *fileURL = [NSURL fileURLWithPath:stringPath];
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.player = [AVPlayer playerWithURL:fileURL];
self.avPlayerViewcontroller = playerViewController;
[self resizePlayerToViewSize];
[view addSubview:playerViewController.view];
view.autoresizesSubviews = TRUE;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) resizePlayerToViewSize
{
CGRect frame = self.view.frame;
NSLog(#"frame size %d, %d", (int)frame.size.width, (int)frame.size.height);
self.avPlayerViewcontroller.view.frame = frame;
}
#end
and that's what I've got so far.
My video is correctly on the Bundle, called video.mov:
I've tried both linking and copying. Same result.
What am I doing wrong??
Thank you very much in advance.
I'd like to avoid using MPMoviePlayerController since it's deprecated in iOS9
It was actually my fault...
I was trying to reproduce an alias.
When you have 20.000 videos and 30.000 resources this things happen.
Instead of using AVPlayer, use MPMoviePlayerController class:
NSString *path = [[NSBundle mainBundle] pathForResource:#"video" ofType:#"mov"];
NSURL *url = [NSURL fileURLWithPath:path];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:url];
[player play];

AVAudioPlayer iOS no sound

Seems to be similar questions asked but none of the solutions seem to work for me. Cant for the life of me understand why my code doesnt work so here it is.
I dont get any errors but also get no sound.
#interface MainApp ()
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
-(void)playSoundFX:(NSString*) soundFile;
#end
#implementation MainApp
- (void)viewDidLoad {
[super viewDidLoad];
// Play sound
[self playSoundFX:#“sound.mp3"];
}
// Play sound
- (void)playSoundFX:(NSString*)soundFile {
// Setting up path to file url
NSBundle* bundle = [NSBundle mainBundle];
NSString* bundleDirectory = (NSString*)[bundle bundlePath];
NSURL *url = [NSURL fileURLWithPath:[bundleDirectory stringByAppendingPathComponent:soundFile]];
// Make an audioPlayer object and play file
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[audioPlayer setVolume:100.0f];
if (audioPlayer == nil)
NSLog(#"%#", [error description]);
else
[audioPlayer play];
}
#end
*********vvvvvvvvv Amended Code that works vvvvvvvvv**********
#interface MainApp ()
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
-(void)playSoundFX:(NSString*) soundFile;
#end
#implementation MainApp
- (void)viewDidLoad {
[super viewDidLoad];
// Play sound
[self playSoundFX:#“sound.mp3"];
}
// Play sound
- (void)playSoundFX:(NSString*)soundFile {
// Setting up path to file url
NSBundle* bundle = [NSBundle mainBundle];
NSString* bundleDirectory = (NSString*)[bundle bundlePath];
NSURL *url = [NSURL fileURLWithPath:[bundleDirectory stringByAppendingPathComponent:soundFile]];
// Make an audioPlayer object and play file
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[self.audioPlayer setVolume:100.0f];
if (self.audioPlayer == nil)
NSLog(#"%#", [error description]);
else
[self.audioPlayer play];
}
#end
I am execute your code on my iPhone. It is work properly.Please Select a device and run your code. I hope it will execute properly with sound.
You got to segregate the functionalities..
Loading audio file in viewDidLoad and play it on play action, some thing like this
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#interface ViewController ()
{
AVAudioPlayer *_audioPlayer;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Construct URL to sound file
NSString *path = [NSString stringWithFormat:#"%#/sound.mp3", [[NSBundle mainBundle] resourcePath]];
NSURL *soundUrl = [NSURL fileURLWithPath:path];
// Create audio player object and initialize with URL to sound
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)playSoundTapped:(id)sender
{
// When button is tapped, play sound
[_audioPlayer play];
}

How do I stop the background music in another view in Xcode?

So I have a background music playing in one view, then I press the button and go to another view, the background music in another view run as well.
Then I have two background music playing. I want to stop music from the previous view.
So here is the .h code for the first view:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController<AVAudioPlayerDelegate>{
AVAudioPlayer *startingMusic;
}
-(IBAction)StartGame:(id)sender;
So here is the .m code for the first view:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)StartGame:(id)sender{
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *music = [[NSBundle mainBundle] pathForResource:#"Morning_Walk" ofType:#"mp3"];
startingMusic=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
startingMusic.delegate=self;
startingMusic.numberOfLoops=-1;
[startingMusic play];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
here is the .h code for the second view:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface StageOne : UIViewController<AVAudioPlayerDelegate>
AVAudioPlayer *gameMusic;
}
here is the .m code for the second view:
#import "StageOne.h"
#interface StageOne ()
#end
#implementation StageOne
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *music = [[NSBundle mainBundle] pathForResource:#"Green_Hills" ofType:#"mp3"];
gameMusic=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
gameMusic.delegate=self;
gameMusic.numberOfLoops=-1;
[gameMusic play];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Thanks You so much!
This is normal behavior, as your first controller are still loaded
Try this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear: animated];
NSString *music = [[NSBundle mainBundle] pathForResource:#"Green_Hills" ofType:#"mp3"];
gameMusic=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
gameMusic.delegate=self;
gameMusic.numberOfLoops=-1;
[gameMusic play];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear: animated];
gameMusic.delegate = nil;
[gameMusic stop];
gameMusic = nil;
}

Identical Functions, both get executed, no Sound in one

I'v googled the problem but couldn't find a similar case.
I've used this tutorial to play the testSound.mp3 - File when hitting a button on the iPad-Simulator:
http://mobileorchard.com/easy-audio-playback-with-avaudioplayer/
It works that way (it plays the sound), if the playSound-Method is in my ViewController.m, but not in my Sound.m (which has a identical method).
The Code gets executed (NSLog says: "Sound.m playSound executed"), but there is no sound at all.
I'd really appreciate some help here, guess I'm totally stuck... :(
Best regards,
- Teapot
// ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import "Sound.h"
#interface ViewController : UIViewController {
AVAudioPlayer *audioPlayer;
}
- (IBAction)pressButton:(id)sender;
- (void)playSound: (NSString*) soundFile volume : (NSInteger) volume repeats : (NSInteger) repeats;
#end
// ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading thea view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)pressButton:(id)sender {
NSLog (#"Method: pressButton");
[self playSound: #"testSound.mp3" volume: 2 repeats: 2 url : url]; //It works!
Sound *tempSound = [[Sound alloc] init];
[tempSound playSound: #"testSound.mp3" volume: 2 repeats: 2]; // Doesn't work. -> Says "Sound.m playSound executed", but there is no Sound.
}
- (void)playSound: (NSString*) soundFile volume : (NSInteger) volume repeats : (NSInteger) repeats {
NSLog(#"ViewControler playSound");
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = -1;
if (audioPlayer == nil){
NSLog([error description]);
NSLog(#"ViewController.m playSound NOT executed");
}
else{
[audioPlayer play];
NSLog(#"ViewController.m playSound executed");
}
}
#end
// Sound.h
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#interface Sound : NSObject {
AVAudioPlayer *audioPlayer;
}
- (void) playSound: (NSString*) soundFile volume : (NSInteger) volume repeats : (NSInteger) repeats;
#end
// Sound.m
#import "Sound.h"
#implementation Sound
- (void)playSound: (NSString*) soundFile volume : (NSInteger) volume repeats : (NSInteger) repeats {
NSLog(#"Sound playSound");
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = -1;
if (audioPlayer == nil){
NSLog([error description]);
NSLog(#"Sound.m playSound NOT executed");
}
else{
[audioPlayer play];
NSLog(#"Sound.m playSound executed");
}
}
#end
There are some inconsistencies in your code: playSound: has an NSString parameter, but AVAudioPlayer inside that method uses a NSURL. Then you set numberOfLoops = -1 (which means infinite repetition) instead of numberOfLoops = repeat.
But the main problem is that here (assuming that you compile with "Automatic Reference Counting")
Sound *tempSound = [[Sound alloc] init];
[tempSound playSound: #"testSound.mp3" volume: 2 repeats: 2];
the tempSound object is deallocated when the pressButton: is left, because no strong references to that object exist anymore.
If you add an instance variable (or property) sound to the view controller class, and assign to that
sound = [[Sound alloc] init];
[sound playSound: #"testSound.mp3" volume: 2 repeats: 2];
then it should work as expected.
Alternatively, you could prevent the Sound object from being deallocated too early by maintaining a "self reference" inside the object, which is removed only when the sound has finished playing:
#interface Sound () <AVAudioPlayerDelegate>
#property(strong, nonatomic) AVAudioPlayer *audioPlayer;
#property(strong, nonatomic) Sound *selfRef;
#end
#implementation Sound
- (void)playSound:(NSString *)soundFile volume:(NSInteger)volume repeats:(NSInteger)repeats
{
NSLog(#"Sound playSound");
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:soundFile withExtension:nil];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
if (self.audioPlayer == nil) {
NSLog(#"%#", [error description]);
NSLog(#"Sound.m playSound NOT executed");
} else{
self.audioPlayer.numberOfLoops = repeats;
self.audioPlayer.delegate = self;
[self.audioPlayer play];
self.selfRef = self; // self reference to avoid deallocation
NSLog(#"Sound.m playSound executed");
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
self.selfRef = nil; // remove self reference
}
#end
Of course, you shouldn't do this with "infinite repetition"!

iOS 5 movie player

Hi everyone i got a problem to play a video in iOS 5. When I'm building the program i get a warning "local declaration of hides instance variables" and when i run the program and tap the button i get a "SIGABRT". And i don't know what to do, all the help i can get is aprriciated!!
Thx in advance
MY .h file
#import <MediaPlayer/MediaPlayer.h>
#interface MainViewController : UIViewController {
MPMoviePlayerController *moviePlayer;
}
-(IBAction)Video:(id)sender;
#end
MY .m file
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
-(IBAction)Video:(id)sender {
MPMoviePlayerController *moviePlayer;
NSString *path = [[NSBundle mainBundle] pathForResource:#"big-buck-bunny-clip" ofType:#"m4v"];
NSURL *videoURL = [NSURL fileURLWithPath:path];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[moviePlayer setControlStyle:MPMovieControlStyleDefault];
[moviePlayer.view setFrame: self.view.bounds];
[self.view addSubview: moviePlayer.view];
[moviePlayer prepareToPlay];
[moviePlayer play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
local declaration of hides instance variables
remove the first line of your -(IBAction)Video:(id)sender method.
MPMoviePlayerController *moviePlayer; //this line;
because you already have declared such variable in your .h file.
Means you declared the same variable names two times, one in .h file and another in .m file.