Play and Pause function - ios

I have a soundboard app that plays sound and is supposed to play music and if you click the button then it pauses but it doesn't pause it only stops the music.
And once the music finishes the button stays selected.
My code is;
- (IBAction)aint:(id)sender {
UIButton *aint = (UIButton *)sender;
aint.selected = !aint.selected;
if(aint.selected)
{
// Play
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"mp3"];
theAudio2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path2] error:NULL];
theAudio2.delegate = self;
theAudio2.numberOfLoops = 0;
[theAudio2 play];
[[NSUserDefaults standardUserDefaults] setObject:#"-" forKey:#"music"];
}
else
{
// Pause
[theAudio2 pause];
}
}
And I have theAudio2 and AVAudioPlayer declared.

Try this it will work as expected -
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"mp3"];
theAudio2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path2] error:NULL];
theAudio2.delegate = self;
theAudio2.numberOfLoops = 0;
}
- (IBAction)aint:(id)sender
{
UIButton *aint = (UIButton *)sender;
aint.selected = !aint.selected;
if(aint.selected)
{
// Play
[theAudio2 play];
[[NSUserDefaults standardUserDefaults] setObject:#"-" forKey:#"music"];
}
else
{
// Pause
[theAudio2 pause];
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
playerBtn.selected = NO;
}

Related

How to play the music continously which are stored in NSArray?

In tableview footer i have a play button to play the music, as the music starts tableview scrolls automatically according to the audio played but if the user tap on particular cell, the content in the particular cell is playing and stops but i want to continue the music from where the use taps to the end. Below is the code. Please help.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int ref =(int) indexPath.row;
NSString *filePath = [soundArray objectAtIndex:ref];
NSString *Path = [[NSBundle mainBundle] pathForResource:filePath ofType:#"mp3"];
NSURL *musicFile = [NSURL fileURLWithPath:Path];
myAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile error:nil];
if (playing == YES) {
[playButton setBackgroundImage:[UIImage imageNamed:#"pause_White.png"] forState:UIControlStateNormal];
[myAudioPlayer play];
// playing = NO;
}
if (playing == NO) {
// [playButton setBackgroundImage:[UIImage imageNamed:#"play_white.png"] forState:UIControlStateNormal];
}
}
SoundArray contains trimmed music. How to continue the song ? Help much appreciated.
Here is my code as per my concept. You may have to manage it more as its just a sample
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
isMainMusic = NO;
// Construct URL to sound file
NSString *path = [NSString stringWithFormat:#"%#/1.mp3", [[NSBundle mainBundle] resourcePath]];
mainMusicUrl = [NSURL fileURLWithPath:path];
NSString *path1 = [NSString stringWithFormat:#"%#/2.mp3", [[NSBundle mainBundle] resourcePath]];
secondMusicUrl = [NSURL fileURLWithPath:path1];
}
-(void)playSecondaryMusic
{
if ([playMainMusic isPlaying]) {
[playMainMusic pause];
}
if (playSecondaryMusic) {
playSecondaryMusic.delegate = nil;
playSecondaryMusic = nil;
}
isMainMusic = NO;
playSecondaryMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:secondMusicUrl error:nil];
playSecondaryMusic.delegate = self;
[playSecondaryMusic play];
}
- (IBAction)playMainMusic:(UIButton *)sender {
if (playMainMusic) {
playMainMusic.delegate = nil;
playMainMusic = nil;
}
isMainMusic = YES;
playMainMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:mainMusicUrl error:nil];
playMainMusic.delegate = self;
[playMainMusic play];
}
//Delegate method
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if (isMainMusic)
{
NSLog(#"Main music");
}
else
{
NSLog(#"Second music");
[playMainMusic play];
isMainMusic = YES;
}
}

Memory Management - Loading Sound Effects - Cocoa Xcode

So it has been brought to my attention that I should optimise the way I load and use sounds in a small game that I am developing for iOS.
I load a "boing" sound and play it every time I tap the screen, making the sprite jump (like mario).
I want to be able to play the sound every time, even if the sound is already playing from the previous jump...
Below are the 2 ways I'm currently using:
1st implementation:
//load the music from file
-(void)LoadMusic{
jumpSound = [[NSBundle mainBundle] pathForResource:#"boing" ofType:#"mp3"];
}
//call in viewDidLoad
- (void)viewDidLoad{
[self LoadMusic];
...
[super viewDidLoad];
}
//play sound when called
-(void)playSound{
jumpAffect = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
[jumpAffect play];
}
//tap/touch to jump (& play sound)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event{
[self playSound];
jumpUp = 16;
}
2nd implementation:, this is similar except I load the same file 5 times, and loop through to the next one (so the same sound affect can be called even if it's already in previous session).
int soundStage = 1;
//load the music from file
-(void)LoadMusic{
jumpSound = [[NSBundle mainBundle] pathForResource:#"Boing" ofType:#"mp3"];
jumpAffect = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect.delegate = self;
jumpAffect2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect2.delegate = self;
jumpAffect3 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect3.delegate = self;
jumpAffect4 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect4.delegate = self;
jumpAffect5 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect5.delegate = self;
}
//call in viewDidLoad
- (void)viewDidLoad{
[self LoadMusic];
...
[super viewDidLoad];
}
//tap/touch to jump (& play sound)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event{
jumpUp = 16;
if(soundStage == 1){
[jumpAffect play];
soundStage = 2;
}
else if(soundStage == 2){
[jumpAffect2 play];
soundStage = 3;
}
else if(soundStage == 3){
[jumpAffect3 play];
soundStage = 4;
}
else if(soundStage == 4){
[jumpAffect4 play];
soundStage = 5;
}
else if(soundStage == 5){
[jumpAffect5 play];
soundStage = 1;
}
I'm wondering which why is the better way? I'm hoping to avoid memory leaks and just optimise it by being able to continuously have the same sound play when the screen is tapped. Thanks.
AVAudioPlayer plays multiple sounds simultaneously, one sound per audio player. So better is to load/play your quick sound inside the touchesBegan method without keeping the reference:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event
{
NSString *jumpSound = [[NSBundle mainBundle] pathForResource:#"boing" ofType:#"mp3"];
AVAudioPlayer *jumpAffect = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
[jumpAffect prepareToPlay];
[jumpAffect play];
jumpUp = 16;
}

How can I use this code to play more sounds?

//Action to play Audio//
-(IBAction)playAudio:(id)sender {
[self.loopPlayer play];
}
//Action to stop Audio//
-(IBAction)stopAudio:(id)sender {
if (self.loopPlayer.isPlaying) {
[self.loopPlayer stop];
self.loopPlayer.currentTime = 0;
self.loopPlayer.numberOfLoops = -1;
[self.loopPlayer prepareToPlay];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Code that gets audio file "trap synth"//
NSURL* audioFileURL = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];
}
This is the code i'm using with one button to play the sound when the button is tapped and stop the sound when the button is released. How would I go about adding more sounds to more buttons? I want to have more buttons that play and stop different sounds just like this.
property (nonatomic, strong) AVAudioPlayer *loopPlayer;
This code is also in my ViewController.h file
Ok although the answer provided by Miro is on the write track the code example given has issues.
Should be this in viewDidLoad -
- (void)viewDidLoad {
[super viewDidLoad];
NSURL* audioFileURL1 = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL1 error:nil];
NSURL* audioFileURL2 = [[NSBundle mainBundle] URLForResource:#"other_audio_file" withExtension:#"wav"];
self.loopPlayer2 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL2 error:nil];
}
also stopAudio: method should be this
-(IBAction)stopAudio:(id)sender {
if (self.loopPlayer1.isPlaying && (sender.tag == 1)) {
[self.loopPlayer1 stop];
self.loopPlayer1.currentTime = 0;
self.loopPlayer1.numberOfLoops = -1;
[self.loopPlayer1 prepareToPlay];
}
if (self.loopPlayer2.isPlaying && (sender.tag == 2)) {
[self.loopPlayer2 stop];
self.loopPlayer2.currentTime = 0;
self.loopPlayer2.numberOfLoops = -1;
[self.loopPlayer2 prepareToPlay];
}
}
And finally for playAudio:
-(IBAction)playAudio:(id)sender {
if([sender tag] == 1){
[self.loopPlayer1 play];
}
if([sender tag] == 2){
[self.loopPlayer2 play];
}
}
If you want to play different sounds at the same time you should look into creating separate AVAudioPlayers - if you create a different one for each sound, then you can easily control (play/stop) each of them separately with a specific button.
On the simplest level, you could do something like this, which allows you to use the same button handlers for all your audio. The playAudio checks the tag of the Play button you press (be sure to set the tag value in IB, to 1,2,etc). There really only need be one Stop button.
You could enhance this in many ways, like attempting to reuse the AVAudioPlayer somehow, and loading the audio on the fly instead of all at the beginning. Or storing your audio file info in an array, creating an array of AVAudioPlayers for management, etc. But this is a start.
-(IBAction)playAudio:(id)sender {
// first, stop any already playing audio
[self stopAudio:sender];
if([sender tag] == 1){
[self.loopPlayer1 play];
} else if([sender tag] == 2){
[self.loopPlayer2 play];
}
}
-(IBAction)stopAudio:(id)sender {
if (self.loopPlayer1.isPlaying) {
[self.loopPlayer1 stop];
self.loopPlayer1.currentTime = 0;
self.loopPlayer1.numberOfLoops = -1;
[self.loopPlayer1 prepareToPlay];
} else if (self.loopPlayer2.isPlaying) {
[self.loopPlayer2 stop];
self.loopPlayer2.currentTime = 0;
self.loopPlayer2.numberOfLoops = -1;
[self.loopPlayer2 prepareToPlay];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
NSURL* audioFileURL1 = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];
NSURL* audioFileURL2 = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer2 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];
}
AND, in the .h file;
property (nonatomic, strong) AVAudioPlayer *loopPlayer1;
property (nonatomic, strong) AVAudioPlayer *loopPlayer2;

My buttons play all the same sound?

Here is my MainViewController.m
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize audioPlayer;
#synthesize soundsArray;
-(void)prepareSounds
{
NSString *filepath= [[NSBundle mainBundle] pathForResource:#"Sounds" ofType:#"plist"];
self.soundsArray = [[NSArray alloc] initWithContentsOfFile:filepath];
}
- (IBAction)playSound:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
- (IBAction)playSound2:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -2)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
- (IBAction)playSound3:(id)sender {
UIButton *buttonPressed = (UIButton *)sender;
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -3)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES completion:nil];
}
#end
My MainViewController.h
#import <UIKit/UIKit.h>
#import "FlipsideViewController.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
AVAudioPlayer *audioPlayer;
NSArray *soundsArray;
}
#property(nonatomic, retain) AVAudioPlayer *audioPlayer;
#property(nonatomic, retain) NSArray *soundsArray;
-(void)prepareSounds;
- (IBAction)playSound:(id)sender;
- (IBAction)playSound2:(id)sender;
- (IBAction)playSound3:(id)sender;
#end
In the 'Supporting Files' folder I have an array of strings with the name of the sound files I want to play, and in the 'Supporting Files' folder I have a folder named 'Sounds', which contains the sound files.
All of my buttons play the same sound. Can someone please provide some insight. Thanks!
I think the problem may be in this line playSound:
NSString *soundName = [soundsArray objectAtIndex:(buttonPressed.tag -1)]
which is repeated in playSound2 and playSound3 with "buttonPressed.tag -2" and "buttonPressed.tag -3".
If your buttonPressed.tags are set to 1, 2, and 3, then each time "buttonPressed.tag -X" is likely evaluating to 0, and playing the sound of the first file in the array.
You are repeating the code to do the same task.
Add all your buttons IBAction to a single method (say it as playSound)
Implement the method like:
- (IBAction)playSound:(UIButton *)sender
{
NSString *soundName = [soundsArray objectAtIndex:(sender.tag -1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
[self.audioPlayer play];
}
There is no need of writing same code for each individual button.
SOLVED: prepareSounds() was never called. Here is the working code:
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize audioPlayer;
#synthesize soundsArray;
-(void)prepareSounds
{
NSString *filepath= [[NSBundle mainBundle] pathForResource:#"Sound" ofType:#"plist"];
self.soundsArray = [[NSArray alloc] initWithContentsOfFile:filepath];
}
- (void)stopAudio
{
if (audioPlayer!= nil) {
[audioPlayer stop];
//do some task for changing the Image i.e setting the default image
}
}
- (IBAction)playSound:(UIButton *)sender
{
UIButton *btn = (UIButton*)sender;
NSString *soundName = [soundsArray objectAtIndex:(btn.tag - 1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
if([audioPlayer isPlaying])
{
[self stopAudio];
}
[self.audioPlayer play];
}
- (void)viewDidLoad
{
[self prepareSounds];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES completion:nil];
}
#end

expected identifer or "(" Objective C

I am incredibly new to xcode and im making an app for a school project. I am working on a background music code to play/pause on the same button (found the code but modified it some). I've been able to clear up the other errors but I don't know what to do about this... expected identifier or "("
#implementation settingscontroller2
-(void) btnAction:(UIButton*)button{
button.selected = !button.selected;}
{ //expected Identifier or "("
if (button.selected){
// Play
NSString *path = [[NSBundle mainBundle] pathForResource:#"app" ofType:#"mp3"];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
theAudio.numberOfLoops = -1;
[theAudio play];
}
else (!button.selected){
// Pause
[theAudio pause];
return.nil
}
}
once check this one,
-(void) btnAction:(UIButton*)button{
button.selected = !button.selected;
if (button.selected){
// Play
NSString *path = [[NSBundle mainBundle] pathForResource:#"app" ofType:#"mp3"];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
theAudio.numberOfLoops = -1;
[theAudio play];
}
else if(!button.selected){//here also one problem in your code.
// Pause
[theAudio pause];
//return.nil
}
}
In your line
button.selected = !button.selected;}
The "}" is too much as the following "{".
-(void) btnAction:(UIButton*)button{
button.selected = !button.selected;}
{ //expected Identifier or "("
You've got two method bodies here. It looks like you should probably remove the first } and the next {, and maybe reformat a bit, so that you have:
-(void) btnAction:(UIButton*)button
{
button.selected = !button.selected;
if (button.selected){
Try to replace the second last line with return;
try to remove the } at the end of
button.selected = !button.selected;
and the line that gives you error.

Resources