AVAudioRecorder cannot save to file - ios

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];
}

Related

Objective-C Record, Pause Record, Play the Paused Record, Continue Recording

I am trying to make a voice recorder which behaves as following
Record voice
Pause the voice
Listen to the recording
Continue Recording
I tried doing this:
Initialize the Recorder
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *dataPath = [cacheDir stringByAppendingPathComponent:#"/AudioFiles"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
{
NSError *error=nil;
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
}
NSArray *pathComponents = [NSArray arrayWithObjects:
dataPath,
[NSString stringWithFormat:#"%#.m4a",self.FileName],
nil];
NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
// Setup audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
// Define the recorder setting
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:22050.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithFloat:32000.0] forKey:AVEncoderBitRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:AVAudioBitRateStrategy_Variable forKey:AVEncoderBitRateStrategyKey];
// Initiate and prepare the recorder
recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL];
recorder.delegate = self;
recorder.meteringEnabled = YES;
[recorder prepareToRecord];
Record
[recorder record];
Pause the record
[recorder pause];
Play the record
playingSession = [AVAudioSession sharedInstance];
[playingSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[playingSession setActive: YES error:nil];
NSError *error = nil;
player = [[AVAudioPlayer alloc] initWithContentsOfURL:recorder.url error:&error];
NSLog(#"Error initializing player: %#", error);
[player setDelegate:self];
[player play];
So I get the following error
Error Domain=NSOSStatusErrorDomain Code=1685348671 "(null)"
Any idea how can I make this work?

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]);
}

How to name recorded file from AVAudioRecorder

I am making an iOS app where I need to record speech using AVAudioRecorder and then I want to rename the file. Right now, I can successfully record the speech but I don't know how to give the file a custom name. How can I give the recorded file a custom name? Any help is appreciated.
In the viewDidLoad:
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
#"MyAudioMemo.m4a",
nil];
outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
// Setup audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
// 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
recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:nil];
recorder.delegate = self;
recorder.meteringEnabled = YES;
[recorder prepareToRecord];
and all the other methods:
- (IBAction)recordPressed:(id)sender {
if (!recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
// Start recording
[recorder record];
NSLog(#"Recording...");
} else {
// Pause recording
[recorder pause];
NSLog(#"Paused...");
}
}
- (IBAction)stopPressed:(id)sender {
[recorder stop];
NSLog(#"Stopped...");
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setActive:NO error:nil];
}
You can simple move your file to another path, when you do that, you can specify a new name for the file, is the exactly same behavior of the mv command in shell.
There is a very simple snippet to you understand how to rename your file using move the FileManager moveItemAtPath:toPath:error method:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *docsDir = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *newPath = [docsDir stringByAppendingPathComponent:#"newname.m4a"];
// Try to move your file and the current path to newPath
if ([fileManager moveItemAtPath:currentPath toPath:newPath error:&error] != YES)
{
NSLog(#"Error: %#", [error localizedDescription]);
}
else
{
// File moved success
}

Why is AVAudioPlayer failing to initialise? With OSStatus error 1685348671?

I am recording audio in a view controller (a voice memo). This works. I can play back the recorded audio as long as the user doesn't dismiss the view controller.
However, if the user dismisses the view controller, and opens the view controller again, initialising the AVAudioPlayer fails with OSStatus error 1685348671.
I also tried to init the player with NSData:
NSData *data = [[NSData alloc] initWithContentsOfURL:_outputFileURL];
_player = [[AVAudioPlayer alloc] initWithData:data error:&error2];, but that would not work either
I have tried .caf, followed every tutorial, but somehow I can not make it work...
This error seems to refer to invalid file or so, though I am not sure. However if I download the app in the Organizer and open it on my Mac, I can play it, so the file itself is not corrupted.
Here is my record method:
- (IBAction)recordPauseTapped:(id)sender {
// Stop the audio player before recording
if (_player.playing) {
[_player stop];
}
if (!_recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
// Start recording
[_recorder record];
[recordPauseButton setTitle:#"Pause" forState:UIControlStateNormal];
} else {
// Pause recording
[_recorder pause];
[recordPauseButton setTitle:#"Aufnahme" forState:UIControlStateNormal];
}
[stopButton setEnabled:YES];
[playButton setEnabled:NO];
}
Recording works, and the file exists in the Documents directory.
Here is my play method, which works if the file was recorded immediately before, with without the user leaving the view controller:
- (IBAction)playTapped:(id)sender {
if (!_recorder.recording){
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setActive:YES error:nil];
NSError *error;
BOOL success = [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
if(!success)
{
NSLog(#"error doing outputaudioportoverride - %#", [error localizedDescription]);
}
NSError *error2;
NSLog(#"_outputFileURL: %#", _outputFileURL);
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:_outputFileURL error:&error2];
if (error2) {
NSLog(#"error initialising player - %#", [error2 localizedDescription]);
}
[_player setDelegate:self];
[_player play];
}
}
And here is my viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.translucent = NO;
[stopButton setEnabled:NO];
// Set the audio file
if ([_audioFileName isEqualToString:#""]) {
NSString *guid = [[NSUUID new] UUIDString];
_audioFileName = [NSString stringWithFormat:#"audio-%#.m4a", guid];
[playButton setEnabled:NO];
} else {
[playButton setEnabled:YES];
}
NSLog(#"_audioFileName: %#", _audioFileName);
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
_audioFileName,
nil];
_outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
// Setup audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[session setActive:YES error:nil];
// 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
_recorder = [[AVAudioRecorder alloc] initWithURL:_outputFileURL settings:recordSetting error:nil];
_recorder.delegate = self;
_recorder.meteringEnabled = YES;
[_recorder prepareToRecord];
}
Your problem is that you have [_recorder prepareToRecord]; into the viewLoad, which means that
it will be overwritten each time that you load the view controller.
If you don't wish this behaviour you should remove this line and put it at the beginning of
recordPauseTapped for example.
That should fix your issues.

Recorder delegate method not called

NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
#"MyAudioMemo.m4a",
nil];
NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
// Setup audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
// 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
recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL];
recorder.delegate = self;
recorder.meteringEnabled = YES;
[recorder prepareToRecord];
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
//Start the actual Recording
[recorder record];
[recorder updateMeters];
level = [recorder peakPowerForChannel:0];
NSLog(#"%f",level);
i have used this code in viewDidload() method to record a sound sound get in level.
i want to call the deleget method when device get the sound.
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
NSLog(#"Level is %f",level);
}
this method not called.
i am setting recorder delegate in .h file but not called this method why this is happening.
help me to do this.
Thanks in advance.
Are you actually storing the AVAudioRecorder instance somewhere? If you are not then it is likely deallocated by the time the above code finishes.
Try this
-(void)initialiceAudio{
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
#"MyAudioMemo.m4a",
nil];
NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
// Define the recorder setting
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:5000.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
// Initiate and prepare the recorder
recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL];
recorder.delegate = self;
recorder.meteringEnabled = YES;
[player setVolume: 1.0];
[recorder prepareToRecord];
}
-(IBAction)record:(id)sender {
if (!recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
recordBtn.selected=YES;
tabBtn.selected = YES;
tabBtn.userInteractionEnabled = NO;
// Start recording
[recorder record];
} else {
}
}
-(void) audioRecorderDidFinishRecording:(AVAudioRecorder *)avrecorder successfully:(BOOL)flag{
recorder = nil;
player = nil;
spinnerView = nil;
UploadAudioViewController *upload = [[UploadAudioViewController alloc]initWithNibName:#"UploadAudioViewController" bundle:nil];
NSLog(#"recorder url----%#",recorderurl);
upload.audioURL = recorderurl;
[self.navigationController pushViewController:upload animated:YES];
}
and make sure - you used AVAudioRecorderDelegate and AVAudioPlayerDelegate

Resources