0

So I am writing accelerometer values to a csv file. Sometimes it works and sometimes it doesn't. Typically when the accelerometer is on for over 5 seconds it crashes and I get the error.

Here is the code:

int recordbuttonstatus=0;
int playbuttonstatus=0;


int count;

NSString *dataStr;
NSString *dirName;
NSFileManager *filemgr;
NSString *audiofilename = @"Pneumonia_audio.wav";
NSString *audiofilepath;
NSString *csvfileName = @"accel.csv";
NSFileHandle *myHandle;


- (void)viewDidLoad {
    [super viewDidLoad];
    playbuttonimage.enabled=FALSE;
    NSArray *pathComponents = [NSArray arrayWithObjects:
                               [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],
                               audiofilename,
                               nil];
    NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];



    // Setup audio session
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

    // Define the recorder setting
    NSDictionary *recordSetting = [NSDictionary
                                   dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:AVAudioQualityMin],
                                   AVEncoderAudioQualityKey,
                                   [NSNumber numberWithInt:16],
                                   AVEncoderBitRateKey,
                                   [NSNumber numberWithInt: 1],
                                   AVNumberOfChannelsKey,
                                   [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                   [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
                                   nil];

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

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)recordbuttonaction:(id)sender {
    if (recordbuttonstatus==0){
    [recordbuttonimage setImage:[UIImage imageNamed:@"stoprecord.png"] forState:UIControlStateNormal];
        recordbuttonstatus=1;
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setActive:YES error:nil];

        // Start recording
        [recorder record];

        //Prepare writing to csv
        dirName = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
        filePath = [dirName stringByAppendingPathComponent: csvfileName];
        filemgr = [NSFileManager defaultManager];
        if ([filemgr fileExistsAtPath:filePath]) {
            NSLog(@"File %@ being overwritten...", csvfileName);
            NSError *error = nil;
            [filemgr removeItemAtPath:filePath error:&error];}

        else {
            NSLog(@"File %@ doesn't exist.  Making %@.", csvfileName,csvfileName);
        }
        [[NSFileManager defaultManager] createFileAtPath:filePath
                                                contents:nil
                                              attributes:nil];
        myHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];

        //Start accelerometer
        count =0;
        motionManager = [[CMMotionManager alloc] init];
        motionManager.deviceMotionUpdateInterval=.02;

        [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *deviceMotion, NSError *error) {
            CMAcceleration userAcceleration = deviceMotion.userAcceleration;
            float accelval = userAcceleration.y*9.81;
            count = count + 1;
            NSString *accelvalue = [[NSString alloc] initWithFormat:@"%f\n",accelval];
            NSLog(@"number: %d Accelval: %f",count, accelval);
            [myHandle seekToEndOfFile];
            [myHandle writeData:[accelvalue dataUsingEncoding:NSUTF8StringEncoding]];

        }];
    }
        else{
            [motionManager stopDeviceMotionUpdates];
            [myHandle closeFile];
            [recordbuttonimage setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];
        recordbuttonstatus=0;
        playbuttonimage.enabled=TRUE;
        [playbuttonimage setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
        [recorder stop];
        }

}
Zen
  • 1
  • 3
  • That code doesn't look complete at first glance? – bbum Mar 26 '17 at 16:48
  • I am wondering if its a random hardware issue because I got it to work up to 532 values and then when I re-ran the app it crashed when it got over 500. The error doesn't show until you press the button to stop recording. – Zen Mar 26 '17 at 16:49
  • Yeah, it is an excerpt. I will post the entire code if it fits – Zen Mar 26 '17 at 16:49

1 Answers1

0

So I experimented with initiating and changing when I called [fileHandle closeFile] and I got it:

I needed to make sure that there was no chance that the fileHandle would change after a recording or that closeFile was called too early/too late. So I put all the fileHandle lines in the block in which the accelerometer would update for each value. It was afraid it would lag my code but it didn't.
Here is the code:

[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *deviceMotion, NSError *error) {
        CMAcceleration userAcceleration = deviceMotion.userAcceleration;
        float accelval = userAcceleration.y*9.81;
        count = count + 1;
        NSString *accelvalue = [[NSString alloc] initWithFormat:@"%f\n",accelval];
        NSLog(@"number: %d Accelval: %f",count, accelval);
        NSFileHandle *myHandle;
        myHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
        [myHandle seekToEndOfFile];
        [myHandle writeData:[accelvalue dataUsingEncoding:NSUTF8StringEncoding]];
        [myHandle closeFile];
    }];
Zen
  • 1
  • 3
  • You should refactor the code to not open/write/close the file with each new value. That's really inefficient. – bbum Mar 27 '17 at 17:47