5

I have made 2 iPhone apps which can record audio and save it to a file and play it back again.

One of them uses AVAudiorecorder and AVAudioplayer. The second one is Apple's SpeakHere example with Audio Queues.

Both run on Simulater as well as the Device.

BUT when I restart either app the recorded file is not found!!! I've tried all possible suggestions found on stackoverflow but it still doesnt work!

This is what I use to save the file:

NSArray *dirPaths; 
NSString *docsDir; 

dirPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); 
docsDir = [dirPaths objectAtIndex:0]; 

NSString *soundFilePath = [docsDir stringByAppendingPathComponent:@"sound1.caf"]; 
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
Pieter
  • 17,435
  • 8
  • 50
  • 89
es1
  • 1,231
  • 3
  • 14
  • 27
  • Where (what directory) are you storing the files?? – Hot Licks Feb 25 '13 at 02:14
  • The Documents directory like this: – es1 Feb 25 '13 at 02:19
  • NSArray *dirPaths; NSString *docsDir; dirPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); docsDir = [dirPaths objectAtIndex:[globals sharedGlobals].folderCounter]; NSString *soundFilePath = [docsDir stringByAppendingPathComponent:@"sound1.caf"]; NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath]; – es1 Feb 25 '13 at 02:19
  • 1
    Have you NSLogged the file path string to make sure it's what you think it is? – Hot Licks Feb 25 '13 at 02:21
  • Nope What should it be? – es1 Feb 25 '13 at 02:23
  • 2
    Please edit your original question to add the code that you put in the comment. MIT is nearly impossible to read this way, and many people will miss it as a comment. – lnafziger Feb 25 '13 at 02:28
  • What do you think it should be? – Hot Licks Feb 25 '13 at 02:39

1 Answers1

16

Ok I finally solved it. The problem was that I was setting up the AVAudioRecorder and file the path in the viewLoad of my ViewController.m overwriting existing files with the same name.

  1. After recording and saving the audio to file and stopping the app, I could find the file in Finder. (/Users/xxxxx/Library/Application Support/iPhone Simulator/6.0/Applications/0F107E80-27E3-4F7C-AB07-9465B575EDAB/Documents/sound1.caf)
  2. When I restarted the application the setup code for the recorder (from viewLoad) would just overwrite my old file called:

    sound1.caf

  3. with a new one. Same name but no content.

  4. The play back would just play an empty new file. --> No Sound obviously.


So here is what I did:

I used NSUserdefaults to save the path of the recorded file name to be retrieved later in my playBack method.


cleaned viewLoad in ViewController.m :

- (void)viewDidLoad
{

     AVAudioSession *audioSession = [AVAudioSession sharedInstance];

     [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

     [audioSession setActive:YES error:nil];

     [recorder setDelegate:self];

     [super viewDidLoad];
}

edited record in ViewController.m :

- (IBAction) record
{

    NSError *error;

    // Recording settings
    NSMutableDictionary *settings = [NSMutableDictionary dictionary];

    [settings setValue: [NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    [settings setValue: [NSNumber numberWithFloat:8000.0] forKey:AVSampleRateKey];
    [settings setValue: [NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
    [settings setValue: [NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    [settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
    [settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
    [settings setValue:  [NSNumber numberWithInt: AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];

    NSArray *searchPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath_ = [searchPaths objectAtIndex: 0];

    NSString *pathToSave = [documentPath_ stringByAppendingPathComponent:[self dateString]];

    // File URL
    NSURL *url = [NSURL fileURLWithPath:pathToSave];//FILEPATH];


    //Save recording path to preferences
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];


    [prefs setURL:url forKey:@"Test1"];
    [prefs synchronize];


    // Create recorder
    recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];

    [recorder prepareToRecord];

    [recorder record];
}

edited playback in ViewController.m:

-(IBAction)playBack
{

AVAudioSession *audioSession = [AVAudioSession sharedInstance];

[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];

[audioSession setActive:YES error:nil];


//Load recording path from preferences
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];


temporaryRecFile = [prefs URLForKey:@"Test1"];



player = [[AVAudioPlayer alloc] initWithContentsOfURL:temporaryRecFile error:nil];



player.delegate = self;


[player setNumberOfLoops:0];
player.volume = 1;


[player prepareToPlay];

[player play];


}

and added a new dateString method to ViewController.m:

- (NSString *) dateString
{
    // return a formatted string for a file name
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"ddMMMYY_hhmmssa";
    return [[formatter stringFromDate:[NSDate date]] stringByAppendingString:@".aif"];
}

Now it can load the last recorded file via NSUserdefaults loading it with:

    //Load recording path from preferences
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];


temporaryRecFile = [prefs URLForKey:@"Test1"];



player = [[AVAudioPlayer alloc] initWithContentsOfURL:temporaryRecFile error:nil];

in (IBAction)playBack. temporaryRecFile is a NSURL variable in my ViewController class.

declared as following ViewController.h :

@interface SoundRecViewController : UIViewController <AVAudioSessionDelegate,AVAudioRecorderDelegate, AVAudioPlayerDelegate>
{
......
......
    NSURL *temporaryRecFile;

    AVAudioRecorder *recorder;
    AVAudioPlayer *player;

}
......
......
@end
es1
  • 1,231
  • 3
  • 14
  • 27
  • 1
    This answer is nearly perfect - it didn't work for me until I set the audiosession mode to record in your record method - but then it worked perfectly on my device – Jeff Grimes Feb 24 '14 at 17:10
  • 2
    @user2105811 You sir are a legend. I have been trying to get this functionality to work in my app for ages but I could not :( Thank you so much man, really helpful. – Supertecnoboff Feb 16 '15 at 07:23
  • 2
    Thank you so much. I've wasted three days searching for the cause of the problem. I did many useless tests to understand why the sound recording is erased. – Markus Apr 22 '16 at 22:05
  • 2
    The truth is that it is very difficult to imagine that the creation of the recorder [AVAudioPlayer alloc] initWithContentsOfURL erased the contents of the previous file. Unbelievable! And I lost more than 3 days trying to understand what was going on! Thank you so much again! – Markus Apr 22 '16 at 22:10
  • Why did you use NSUserDefaults? Why not just save the path in a variable? – AlvinfromDiaspar Nov 08 '16 at 20:54
  • 1
    @AlvinfromDiaspar because values saved in variables are lost once you kill the app and reopen it. – rak appdev Apr 11 '17 at 21:44
  • please provide swift version – Yash R Oct 27 '17 at 07:33
  • This answer is a life saver!! Thank you! @Swift users -- there is no "NSUserDefaults" any more. Use "UserDefaults.standard" instead. – variadics Oct 05 '18 at 21:43