iOS : How to avoid overlapping sound/music in PickerViewController - iphone

I have one music player with multiple sounds using picker view. My problem is when i click the next music, the previous one will overlap with the one that i've selected.Meaning when i scroll the pickerview to select a new object, it will play a new music/sound but the previous object will overlap the current selection. I want to stop the previous music so that it won't overlap. Here is the code.
H File :
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#interface PickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, AVAudioPlayerDelegate>{
UIPickerView *picker;
UILabel *musicTitle;
NSMutableArray *musicList;
AVAudioPlayer *audioPlayer;
}
#property (nonatomic, retain) IBOutlet UIPickerView *picker;
#property (nonatomic, retain) IBOutlet UILabel *musicTitle;
#property (nonatomic, retain) NSMutableArray *musicList;
-(IBAction)playSelectedMusic:(id)sender;
#end
M File :
- (void)viewDidLoad
{
[super viewDidLoad];
musicList = [[NSMutableArray alloc] initWithObjects:#"m1",#"m2",#"m3",#"m6",#"m4", #"m5",nil];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if ([[musicList objectAtIndex:row] isEqual:#"m1"])
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"m1" ofType:#"mp3"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
pickerView.delegate = self;
[theAudio play];
[theAudio setCurrentTime:0.0]; (our friend from this forum have suggested this but still doens't work)
NSString *resultString = [[NSString alloc] initWithFormat:
#"m1",
[musicList objectAtIndex:row]];
musicTitle.text = resultString;
}
if ([[musicList objectAtIndex:row] isEqual:#"m2"])
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"m2" ofType:#"mp3"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
pickerView.delegate = self;
[theAudio play];
[theAudio setCurrentTime:0.0]; (our friend from this forum have suggested this but still doens't work)
NSString *resultString = [[NSString alloc] initWithFormat:
#"m2",
[musicList objectAtIndex:row]];
musicTitle.text = resultString;
}
Code amendment :
NSString *path = [[NSBundle mainBundle] pathForResource:#"you" ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:file error:NULL];
[file release];
self.audioPlayer = theAudio;
[theAudio release];
[audioPlayer prepareToPlay];
[audioPlayer setDelegate:self];
[audioPlayer setNumberOfLoops:0];
[audioPlayer stop];
my silly mistake :
#property (nonatomic, retain) AVAudioPlayer *audioPlayer;

Just stop the currently playing sound before starting another one, your AVAudioPlayer is an ivar so you could do it. Add
[theAudio stop];

Related

Play multiple music with AVAudioPlayer

I am trying to play a 2 musics they should play after each other with loop option ,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString * music = [[NSBundle mainBundle] pathForResource:#"music" ofType:#"wav"];
myMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
myMusic.delegate = self;
[myMusic play];
}
and play second music :
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
NSString * music = [[NSBundle mainBundle] pathForResource:#"music2" ofType:#"wav"];
myMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
myMusic.delegate = self;
[myMusic play];
NSLog(#"MUSIC FINISH");
}
now the problem is how can I play previous music ?
Try this
ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController<AVAudioPlayerDelegate>
{
AVAudioPlayer *player;
int nIndex;
NSArray *arrPlayList;
}
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
arrPlayList =[[NSArray alloc]initWithObjects:#"music1.wav",#"music2.wav",#"music3.wav", nil];
nIndex =[arrPlayList count]-1;
[self playSound:nIndex];
}
-(void)playSound:(int )index
{
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *strFilePath = [path stringByAppendingPathComponent:[arrPlayList objectAtIndex:index]];
NSURL *filePath = [NSURL fileURLWithPath:strFilePath];
player= [[AVAudioPlayer alloc] initWithContentsOfURL:filePath error:nil];
player.delegate=self;
[player play];
}
#pragma mark - AVFoundation Delegate Methods
-(void)audioPlayerDidFinishPlaying: (AVAudioPlayer *)player successfully:(BOOL)flag
{
NSLog(#"MUSIC FINISH");
if (nIndex==0) {
return;
}
nIndex--;
[self playSound:nIndex];
}
-(void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
NSLog(#"Decode Error occurred");
}

ios AVAudioPlayer plays sound with echo

I have two AVAudioPlayer to determine what sound has finished to do something after that. the first sound plays just fine but the second sound (twoPlayer) plays the sound with echo. any of you knows why or how this happend?
I have this on my .h file:
#interface myClass : UIViewController<AVAudioPlayerDelegate>
{
AVAudioPlayer *onePlayer;
AVAudioPlayer *twoPlayer;
}
#property (retain, nonatomic) AVAudioPlayer *onePlayer;
#property (retain, nonatomic) AVAudioPlayer *twoPlayer;
.m file:
NSString *urlAddress = [[NSBundle mainBundle] pathForResource:#"sound" ofType:#"m4a"];
NSURL *url = [NSURL fileURLWithPath:urlAddress];
NSError *error;
twoPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
twoPlayer.delegate=self;
twoPlayer.volume=0.5;
if (twoPlayer == nil)
NSLog(#"[error description]");
else
[twoPlayer play];
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
if (player==onePlayer) {
[onePlayer release];
}
if (player==twoPlayer) {
[numberPlayer release];
}
}
I found the error I was setting a UIButton with "forControlEvents:UIControlEventAllTouchEvents" and the actionw was been trigger more then once. I replace the UIButton with this forControlEvents:UIControlEventTouchDown and works just fine.

UIButtons event Touch up Inside not work properly?

My question is little abmigious ,thats why I posted all my code,so I request to every one please test all this code before giving me the Answer.Thanx
In my application i create all UIButtons programmatically and then save all these UIButtons in NSMutableArray. Here is my code:-
-(void)button:(id)sender
{
int btnn = 0;
int spacex = 152;
int spacey=20;
int k=0;
saveBtn = [[NSMutableArray alloc] init];
for (int i=0; i<48; i++)
{
if (btnn>6)
{
spacey=spacey+25;
spacex = 152;
btnn = 0;
}
else
{
btnn++ ;
k++;
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(spacex, spacey, 25.0, 25.0);
int idx;
idx = arc4random()%[arr count];
NSString* titre1 = [arr objectAtIndex:idx];
[btn setTitle: titre1 forState: UIControlStateNormal];
[btn setTitleColor: [UIColor yellowColor] forState: UIControlStateNormal];
[btn.titleLabel setFont:[UIFont fontWithName:#"TimesNewRomanPS-BoldMT" size:22.0]];
spacex = spacex + 25;
btn.tag=k;
[btn addTarget:self action:#selector(aMethod:)forControlEvents:UIControlEventTouchUpInside];
[saveBtn addObject:btn];
[self.view addSubview:btn];
}
}
}
Now in (aMethod:) I add click sound on Each UIButton TouchUpInside event. Here is my code.
- (void)aMethod:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
[theAudio play];
}
Every thing work fine in start of my application , but continiously clicking the UIButtons approximatilly after 100 clicks i hear no sound of click and when i click on Next UIButtons touchup inside event its crash.Can any body help me in this issue.Thanx
app due to uncaught exception NSInternalInconsistencyException, reason: Could not load NIB in bundle: NSBundle </Users/moon/Library/Application Support/iPhone Simulator/4.1/Applications/3E14E5D6-4D1B-4DAC-A2B9-07667E99C399/soundtesting.app‌​> (loaded) with name secondclass
Ah, yes. What we have here is a failure to understand log messages. Your UIButton, which I can only assume pushes a new view onto the stack, is referencing a NIB that simply doesn't exist. It's a naming issue, not a button issue. Most likely, I would check for any calls to -initWithNibName: and see if your NIB really is named "secondclass.". Remember, iOS file names are CaSe SeNsITive.
//.h
...
#property (nonatomic, retain) AVAudioPlayer * player;
//.m
-(void)viewDidLoad
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
player=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
player.delegate=self;
//in MRC, use [path release];
}
-(void)someMethod:(id)sender
{
[player play];
}
The reason might me memory leak for playing same audio these many times it may fill memory use this code for playing audio
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundleOrNil
{
if (self = [super initWithNibName:nibName bundle:nibBundleOrNil]) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
theAudio = [AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:NULL];
}
return self;
}
- (IBAction)playSound
{
[theAudio play];
}
- (void)dealloc
{
[theAudio release];
[super dealloc];
}
You have a memory issue. When you do :
- (void)aMethod:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
[theAudio play];
}
1/ path is never released
2/ theAudio is never release
So you need to release theAudio in delegate method :
– audioPlayerDidFinishPlaying:successfully:
And you need to release path like this :
- (void)aMethod:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
[theAudio play];
[path release];
}
I think your problem should be solved.
I test your code . Changes in your aMethod following code. Though this I can get tag value.
- (void)aMethod:(id)sender
{
UIButton *btn=(UIButton *)sender;
NSLog(#"\n\n\nselectedbutton tag === %d \n\n\n",btn.tag );
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
[audioPlayer play];
}

iPhone Subclass of Sounds

Update! Fixed! This now works! Use at your will !
#import <Foundation/Foundation.h>
#import "AVFoundation/AVAudioPlayer.h"
#interface SoundsClass : NSObject <AVAudioPlayerDelegate> {
AVAudioPlayer *buttonClick;
AVAudioPlayer *slide;
AVAudioPlayer *Cellpush;
AVAudioPlayer *pop;
AVAudioPlayer *tick;
AVAudioPlayer *done;
AVAudioPlayer *swoosh;
}
#property (nonatomic, retain) AVAudioPlayer *buttonClick;
#property (nonatomic, retain) AVAudioPlayer *slide;
#property (nonatomic, retain) AVAudioPlayer *Cellpush;
#property (nonatomic, retain) AVAudioPlayer *pop;
#property (nonatomic, retain) AVAudioPlayer *tick;
#property (nonatomic, retain) AVAudioPlayer *done;
#property (nonatomic, retain) AVAudioPlayer *swoosh;
-(void)PlayButtonClick:(id)sender;
-(void)PlaySlide:(id)sender;
-(void)PlayCellPush:(id)sender;
-(void)PlayPop:(id)sender;
-(void)PlayTick:(id)sender;
-(void)PlayDone:(id)sender;
-(void)PlaySwoosh:(id)sender;
#end
#import "SoundsClass.h"
#implementation SoundsClass
#synthesize buttonClick, swoosh, slide, tick, done, Cellpush, pop;
-(void)dealloc{
[buttonClick release];
[swoosh release];
[slide release];
[tick release];
[done release];
[Cellpush release];
[pop release];
[super dealloc];
}
-(void)PlayButtonClick:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"button_click"
ofType:#"caf"];
self.buttonClick = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
self.buttonClick.delegate = self;
[self.buttonClick play];
}
}
-(void)PlaySlide:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"popover_show" o
fType:#"caf"];
slide = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]
error:NULL];
slide.delegate = self;
[slide play];
}
}
-(void)PlayCellPush:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"cell_swoosh"
ofType:#"caf"];
buttonClick = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
buttonClick.delegate = self;
[buttonClick play];
}
}
-(void)PlayPop:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"pop" ofType:#"caf"];
buttonClick = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
buttonClick.delegate = self;
[buttonClick play];
}
}
-(void)PlayTick:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Tick" ofType:#"caf"];
buttonClick = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
buttonClick.delegate = self;
[buttonClick play];
}
}
-(void)PlayDone:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Done" ofType:#"caf"];
buttonClick = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
buttonClick.delegate = self;
[buttonClick play];
}
}
-(void)PlaySwoosh:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"appSounds"]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"flip" ofType:#"caf"];
buttonClick = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
buttonClick.delegate = self;
[buttonClick play];
}
}
#end
When you want to use the class just
#import "SoundsClass.h"
#class SoundsClass;
SoundsClass *sounds;
#property (nonatomic, retain) SoundsClass *sounds;
-(IBAction)openFolder:(id)sender;
-(IBAction)openFolder:(id)sender{
sounds = [[SoundsClass alloc] init];
[self.sounds PlayButtonClick:sender];
}
Thats about it really easy but works with Defaults just use a switch and set bool

iOS - How to stop background music when changing views

How to stop background music when changing views? I have no clue. If i press a button which takes me to a new view, there is new background music. But the old background music (which goes in an infinite loop) keeps on going. Please help! also sample some code please, here is mine:
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MathMusic2" ofType:#"wav"];
AVAudioPlayer* theAudio= [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
theAudio.numberOfLoops = -1;
[super viewDidLoad];
}
I just need to know how to make the background music from the new view stop playing. And vice versa when i press the back button from the new view
Create a property for the AVAudioPlayer *theAudio so you can access the audioPlayer from any point in your class.
Header file of viewController
...
AVAudioPlayer *theAudio;
...
#property (nonatomic, retain) AVAudioPlayer *theAudio;
Implentation file of viewController
...
#synthesize theAudio;
...
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MathMusic2" ofType:#"wav"];
self.theAudio= [[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]] autorelease];
theAudio.delegate = self;
[theAudio play];
theAudio.numberOfLoops = -1;
[super viewDidLoad];
}
If viewWillDisappear is called you can then just stop the audio with
- (void)viewWillDisappear
{
[theAudio stop];
}
it gaves errors in here :
"theAudio.delegate = self;" as something like assigning to id...
its yellow anyway..
still when i change view and go to another class music not stoping....