AVAudioRecorder stops working when writing to /dev/null on iPhone 5s with iOS 7 - ios7

I have an app that monitors the background audio level without recording to a file. I use the trick of writing to /dev/null to accomplish this.
This code has worked on the iPhone 3GS with iOS 6, iPhone 4 with iOS 6 and iOS 7, and in the simulator with iOS 7 and iPhone Retina (4-inch 64-bit).
When I try it on a real iPhone 5s, however, the recorder seems to capture audio for a moment, and then silently dies.
This is the code:
// Inititalize the audio
NSURL *url = [NSURL fileURLWithPath:#"/dev/null"];
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:url settings:settings error:&error];
if (recorder) {
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: #selector(levelTimerCallback:) userInfo: nil repeats: YES];
// peakLevelTimer = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: #selector(peakLevelTimerCallback:) userInfo: nil repeats: YES];
} else {
NSLog(#"There was an error setting up the recorder.");
NSLog([error description]);
}
Any ideas what might be going on?
Could anyone suggest a workaround? Writing to a real file works, but I don't want to fill up any space on the device just to monitor audio. Is there a way to write to a small file buffer that just evaporates into thin air? Implement my own /dev/null, effectively?

I had the same issue when testing one of my apps for iOS 7.
I got around the absence of /dev/null by creating an initial file that I then deleted a number of seconds after the recording started. The recording still continued to work for my application and there was no data file being stored.
- (void)startRecording
{
// New recording path.
NSString *recorderFilePath = [NSString stringWithFormat:#"%#/%#.caf", [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"], #"cache"];
NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
AVAudioRecorder recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err];
if([recorder prepareToRecord])
{
[recorder record];
NSTimer deleteFileTimer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:#selector(removeRecordingFile) userInfo:nil repeats:NO];
}
}
- (void)removeRecordingFile
{
// Remove the data file from the recording.
NSString *recorderFilePath = [NSString stringWithFormat:#"%#/%#.caf", [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"], #"cache"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
BOOL success = [fileManager removeItemAtPath:recorderFilePath error:&error];
if(success)
{
NSLog(#"Deleted recording file");
}
else
{
NSLog(#"Could not delete file -:%# ",[error localizedDescription]);
}
}

You need to change:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
to:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:NULL];

Related

AVAudioRecorder woes on MacOSX

I'm attempting to use AVAudioRecorder on MacOSX 10.14.x to get audio level readings of an input source -- in this case, the microphone. As this isn't on iOS, the use of AVAudioSession does not apply. I did enable the microphone in the SandBox settings, as well as double-checking everything in Audio Midi Setup app, with the microphone set to 2ch 24-bit Integer 44.1kHz. I've removed all error checking, but everything should be fine (eg. apparent success on all calls to the recorder object). Also, I tried this on another 10.14.x machine with the same result.
When I run this, all I get is values of -120.0 for both the average and peak power in my callback, even if there is audio.
Any idea what I'm doing wrong?
Note: When I initiate [recorder prepareToRecord], I receive these two error messages:
no saved enable hardware sample rate converter preference found
ca_debug_string: inPropertyData == NULL
AVAudioRecorder *recorder; // instance variable
NSTimer *levelTimer; // instance variable
NSURL *url = [NSURL fileURLWithPath: #"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.00], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityHigh], AVEncoderAudioQualityKey,
nil];
NSError *error = nil;
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval:0.03
target:self
selector:#selector(levelTimerCallback:)
userInfo:nil
repeats:YES];
- (void)levelTimerCallback:(NSTimer *)timer {
[recorder updateMeters];
float peakPower = [recorder peakPowerForChannel:0];
float avgPower = [recorder averagePowerForChannel:0];
}

AVAudioRecorder not Working in iOS8

I have implemented AVAudiorecorder for recording and playing voice for 10 secs.it is working fine with iOS 7.But when i run the same code on ios8 ,it is not working please help.
Here is a source Code.
//Below is my code for recording and Playing.
//Here is the Recording code which records sound for 10 secs
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
if(err){
return;
}
[audioSession setActive:YES error:&err];
err = nil;
// Setup audio recording
recordSetting = #{AVFormatIDKey: #(kAudioFormatMPEG4AAC),
AVEncoderAudioQualityKey: #(AVAudioQualityLow),
AVNumberOfChannelsKey: #1,
AVSampleRateKey: #22050.0f};
recorderFilePath = [NSString stringWithFormat:#"%#/MySound.wave", DOCUMENTS_FOLDER];
NSData *postData = [NSData dataWithContentsOfFile:recorderFilePath];
NSURL *url = [NSURL fileURLWithPath:recorderFilePath];err = nil;
NSData *audioData = [NSData dataWithContentsOfFile:[url path] options: 0 error:&err];
if(audioData)
{NSFileManager *fm = [NSFileManager defaultManager];
[fm removeItemAtPath:[url path] error:&err];}
err = nil;
recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err];
//prepare to record
[recorder setDelegate:self];
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
//Please help me out and tell if i have to add/modify something because it is working in ios7.
It seems that there isn't nothing wrong in your code snippet.
I use approximately the same code to make a registration on my iPhone, too.
The only difference with my code is a call to
[recorder recordForDuration:(NSTimeInterval) 10];
in order to start the registration for 10 seconds

AVURLAsset duration zero in iOS7

I am trying to play video on iPad by using this code. It is okay for iOS 6. But, in iOS 7, its self.asset.duration.value is zero. I would like to know how to do.
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVURLAsset *assetToCombine = [AVURLAsset URLAssetWithURL:url options:options];//original
[assetToCombine retain];
NSArray *requestedKey=[NSArray arrayWithObjects:#"duration", nil];
[assetToCombine loadValuesAsynchronouslyForKeys:requestedKey completionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
//do nth here
NSLog(#"dispatch_async assetToCombine.duration.value is %lld.",assetToCombine.duration.value);
});
}];
NSLog(#"assetToCombine.duration.value is %lld.",assetToCombine.duration.value);

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?

How to pitch the recorded sound

1) I want to make an Iphone app like Talking Tom. I have downloaded the sample example from :--> https://github.com/zoul/Finch site. It plays fine with given audio file. But I want to play my recorded file with pitch effect. My problem is when I pass my recorded file (Recorded using AVAudioRecorder) the error comes like "Failed to read sound data." please help me why this error occurs. Is there any file format problem when recording file using AVAudioRecorded or any setting problem?
my Setting code is here....
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:#"sound.caf"];
soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt: AVAudioQualityMedium],AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],AVNumberOfChannelsKey,
[NSNumber numberWithFloat: 44100.0],AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithBool:YES],AVLinearPCMIsBigEndianKey,
nil];
NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc] initWithURL:soundFileURL settings:recordSettings error:&error];
if(error)
{
NSLog(#"error in AudioRecorder Initializing...: %#", [error localizedDescription]);
}
else
{
//audioRecorder.meteringEnabled = YES;
[audioRecorder prepareToRecord];
}
2)I found another example from http://dirac.dspdimension.com/Dirac3_Technology_Home_Page/Dirac3_Technology.html site.
In this example I can Play my recorded file but too much disturbance comes.
The sound is continuously playing after playing and not able to stop it. Sometimes app crashes when pitch changed.In this example they are using "libDIRAC_iOS4-fat.a" library. so can we use this library ? And how can we stop sound playing.
Is there any way to do this using easily ?
Thanks in advance.