How to name recorded file from AVAudioRecorder - ios

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
}

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?

AVAudioRecorder recorded m4a won't play

I have recording application and it is working fine for m4a files. Now issue is only arise when I close application without stopping AVAudioRecorder.
Here is my code for record function:
- (IBAction)recordTapped:(id)sender {
// Set the audio file
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:AVAudioSessionCategoryRecord 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];
[session setActive:YES error:nil];
// Start recording
[recorder record];
}
And this is my stop recorder function:
- (IBAction)stopTapped:(id)sender {
[recorder stop];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setActive:NO error:nil];
}
So now when I start recording and after some recording, I tap on stop button and then try to play recording. It works fine.
Now if I start recording and then without stopping I double tap on home button and from app list I closes app. Then I restart app and try to play that previously recorded file, It won't work.
So is there any method to resolve this issue?

iPhone - Problems Saving Audio After Recording

I a button that records audio when isNotRecording is false and plays audio when isNotRecording is true. Here is my code in the viewDidLoad function:
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];
Here is my code to play the sound or record:
if (isNotRecording==NO){
if (player.playing) {
[player stop];
}
if (!recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
// Start recording
[recorder record];
}
}
else{
if (!recorder.recording){
player = [[AVAudioPlayer alloc] initWithContentsOfURL:recorder.url error:nil];
[player setDelegate:self];
[player play];
}
}
And here is my code to stop the playing/recording:
[recorder stop];
[player stop];
Now, everything works almost perfectly (i.e. I can record and play sounds fine). However, there are two issues. The major one is that after I close out the app and try to play the sound, it does not have a sound to play. I want it to play the previous recording. That is my main issue, but it would also be great if I could reduce the lag from when I press the button and the sound plays. Sometimes, if I press the button and release it very fast, no sound plays at all. Any suggestions are greatly appreciated. However, again, the main issue I need fixed is that the recording doesn't save after I close out the app.
I think what's happening is that when you initialize your AVAudioRecorder when the view loads then that will delete any existing file at the target location, irrespective of whether you start recording at that stage. So I think that's how the file is going missing.
Simplest may be just not to call [recorder prepareToRecord]; when you do, as I suspect that's when your recording is getting deleted.
Or you might want to use a temporary file while recording and move it to the final location when you're notified that the recording is finished, in order to avoid that issue. Code is something like:
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
#"MyAudioMemoTemp.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];
if (isNotRecording==NO){
if (player.playing) {
[player stop];
}
if (!recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
// Start recording
[recorder record];
}
}
else{
if (!recorder.recording){
NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
#"MyAudioMemo.m4a",
nil];
NSURL *inputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:inputFileURL error:nil];
[player setDelegate:self];
[player play];
}
}
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder
                            successfully:(BOOL)flag
{
if (successfully) {
// Copy temp file used during recording to replace that used when playing
//
pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
#"MyAudioMemo.m4a",
nil];
NSURL *targetFileURL = [NSURL fileURLWithPathComponents:pathComponents];
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtURL:targetFileURL error:&error];
error = nil;
[[NSFileManager defaultManager] copyItemAtURL:recorder.url toURL:targetFileURL error:&error];
}
}

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

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

Resources