Can't record or play with a simple recorder? - objective-c

I have 2 classes, a record and a player. In my main scene, I create an instance of them and play and record. But, as I see, it only records and somehow does not play (the file is not there!)
Here is the code for both :
-(void)record {
NSArray *dirPaths;
NSString *docsDir;
NSString *sound= #"sound0.caf" ;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ;
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:sound];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax],
AVEncoderAudioQualityKey, nil];
NSError *error;
myRecorder = [[AVAudioRecorder alloc] initWithURL:soundFileURL settings:settings error:&error];
if (myRecorder) {
NSLog(#"rec");
[myRecorder prepareToRecord];
myRecorder.meteringEnabled = YES;
[myRecorder record];
} else
NSLog( #"error" );
}
I can see the log of rec.
-(void)play {
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath1 = #"sound0.caf" ;
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath1];
BOOL isMyFileThere = [[NSFileManager defaultManager] fileExistsAtPath:soundFilePath1];
if(isMyFileThere) {
NSLog(#"PLAY");
avPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:NULL];
avPlayer1.volume = 8.0;
avPlayer1.delegate = self;
[avPlayer1 play];
}
}
I DONT SEE THE LOG OF PLAY !
I call them both with:
recInst=[recorder alloc]; //to rec
[recInst record];
plyInst=[player alloc]; //play
[plyInst play];
and to stop the recorder:
- (void)stopRecorder {
NSLog(#"stopRecordings");
[myRecorder stop];
//[myRecorder release];
}
What's wrong here? Thanks.

In your record method, you're appending the file name to the path with:
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:#"sound0.caf"];
You do not do that in your play method, so it's looking for the file in whatever the current working directory is, rather than the Documents directory.
You need to do:
NSString *soundFilePath1 = [docsDir stringByAppendingPathComponent:#"sound0.caf"];
instead of:
NSString *soundFilePath1 = #"sound0.caf" ;
And just another note: soundFilePath and soundFilePath1 are both local variables. Therefore, they are not visible outside their respective methods. Thus, it's not necessary to give them different names. You can call them both soundFilePath and there will not be a conflict.

Related

writeToFile not properly saving data

I have data from a url (.m4a) and I am trying to save the file so I can edit it's metadata (change background image). The code below doesn't seem to work and I have no idea why. It is saving a file, but the file is empty.
_previewData = [NSMutableData dataWithContentsOfURL:[NSURL URLWithString:#"http://a281.phobos.apple.com/us/r1000/119/Music/v4/f1/7b/d6/f17bd6e3-55c0-b7e0-9863-bc522900e950/mzaf_5153970109972844579.aac.m4a"]];
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory=[paths objectAtIndex:0];
NSString *path = [documentDirectory stringByAppendingPathComponent:[NSString stringWithFormat: #"file.mp4"]];
NSFileManager *filemanager;
filemanager = [NSFileManager defaultManager];
[_previewData writeToFile:path atomically:YES];
if ([filemanager fileExistsAtPath:path]) {
// Runs
NSLog(#"It worked");
}
NSLog(#"%#",path);
ANMovie* file = [[ANMovie alloc] initWithFile:path]; // or .mp4
NSData* jpegCover = UIImageJPEGRepresentation(artworkImage, 1.0);
_imageView.image = [UIImage imageWithData:jpegCover];
ANMetadata* metadata = [[ANMetadata alloc] init];
metadata.albumCover = [[ANMetadataImage alloc] initWithImageData:jpegCover type:ANMetadataImageTypeJPG];
[file setMovieMetadata:metadata];
[file close];
_previewData = [NSMutableData dataWithContentsOfFile:path];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSDictionary *imageItem=#{#"public.mpeg-4-audio":self.previewData};
NSDictionary *textItem=#{#"public.plain-text":self.linkData};
pasteboard.items=#[imageItem,textItem];

issues reading from plist file

I have created a simple plist file with some user preferences for a card game I'm writing.
I have also created a controller that reads and writes to this plist file which is a singelton.
everything works fine, but then after a couple of tries it stops working.
Logging the values to the console it shows the list returning a value of 0 which causes my app to crash
I have deleted the plist and created a new one and then the same story, works fine for 2 or three time and then boom zero.
here is a copy of the controller singelton code:
#implementation userOptionsController
static userOptionsController* _sharedOptionsController = nil;
#synthesize backgroundSound=_backgroundSound;
#synthesize soundEffects = _soundEffects;
#synthesize coach = _coach;
#synthesize numberOfDecks = _numberOfDecks ;
+(userOptionsController*)sharedOptionsController{
#synchronized([userOptionsController class])
{
if(!_sharedOptionsController)
[[self alloc]init];
return _sharedOptionsController;
}
return nil;
}
+(id)alloc
{
#synchronized ([userOptionsController class])
{
NSAssert(_sharedOptionsController == nil, #"Attempted to allocate a second instance of userOptionsController singleton");
_sharedOptionsController = [super alloc];
return _sharedOptionsController;
}
return nil;
}
- (id) init {
self = [super init];
if (self) {
}
return self;
}
-(void)readPlistFile
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"playerPrefOptions" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
NSMutableDictionary *temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
self.backgroundSound = [[temp objectForKey:#"backgroundSounds"]boolValue];
self.soundEffects = [[temp objectForKey:#"soundEffects"]boolValue];
self.coach =[[temp objectForKey:#"coach"]boolValue];
self.numberOfDecks = [[temp objectForKey:#"numberOfDecks"]intValue];
}
-(void)writeOptionsToFile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSMutableDictionary *infoDict = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSNumber *moshe = [NSNumber numberWithInt:self.numberOfDecks];
[infoDict setObject: moshe forKey:#"numberOfDecks"];
[infoDict setObject:[NSNumber numberWithBool:self.coach] forKey:#"coach"];
[infoDict setObject:[NSNumber numberWithBool:self.backgroundSound] forKey:#"backgroundSounds"];
[infoDict setObject:[NSNumber numberWithBool:self.soundEffects] forKey:#"soundEffects"];
[infoDict writeToFile:path atomically:YES];
}
#end
so the property :
int numberOfDecks =[userOptionsController sharedOptionsController].numberOfDecks;
will return zero.
any ideas?
thanks.
Rather than use a plist for this content, it looks like NSUserDefaults is a more appropriate location.
Instead of shipping the app with a default plist file, instead just registerDefaults: with NSUserDefaults (often done in your app delegate application:didFinishLaunchingWithOptions:).
Then, whenever any changes are made just update NSUserDefaults and call synchronize to save the changes.
Try this and see what it does (what logs are output):
#implementation userOptionsController
+ (userOptionsController*)sharedOptionsController
{
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
- (id) init {
self = [super init];
if (self) {
}
return self;
}
-(void)readPlistFile
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"playerPrefOptions" ofType:#"plist"];
if (![fileManager copyItemAtPath:bundle toPath: path error:&error]) {
NSLog(#"ERROR - file couldn't be copied: %#", error);
}
}
NSMutableDictionary *temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
if (temp == nil) {
NSLog(#"ERROR - file couldn't be read");
}
self.backgroundSound = [[temp objectForKey:#"backgroundSounds"]boolValue];
self.soundEffects = [[temp objectForKey:#"soundEffects"]boolValue];
self.coach =[[temp objectForKey:#"coach"]boolValue];
self.numberOfDecks = [[temp objectForKey:#"numberOfDecks"]intValue];
}
-(void)writeOptionsToFile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"playerPrefOptions.plist"];
NSMutableDictionary *infoDict = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSNumber *moshe = [NSNumber numberWithInt:self.numberOfDecks];
[infoDict setObject: moshe forKey:#"numberOfDecks"];
[infoDict setObject:[NSNumber numberWithBool:self.coach] forKey:#"coach"];
[infoDict setObject:[NSNumber numberWithBool:self.backgroundSound] forKey:#"backgroundSounds"];
[infoDict setObject:[NSNumber numberWithBool:self.soundEffects] forKey:#"soundEffects"];
if (![infoDict writeToFile:path atomically:YES]) {
NSLog(#"ERROR - failed to write the new file (%#)", path);
} else {
NSLog(#"Completed write of:\n%#", infoDict);
}
}
#end

AVRecorder is delay when back from background mode?

i am using a lot the AVRecorder and AVPlayer.
i saw that they both , delay when i am back to my app ,after she was on background- then if for example i am trying to record , it takes 4 seconds till it starts .
in my code, i am preparing to record before i am recording, but when back to app, it doesnt help .
what can i do to improve it ?
this is done when app is open(at the start, not when back from background! )
-(void)prepareToRecord
{
NSArray *dirPaths;
NSString *docsDir;
NSString *sound=[NSString stringWithFormat:#"sound%d.caf",[memoryInstnace getNextFreePlace]];
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ;
docsDir = [dirPaths objectAtIndex:0];
currentSoundFilePath = [docsDir stringByAppendingPathComponent:sound];
NSURL *soundFileURL = [NSURL fileURLWithPath:currentSoundFilePath];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
NSError *error;
recorder = [[AVAudioRecorder alloc] initWithURL:soundFileURL settings:settings error:&error];
//to not having a delay befor record
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
if (recorder)
{
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
}
else
NSLog( #"error in recordings" );
}
thanks !
If another app had grabbed the control of the mic via starting an active AVAudioSession, then iOS will fade out control from that app and give it to you when you activate your session. This can take a second or two. Is this what is happening? or is something else slowing you down?

Saving data from Twitter feed parsed with JSON into Plist

I have a UITableView populated by a feed from searchtwitter.com. I also have a details table with an image and UILabel. I have all this working, but I want to add a UIButton on the detail page that will save the UIImage and the label into a property list. I'm very new to this; here is what I have so far (not working).
- (IBAction)SaveFriend:(id)sender
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path objectAtIndex:0];
NSString *plistPath = [documentDirectory stringByAppendingPathComponent:#"TwitterFriends.plist"];
NSDictionary * tweet = [[NSDictionary alloc]init];
NSString *text = [tweet objectForKey:#"from_user"];
NSString *user = [tweet objectForKey:#"from_user_name"];
personName.text = text;
personInfo.text = user;
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: personName, personInfo, nil] forKeys:[NSArray arrayWithObjects: #"Name", #"info", nil]];
NSString *error = nil;
// create NSData from dictionary
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistData)
{
// write plistData to our Data.plist file
[tweet writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
[error release];
}
}
Instead of using a .plist, try using an NSArray or NSMutableArray and then the writeToFile method. For example:
NSMutableArray *temp = [NSMutableArray new];
[temp addObject:image];
[temp addObject:label];
[temp writeToFile:[self saveFilePath:#"filename"] atomically:YES];
//Returns the saved information path
- (NSString*) saveFilePath: (NSString *) add
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:add];
return filename;
}

remove some signs from a txt file

i am saving a NSMutuablearray to a text file, he has NSNmbers in it .
when i open it (it sent to my emal) i see :
<integer>-13</integer>
<integer>-80</integer>
<integer>-15</integer>
i want ONLY the numbers without this <integer> sign.
there is a way of removing that? or put that numbers not in nsmutuable ?
code :
//add numbers
for(int i=0;i<417;i++)
{
int x= [globals sharedGlobals].bufBuf[i];
NSNumber* myNumber = [NSNumber numberWithInt: x];
[samples addObject:myNumber];
}
//create file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullFileName = [NSString stringWithFormat:#"%#/samplesTest.txt", documentsDirectory];
[samples writeToFile:fullFileName atomically:NO];
thanks.
You can prepare a string with your numbers, and save it to the file:
NSArray *numbers =
[NSArray arrayWithObjects:
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:2],
[NSNumber numberWithInt:3],
nil
];
NSString *res = [numbers componentsJoinedByString:#","];
NSError *error;
[res writeToFile:fullFileName atomically:NO encoding:NSUTF8StringEncoding
error:&error];