AVAudioRecorder stopped working on iPad - ios

I have an app that was published for IOS9: a relatively minor feature is the ability to record small sound segments. While testing a similar feature on a new app, I found that the same code did not work on an iPad running iOS10, although it works on the simulator. On the iPad, audio metering gives a steady -120dB, and audioRecorderDidFinishRecording is never called. There are no logged messages. Both the published app and the new app do not work on the iPad.
The code looks like this:
- (void) record: (int) record_time {
record_sound = self;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
if(err){
NSLog(#"audioSession: %# %ld %#", [err domain], (long)[err code], [[err userInfo] description]);
return;
}
[audioSession setActive:YES error:&err];
err = nil;
if(err){
NSLog(#"audioSession: %# %ld %#", [err domain], (long)[err code], [[err userInfo] description]);
return;
}
NSMutableDictionary * recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
// Create a new file
NSString * recorderFilePath = [Recorder getRecordFilename];
NSFileManager * fileManager = [NSFileManager defaultManager];
NSError * error = nil;
[fileManager createDirectoryAtPath:[recorderFilePath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:&error]; //Create folder
NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
err = nil;
recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err];
if(!recorder){
NSLog(#"recorder: %# %ld %#", [err domain], (long)[err code], [[err userInfo] description]);
return;
}
//prepare to record
[recorder setDelegate:self];
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
// start recording
[recorder recordForDuration:(NSTimeInterval) record_time];
recordEndTime = [[NSDate date] dateByAddingTimeInterval: (NSTimeInterval) (record_time + 0.5)];
}

I switched off the iPad and restarted it, and everything started working again. Something must have got locked up inside the AVAudioRecorder mechanism.

Related

AVAudioRecorder in iOS 9 Not working

I'm using AVAudioRecorder to record a audio file. The code I'm using works perfectly fine in iOS 8 and below but since the latest update of iOS 9 the recording seems to have stopped working.
I tried logging the properties of AVAudioRecorder object and even after calling the "record" function in AVAudioRecorder the isRecording is showing as NO and when the "stop" function is called i get the call back in the delegate
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag; with success flag as NO
audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
if(err){
NSLog(#"audioSession: %# %ld %#", [err domain], (long)[err code], [[err userInfo] description]);
return;
}
[audioSession setActive:YES error:&err];
recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVEncoderBitRateKey];
[recordSetting setValue :[NSNumber numberWithInt:8] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
[recordSetting setValue :[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
recorderFilePath = [NSString stringWithFormat:#"%#/%#.m4a", DOCUMENTS_FOLDER,#"sample"];
NSLog(#"RecorderFilePath : %#",recorderFilePath);
NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
err = nil;
recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err];
//prepare to record
[recorder setDelegate:self];
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
BOOL audioHWAvailable = audioSession.inputAvailable;
[recorder record];
Please advise if i'm doing something wrong in the code.
Try this:
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryRecord error:nil];
// Define the recorder setting
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey, [NSNumber numberWithFloat:44100.0], AVSampleRateKey, [NSNumber numberWithInt: 2], AVNumberOfChannelsKey,nil];
// [recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
// Initiate and prepare the recorder
if (recorderHelium)
{
recorderHelium = nil;
}
recorderHelium = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:recordedAudioFilePath] settings:recordSetting error:nil];
recorderHelium.delegate = self;
recorderHelium.meteringEnabled = YES;
[recorderHelium prepareToRecord];
[recorderHelium record];
And also import and include these files:
#import <AudioToolbox/AudioServices.h>
#include <AudioToolbox/AudioToolbox.h>

Audio processing in iOS to get volume and pitch

I'm attempting to create a realtime audio analyzer on iOS7. What I'm looking to get is volume and pitch from the native microphone on an iPod Touch Gen 5, and write to a CSV along with a timestamp. I'd like to break it up into 7 channels, and sample at 8Hz. I've looked at a bunch of documentation and code samples, but can't get anything to work.
I'm trying to start something simple now from scratch, but it seems to me that there is nothing outlining how I can achieve what I mentioned above.
Most recently I've tried AVAudioSessionCategoryAudioProcessing hoping to be able to use it for signal processing, but the Audio Session docs suggest that only automated signal processing can be done...and only in voice or video chat modes.
- (void)analyzeAudio
{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
audioUnit = (AudioUnit*)malloc(sizeof(AudioUnit));
NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
if (!success)
{
NSLog(#"AudioSession could not init");
}
[audioSession setCategory:AVAudioSessionCategoryAudioProcessing error:nil];
[audioSession setActive:YES error:nil];
}
Is there a simple way with Audio Session to get what I'm looking for?
Found out that I can use the AVAudioRecorder method updateMeters on a timer to get the peakPowerForChannel: value at some interval.
- (void)recordAudio
{
_audioSession = [AVAudioSession sharedInstance];
NSError *error;
[_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
[_audioSession setActive:YES error:&error];
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[settings setValue:[NSNumber numberWithFloat:8000.0] forKey:AVSampleRateKey];
[settings setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
[settings setValue:[NSNumber numberWithFloat:16000] forKey:AVEncoderBitRateKey];
[settings setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityForVBRKey];
NSArray *dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [dirPath objectAtIndex:0];
long currentTime = [[NSDate date] timeIntervalSince1970];
NSString *filePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"audio_%ld.aac", currentTime]];
NSURL *audioFileURL = [NSURL fileURLWithPath:filePath];
_audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioFileURL settings:settings error:&error];
if (error)
{
NSLog(#"audio record error: %#", [error localizedDescription]);
} else {
[_audioRecorder prepareToRecord];
_audioRecorder.meteringEnabled = YES;
[_audioRecorder record];
[self addTextToLog:#"Recording Audio"];
self.audioTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(updateAudioMeters) userInfo:nil repeats:YES];
}
}
- (void)updateAudioMeters
{
[_audioRecorder updateMeters];
NSLog(#"pkPwr: %f", [_audioRecorder peakPowerForChannel:0]);
}

Record the Background Playing song in iOS7

I am Trying to record the background Playing song using AVAudioRecorder. My code is as Below:
//Initialize audio session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
//Override record to mix with other app audio, background audio not silenced on record
UInt32 allowMixing = true;
OSStatus propertySetError = 0;
propertySetError = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(allowMixing), &allowMixing);
NSLog(#"Mixing: %lx", propertySetError); // This should be 0 or there was an issue somewhere
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
[[AVAudioSession sharedInstance] setActive:YES error:nil];
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] initWithCapacity:0];
if (recordEncoding == ENC_PCM) {
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
} else {
NSNumber *formatObject;
switch (recordEncoding) {
case ENC_AAC:
formatObject = [NSNumber numberWithInt:kAudioFormatMPEG4AAC];
break;
case ENC_ALAC:
formatObject = [NSNumber numberWithInt:kAudioFormatAppleLossless];
break;
case ENC_IMA4:
formatObject = [NSNumber numberWithInt:kAudioFormatAppleIMA4];
break;
case ENC_ILBC:
formatObject = [NSNumber numberWithInt:kAudioFormatiLBC];
break;
case ENC_ULAW:
formatObject = [NSNumber numberWithInt:kAudioFormatULaw];
break;
default:
formatObject = [NSNumber numberWithInt:kAudioFormatAppleIMA4];
break;
}
[recordSetting setValue:formatObject forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:[NSNumber numberWithInt:12800] forKey:AVEncoderBitRateKey];
[recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *recDir = [paths objectAtIndex:0];
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/recordTest.caf", recDir]];
NSError *error = nil;
audioRecorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&error];
if (!audioRecorder) {
NSLog(#"audioRecorder: %# %d %#", [error domain], [error code], [[error userInfo] description]);
return;
}
// audioRecorder.meteringEnabled = YES;
//
BOOL audioHWAvailable = audioSession.inputIsAvailable;
if (! audioHWAvailable) {
UIAlertView *cantRecordAlert =
[[UIAlertView alloc] initWithTitle: #"Warning"
message: #"Audio input hardware not available"
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[cantRecordAlert show];
[cantRecordAlert release];
return;
}
if ([audioRecorder prepareToRecord]) {
[audioRecorder record];
NSLog(#"recording");
} else {
// int errorCode = CFSwapInt32HostToBig ([error code]);
// NSLog(#"Error: %# [%4.4s])" , [error localizedDescription], (char*)&errorCode);
NSLog(#"recorder: %# %d %#", [error domain], [error code], [[error userInfo] description]);
}
but here the session Depreciated in ios7 warning occurs at:
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
can any one Help me to remove this warning without Changing the Functionality

AVAudioRecorder cannot save to file

I am trying to create a Simple AVAudioRecorder wrapper.
As far as I know, after [recorder stop], the audio file will save to the path automatically.
However in my class, it won't save to the path.
Console log:
2014-01-23 15:34:55.754 AudioRecorderDemo[4496:60b] contentURL: file:///var/mobile/Applications/C20F5A5A-14A9-45D4-80A3-999976AC4055/Documents/MyAudio-someDemo.m4a
2014-01-23 15:34:55.756 AudioRecorderDemo[4496:60b] fileExist? : no
Thanks for helping.
The class file on GitHub:
AudioRecorder.h
AudioRecorder.m
// Code when start:
-(void)prepare
{
NSError *error;
// Setup audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if (error)
{
NSLog(#"Error in AVAudioSession: %#", error.description);
return;
}
// Define the recorder setting
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
// Initiate and prepare the recorder
NSURL *contentURL = [STLAudioRecorder contentsOfURLFromUniqueID:self.uniqueID fileNameFormat:self.fileNameFormat];
self.recorder = [[AVAudioRecorder alloc] initWithURL:contentURL settings:recordSetting error:&error];
if (error)
{
NSLog(#"Error in AVAudioRecorder: %#", error.description);
return;
}
self.recorder.delegate = self;
self.recorder.meteringEnabled = YES;
[self.recorder prepareToRecord];
}
-(void)startRecording
{
if (!self.recorder) [self prepare];
if (!self.recorder.isRecording)
{
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
[self.recorder record];
NSLog(#"startRecording, url: %#", self.recorder.url.absoluteString);
}
}
// Code when stop:
-(void)stopRecording
{
if (self.recorder && self.recorder.isRecording)
{
NSError *error;
[self.recorder stop];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setActive:NO error:&error];
if (error) NSLog(#"Error in stopRecording: %#", error.description);
}
else
{
NSLog(#"stopRecording: !(self.recorder && self.recorder.isRecording)");
}
}
Try this one,
-(void) initAudioSession {
AVAudioSession * audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];
[audioSession setActive:YES error: &error];
}
-(void) recordStart {
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
tempFilePath = [NSURL fileURLWithPath:[docsDir stringByAppendingPathComponent:[NSString stringWithFormat: #"%#.%#",audioFileName, #"caf"]]];
NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
stringByAppendingPathComponent: [NSString stringWithFormat: #"%#.%#",audioFileName, #"caf"]]];
recorder = [[ AVAudioRecorder alloc] initWithURL:tempFilePath settings:recordSetting error:&error];
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder record];
}
-(void) stopRecording{
[recorder stop];
}
-(void) playRecord{
avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:tempFilePath error:&error];
[avPlayer prepareToPlay];
[avPlayer play];
}

AVAudioRecord prepareRecord & Record returns NO

I'm currently working on a game project, which supports audio recording. this program is based on WiEngine , a game engine kinda like cocos2d-x.
here's the thing , I've tried many ways , but EVERY time I called [myRecorder Record] it always returns NO. then I called PrepareRecord explicitly , it returns No either.
here's the code how I init the Recorder
- (void)initRecorder
{
if(self.myRecoder!=nil)
{
[self.myRecoder release];
self.myRecoder=nil;
}
NSDictionary *myRecorderParam = [[NSDictionary alloc]initWithObjectsAndKeys:
[NSNumber numberWithFloat:44100.0],AVSampleRateKey,
[NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
[NSNumber numberWithInt:1],AVNumberOfChannelsKey,
[NSNumber numberWithInt:AVAudioQualityMedium],AVEncoderAudioQualityKey,
nil];
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DocumentPath = [pathArray objectAtIndex:0];
DocumentPath = [DocumentPath stringByAppendingString:#"/luyin.wav"];
self.myRecoder = [[AVAudioRecorder alloc]initWithURL:[NSURL URLWithString:DocumentPath]
settings:myRecorderParam
error:nil];
[self.myRecoder setDelegate:self];
}
and I called Record like this
- (void)beginRecord
{
NSLog(#"begin record");
// AVAudioSession *audioSession = [AVAudioSession sharedInstance];
// NSError *err = nil;
// [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
// if(err){
// NSLog(#"audioSession: %# %d %#", [err domain], [err code], [[err userInfo] description]);
// return;
// }
// err = nil;
// [audioSession setActive:YES error:&err];
// if(err){
// NSLog(#"audioSession: %# %d %#", [err domain], [err code], [[err userInfo] description]);
// return;
// }
if(self.myRecoder==nil)
{
NSLog(#"recoder null");
}
BOOL resultPre = [[self myRecoder] prepareToRecord];
if(resultPre)
{
NSLog(#" record pre yes ");
}
else
{
NSLog(#" record pre no ");
}
BOOL result = [[self myRecoder] record];
if(result)
{
NSLog(#" record yes ");
}
else
{
NSLog(#" record no ");
}
}
according to the NSLogs , I’m sure that the initialization does not seem to fail.
I also tried to init an AudioSession , but it doesn't work either
PLEASE HELP
is it AVAudioRecorder ?
AVAudioPlayer is use for play Record
Like this:
NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:[freq.text floatValue]] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: [value.text intValue]] forKey:AVNumberOfChannelsKey];
recordedTmpFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: #"%.0f.%#", [NSDate timeIntervalSinceReferenceDate] * 1000.0, #"caf"]]];
NSLog(#"Using File called: %#",recordedTmpFile);
recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];

Resources