AVAudioPlayer playing multiple songs simultaneously? - objective-c

I am calling this ViewController from another UITableViewController which pass the the song name and index.For the very first time it play the song but when i go back to the tableView and click another song it play both songs simultaneously.
In .h file I used AVAudioPlayer
#property (nonatomic, strong) AVAudioPlayer *audioPlayer;
In .m file:
- (void)viewDidLoad
{
[super viewDidLoad];
[self sliderValueChanged:volumeSlider];
[self updateTime];
[self playOrPauseSound:nil];
volumeSlider.value=0.5;
count=songArray.count;
[self setupAVPlayerForURL:songIndex];
_audioPlayer.delegate=self;
}
-(void) setupAVPlayerForURL: (int) url {
NSString *songname=[NSString stringWithFormat:#"%#",songArray[songIndex]];
songTitle.text=songname;
NSString* saveFileName = songname;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:saveFileName];
NSURL *url1 = [[NSURL alloc] initFileURLWithPath: path];
self.audioPlayer=[[AVAudioPlayer alloc] initWithContentsOfURL:url1 error:NULL];
[self.audioPlayer play];
self.seekBarSlider.minimumValue = 0.0f;
self.seekBarSlider.maximumValue = self.audioPlayer.duration;
[self updateTime];
self.isPlaying=YES;
_audioPlayer.delegate=self;
[_audioPlayer addObserver:self forKeyPath:#"status" options:0 context:nil];
}

Maybe you have to check if the audioplayer is already playing before lauch another song
if(self.audioplayer && [self.audioplayer isPlaying]){
[self.audioplayer stop];
}

Related

Playing a simple Audio file in iOS

A very common question but I can't figure out what I'm doing wrong in playing a simple audio file in iOS 10 and 9. I have the following code:
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
NSString *soundFilePath = [NSString stringWithFormat:#"%#",[[NSBundle mainBundle] pathForResource:#"www/sounds/ringbacktone" ofType:#"mp3"]];
[self playTone:soundFilePath Loop:YES];
-(void) playTone:(NSString *) soundFilePath Loop:(BOOL) loop{
NSLog(#"Sound File Path: %#",soundFilePath);
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:soundFilePath]){
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSError *error = nil;
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
if (error){
NSLog(#"Error creating the audio player: %#",error);
}else{
if (loop == YES)
player.numberOfLoops = -1; //Infinite
[player setVolume:1.0];
[player play];
}
}else{
NSLog(#"No sound will be played. The file doesn't exist.");
}
}
The output is
Sound File Path: /var/containers/Bundle/Application/E8CCA88C-B6AB-4C36-9426-EFBB94E1D509/myapp.app/www/sounds/myfile.mp3
The file exists so the sound should play. I've tried wav,m4a and mp3 files without success.
I'm using the function before calling pjsip library. Not sure if it plays a role.
Any thoughts? Is there any other way to debug it further?
check this solution it may work :
1.create property for ur audio player:
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
2.write delegate methods for player: AVAudioPlayerDelegate
3.implement this in ur action :
yourSoundArray=[NSArray arrayWithObjects:#"sound1",#"sound2",#"sound3",#"sound4",#"sound5",#"sound6", nil];//dont include formate type
NSString *audioPath = [[NSBundle mainBundle] pathForResource: [yourSoundArray objectAtIndex:indexPath.row] ofType:#"mp3"];
NSLog(#"%#",audioPath);
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *audioError = [[NSError alloc] init];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&audioError];
audioPlayer.delegate=self;
if (!audioError) {
NSLog(#"playing!");
audioPlayer play];
}
else {
NSLog(#"Error!");
}
check the audio player-delegate action
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{ NSLog(#"%d",playing the audio);
}
The answer was a combination of these:
in .h file I had to inherit from AVAudioPlayerDelegate, i.e.
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#interface scAudioManager : NSObject <AVAudioPlayerDelegate>{
#property (strong, nonatomic) AVAudioPlayer *player;
}
And then in .m file:
NSString *soundFilePath = [NSString stringWithFormat:#"%#",[[NSBundle mainBundle] pathForResource:#"www/sounds/ringbacktone" ofType:#"mp3"]];
[self playTone:soundFilePath Loop:YES];
-(void) playTone:(NSString *) soundFilePath Loop:(BOOL) loop{
NSLog(#"Sound File Path: %#",soundFilePath);
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:soundFilePath]){
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSError *error = nil;
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
if (error){
NSLog(#"Error creating the audio player: %#",error);
}else{
if (loop == YES)
_player.numberOfLoops = -1; //Infinite
_player.volume=[[AVAudioSession sharedInstance] outputVolume];
_player.delegate = self;
[_player prepareToPlay]
[_player play];
}
}else{
NSLog(#"No sound will be played. The file doesn't exist.");
}
}

How to save AVAudioFile to document directory?

I want to save AVAudioFile to document directory with NSDictionary. Can anyone help me?
AVAudioFile *audiofile=[[AVAudioFile alloc] initForWriting:destinationURL settings:settings error:&error];
save this audio file to document directory...
Path to the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
Saving the audio file to the documents directory:
BOOL status = [NSDictionary writeToFile:filePath atomically:YES];
if(status){
NSLog(#"File write successfully");
}
- (NSString *) dateString
{
// return a formatted string for a file name
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"ddMMMYY_hhmmssa";
return [[formatter stringFromDate:[NSDate date]]stringByAppendingString:#".aif"];
}
It saves below as in Documents
23Aug16_044104PM.aif
Why we save above like is we can differenciate the previous one next one by time.So we can't confuse now.
ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController<AVAudioSessionDelegate,AVAudioRecorderDelegate, AVAudioPlayerDelegate>
{
NSURL *temporaryRecFile;
AVAudioRecorder *recorder;
AVAudioPlayer *player;
}
- (IBAction)actionRecordAudion:(id)sender;
- (IBAction)actionPlayAudio:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setActive:YES error:nil];
[recorder setDelegate:self];
}
- (IBAction)actionRecordAudion:(id)sender
{
NSError *error;
// Recording settings
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setValue: [NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[settings setValue: [NSNumber numberWithFloat:8000.0] forKey:AVSampleRateKey];
[settings setValue: [NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[settings setValue: [NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
[settings setValue: [NSNumber numberWithInt: AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];
NSArray *searchPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath_ = [searchPaths objectAtIndex: 0];
NSString *pathToSave = [documentPath_ stringByAppendingPathComponent:[self dateString]];
NSLog(#"the path is %#",pathToSave);
// File URL
NSURL *url = [NSURL fileURLWithPath:pathToSave];//FILEPATH];
//Save recording path to preferences
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setURL:url forKey:#"Test1"];
[prefs synchronize];
// Create recorder
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
[recorder prepareToRecord];
[recorder record];
}
- (IBAction)actionPlayAudio:(id)sender
{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
//Load recording path from preferences
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
temporaryRecFile = [prefs URLForKey:#"Test1"];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:temporaryRecFile error:nil];
player.delegate = self;
[player setNumberOfLoops:0];
player.volume = 1;
[player prepareToPlay];
[player play];
}
Record and Save Audio Permanently
Record Audio File and save Locally
Just now I tried the below code with iPhone 4s and it works perfectly.
AudioViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface AudioViewController : UIViewController<AVAudioSessionDelegate,AVAudioRecorderDelegate,AVAudioPlayerDelegate>
- (IBAction)actionRecordAudio:(id)sender;
- (IBAction)actionPlayAudio:(id)sender;
- (IBAction)actionStopAudio:(id)sender;
#property (strong, nonatomic) AVAudioRecorder *audioRecorder;
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
#end
AudioViewController.m
#import "AudioViewController.h"
#interface AudioViewController ()
#end
#implementation AudioViewController
#synthesize audioPlayer,audioRecorder;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:#"sound.caf"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSDictionary *recordSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0],
AVSampleRateKey,
nil];
NSError *error = nil;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
audioRecorder = [[AVAudioRecorder alloc]initWithURL:soundFileURL settings:recordSettings error:&error];
if (error)
{
NSLog(#"error: %#", [error localizedDescription]);
}
else {
[audioRecorder prepareToRecord];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)actionRecordAudio:(id)sender
{
if (!audioRecorder.recording)
{
[audioRecorder record];
}
}
- (IBAction)actionPlayAudio:(id)sender
{
if (audioRecorder.recording)
{
NSError *error;
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:audioRecorder.url
error:&error];
audioPlayer.delegate = self;
if (error)
NSLog(#"Error: %#",
[error localizedDescription]);
else
[audioPlayer play];
}
}
- (IBAction)actionStopAudio:(id)sender
{
if (audioRecorder.recording)
{
[audioRecorder stop];
}
else if (audioPlayer.playing) {
[audioPlayer stop];
}
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
}
-(void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
NSLog(#"Decode Error occurred");
}
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
}
-(void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error
{
NSLog(#"Encode Error occurred");
}
#end
Here is source

SKVideoNode strange log error

I'm creating a SKVideoNode in the following way. It creates the video without any issues, but I get this strange log message and I'm wondering if anyone knows what it's all about. I tried googling it, but I couldn't find anything.
Here's the error:[22:48:15.170] vtFindDynamicSession signalled err=-11204 (err) (registered pixel transfer service failed to open; falling back) at /SourceCache/CoreMedia_frameworks/CoreMedia-1562.240/Sources/VideoToolbox/VTPixelTransferSession.c line 6878
GameScene.m
#import "GameScene.h"
#import <AVFoundation/AVFoundation.h>
#interface GameScene()
#property SKVideoNode *vid;
#property AVPlayer *avPlayer;
#end
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
NSString *fileName = #"QSeanRay";
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDesktopDirectory, NSUserDomainMask, YES);
NSString *desktopPath = [paths objectAtIndex:0];
NSString *resourcePath = [NSString stringWithFormat:#"%#/vs", desktopPath];
NSString *videoPath = [NSString stringWithFormat:#"%#/%#.mp4", resourcePath, fileName];
NSURL *fileURL = [NSURL fileURLWithPath:videoPath];
AVPlayer *avPlayer = [[AVPlayer alloc] initWithURL:fileURL];
_vid = [SKVideoNode videoNodeWithAVPlayer:avPlayer];
_vid.position = CGPointMake(view.bounds.size.width/2, view.bounds.size.height/2);
[_vid setScale:0.4];
[self addChild:_vid];
[_vid play];
avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[avPlayer currentItem]];
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
AVPlayerItem *p = [notification object];
[p seekToTime:kCMTimeZero];
}
#end

iOS: Saving A Picture In UIImageView

I have an app that allows the user to choose a picture from their camera roll, and display it in a UIImageView. I usually use this method to save text in text fields, and I assumed that it would work for an image as well, but I'm having some issues with it. There are no errors, but it simply does not save the image.
This is the relevant code I'm using:
.h:
#define kFilename9 #"PGdata.plist"
...
- (NSString *)dataFilePath;
.m:
- (NSString *)dataFilePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename9];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification {
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:image.image];
[array writeToFile:[self dataFilePath] atomically:YES];
}
- (void)viewDidLoad
{
...
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
image.image = [array objectAtIndex:0];
}
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app];
[super viewDidLoad];
}
You have to convert the UIImage to a PNG or JPG first, using UImagePNGRepresentation or UIImageJPEGRepresentation. Those function return NSData which you can then write to a file.
You can save by following this way。
UIImage * image;//the image you want to save
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir=[paths objectAtIndex:0];
NSFileManager *filemanager=[NSFileManager defaultManager];
NSData * imagedata=UIImageJPEGRepresentation(image,1);
NSString *savePath= [docDir stringByAppendingPathComponent:#"imageName.jpg"];
BOOL isdic=NO;
BOOL isHave=[filemanager fileExistsAtPath:savePath isDirectory:&isdic];
if (isHave==YES&&isdic==NO) {
[filemanager removeItemAtPath:savePath error:nil];
}
BOOL result= [imagedata writeToFile:savePath atomically:YES];

how do I use a file from my apps documents directory with "didSelectRowAtIndexPath"?

I have a bunch of mp3's displayed in a UITableView which are located in my apps documents directory.
When I select the row, I want the file to load into AVAudioPlayer and Play.
Can anyone suggest how I would go about doing this?
Any help would be greatly appreciated.
Thanks!
I finally figured this out:
NSArray *songs;
AVAudioPlayer *player;
- (void)viewDidLoad
{
[self.player prepareToPlay];
// Point to Document directory
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSError *error = nil;
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
if (array == nil) {
// Handle the error
}
self.songs = array;
//[array release];
//self.title = #"Song List";
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *applicationDocumentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [applicationDocumentsDirectory stringByAppendingPathComponent: [songs objectAtIndex:indexPath.row]];
NSURL *url = [NSURL fileURLWithPath:filePath];
player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
[player play];
}