AVAudioRecorder

I’m having a hard time trying to use the ios AVAudioRecorder (basically due to Xojo declaration syntax, objective-c sources are available on the net). Any suggestion or example to use as a reference?

I’m a using as a reference the following

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioRecorder_ClassReference/#//apple_ref/occ/instm/AVAudioRecorder/record

PREPARATION CODE

  • (void)viewDidLoad
    {
    [super viewDidLoad];

    // Disable Stop/Play button when application launches
    // [stopButton setEnabled:NO];
    // [playButton setEnabled:NO];

    // Set the audio file
    NSArray *pathComponents = [NSArray arrayWithObjects:
    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
    @“myaudiodemo.caf”,
    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: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];

    // Initiate and prepare the recorder
    recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL];
    recorder.delegate = self;
    recorder.meteringEnabled = YES;
    [recorder prepareToRecord];
    }

RECORDING CODE

  • (IBAction)recordPauseTapped:(id)sender {
    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:@"Record" forState:UIControlStateNormal];
    

    }

    // [stopButton setEnabled:YES];
    // [playButton setEnabled:NO];
    }

Currently not included in iOSLib but in the SpriteKit addition (but still undocumented) is AVPlayer. You’ll find NSNumber and NSURL too. Maybe that helps to create own classes? If not, just let me know.

Daniel, I created the AVAudioRecorder class in my AVFoundation classes. I will be posting them tomorrow. Coincidentally I found and implemented the example in your first link to show how to use the class.

Thanks Jason! I’ll test it tomorrow …

iOSKit updated with AVAudioRecorder and other classes!

https://github.com/kingj5/iOSKit

I’ve made some preliminary tests:

a) The ioskit project loads without any problem (just some warnings about the Launch Images location that can be resolved by indicating the correct location)

b) I’ve loaded the following modules in my AVAudioRecorder test project (using export/import functions):

  • Foundation
  • AVFoundation
  • UIKit
  • QuartzCore
  • Extensions

and the RecordPlayAudioView iosView

c) In the ios simulator the usage of the Record/Pause/Stop buttons do not raise any problem (even if there is no internal mic in the development mac): I’ll try later with a complete enviroment …

Hi Daniel, many of the classes will only work when you deploy your app to a iPhone/iPad (but should still compile and run in the simulator, although sometimes with an error.)

Thanks Jason … in any case the file MyRecordingDemo.m4a was correctly generated in the iOS simulator app document folder (~ /Library/Developer/CoreSimulator/Devices/ID_simulator/data/Containers/Data/Application/ID_app/Documents) and it is playable (with iTunes) and of course has no mic signal !!!

I have to say I’m slightly surprised by that, but that is pretty cool!

Hi Jason!

Tested AVAudioRecorder with an external microphone in ios simulator: it works like a charm!

NOTE on RecordPlayAudioView iosView example : after recording, a click on the Play button starts an audio session of the recorded file, if you click it again (while playing the recorded file) it starts a second session of the recorded file (you can hear both sessions overlapped!)

I’m using AVAudioRecoder to record sounds (in linear PCM, 16 bit, mono) from the device microphone. On the Mac Simulator and Ipad (64bit) ios 8.2 everything is fine, but on iPhone 5 (32bit) ios 8.3 something is not working properly. The sound is generated but if I check the audio data loading it with a BinaryStream object the sound level is low, max 0x1FF (I copy the stream in a memory block and read 2 bytes per sample using the data.short property (mb.data.Short(startpoint)). I do not know if the problem is in the PCM file format generation or in the Stream reading. I suspect that the problem is linked to a 64/32 bit issue (data.Short?). Any ideas?

Some tests on different iOS suggest that the problem is linked to iOS 8.3 (all devices work properly with lower iOS versions). I suspect that a default AVaudio parameter that you do not need to specify with iOS 8.2 is changed in iOS 8.3 …

Interesting, everything works just fine for me in the iOSKit example project on my iPhone 6 running 8.4 and the simulator running iOS 9.0, although I have no way to test on iOS 8.3. Is it possible the data is not formatted exactly how you expect it? I don’t think that you should have to read a different bit size value on each architecture since the format should be transferrable to a different architecture with no changes, but maybe I’m wrong? (I don’t know anything about the PCM format to be honest). Maybe you should try to make a recording, then download the file to you computer and inspect it to see if there are any differences from what you expect? You probably already did that but its just a suggestion.

Hi Jason! I’am analyzing the files with HexMiner … comparing the one generated on iPhone 5 with iOS 8.3 an the one generated on iPad with iOS 8.1 and the one generated on mini iPad 2 with iOS 8.2 … no difference in the file structure and the data in the linear PCM file looks fine (16bit: sequence of 2 bytes ranging from 0000 to FFFF). It looks like that the problem is in reading the file : I use the BinaryStream object and I copy the stream in a memory block and read 2 bytes per sample using the data.short property (mb.data.Short(startpoint)) … I should read a signed integer ranging from -32768 to +32767 and it works on other devices/iOS but not on iPhone5/iOS 8.3 … code example:

'read myfile
Dim myFile As FolderItem= SpecialFolder.Temporary.Child(“test.caf”)
Dim ReadStream As BinaryStream = BinaryStream.Open(myFile, BinaryStream.LockModes.Read)
'copy stream to block
Dim mylenght as integer
mylenght = ReadStream.Length
dim mb As New MemoryBlock(ReadStream.Read(mylenght))

'read a signed integer from mystartpoint (integer)
Dim myvalue as double
myvalue=mb.data.Short(mystartpoint)

Do you see the same results when testing in the simulator? I wonder if there is a problem with binary stream in 32bit?

  1. you should use uint os int16 instead of short ?
  2. does the endianness of the memoryblock matter in this ?
  3. does it work for some recordings but not others ?

Hi! Thank you for your help …

a) Jason: In the simulator (Xcode 6.2/Mavericks) everything is fine … I’ve also loaded iOS 9.0.2 on mini ipad 2 (64 bit) and everything is fine (it looks like a problem with binary stream or memoryblock in 32bit and iphone5/iOS8.3 …)

b) Norman: I’ve tried mb.data.int16 without success … endianess is littleendian (PCM data and memoryblock) … any recording done on iPhone5/iOS8.3 has the same issue if I try to read the data with the binary stream in the same enviroment (but if I read the file with a media player in the same or other enviroment I have no problems; and also no problems if a read the same file in mini iPad2/iOS8.2 or iPad2/iOS8.1 or mini iPad2/iOS9.0.2 with the binary stream)

I think I found the problem … iphone5 starts recording at a low volume and only after some time (about 100 ms) the final recording volume is reached … iPads start recording at the correct sound level almost immediately (in about 10 ms). So no bugs in BinaryStream or iOSKit … only a different behavior of the device!