user3542888
user3542888

Reputation: 49

AudioFileReadPackets gives strange data

I'm trying to record audio to a file (working) and then sample the data in that file (giving strange results). FYI, I am roughly following this code... Extracting Amplitude Data from Linear PCM on the iPhone

I have noticed a few different results. For simplicity, assume the record time is fixed at 1 second.

  1. when sampling up to 8,000 samples/sec, the mutable array (see code) will list 8,000 entries but only the first 4,000 have real-looking data, the last 4,000 points are the same number value (the exact number value varies from run-to-run).

  2. somewhat related to issue #1. when sampling above 8,000 samples/second, the first half of the samples (ex. 5,000 of a 10,0000 sample set from 10,000 samples/sec for 1 second) will look like real data, while the values of the second half of the set will be fixed to some value (again this exact value varies run to run). See below snippet from my debug window, first number is packetIndex, second number is buffer value.

4996:-137

4997:1043

4998:-405

4999:-641

5000:195notice the switch from random data to constant value at 5k, for 10k sample file

5001:195

5002:195

5003:195

5004:195

3 . when having the mic listen to a speaker playing a 1kHz sinusoidal tone in close proximity and sampling this tone at 40,000 samples per second, the resulting data when plotted in a spreadsheet shows the signal at about 2kHz, or double.

Any ideas what I may be doing wrong here?

Here is my setup work to record the audio from the mic...

-(void) initAudioSession {
//    setup av session
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [audioSession setActive:YES error: nil];
    NSLog(@"audio session initiated");
//    settings for the recorded file
    NSDictionary *recordSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
                                    [NSNumber numberWithFloat:SAMPLERATE],AVSampleRateKey,
                                    [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                    [NSNumber numberWithInt:1],AVNumberOfChannelsKey,
                                    [NSNumber numberWithInt:16],AVEncoderBitRateKey,
                                    [NSNumber numberWithInt:AVAudioQualityMax],AVEncoderAudioQualityKey, nil];
//    setup file name and location
    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    fileURL = [NSURL fileURLWithPath:[docDir stringByAppendingPathComponent:@"input.caf"]];//caf or aif?
//    initialize my new audio recorder
    newAudioRecorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:recordSettings error:nil];
//    show file location so i can check it with some player
    NSLog(@"file path = %@",fileURL);
//    check if the recorder exists, if so prepare the recorder, if not tell me in debug window
    if (newAudioRecorder) {
        [newAudioRecorder setDelegate:self];
        [newAudioRecorder prepareToRecord];
        [self.setupStatus setText:[NSString stringWithFormat:@"recorder ready"]];
    }else{
        NSLog(@"error setting up recorder");
    }
}

Here is my code for loading the recorded file and grabbing the data...

//loads file and go thru values, converts data to be put into an NSMutableArray
-(void)readingRainbow{
    //    get audio file and put into a file ID
    AudioFileID fileID;
    AudioFileOpenURL((__bridge CFURLRef)fileURL, kAudioFileReadPermission, kAudioFileCAFType /*kAudioFileAIFFType*/ , &fileID);
    //    get number of packets of audio contained in file
//    instead of getting packets, i just set them to the duration times the sample rate i set
//    not sure if this is a valid approach
    UInt64 totalPacketCount = SAMPLERATE*timer;
    //    get size of each packet, is this valid?
    UInt32 maxPacketSizeInBytes = sizeof(SInt32);
    //    setup to extract audio data
    UInt32 totPack32 = SAMPLERATE*timer;
    UInt32 ioNumBytes = totPack32*maxPacketSizeInBytes;
    SInt16 *outBuffer = malloc(ioNumBytes);
    memset(outBuffer, 0, ioNumBytes);
    //    setup array to put buffer samples in
    readArray = [[NSMutableArray alloc] initWithObjects: nil];
    NSNumber *arrayData;
    SInt16 data;
    int data2;


//    this may be where i need help as well....
    //    process every packet
    for (SInt64 packetIndex = 0; packetIndex<totalPacketCount; packetIndex++) {
// method description for reference..
//        AudioFileReadPackets(<#AudioFileID inAudioFile#>, <#Boolean inUseCache#>, <#UInt32 *outNumBytes#>,
//        <#AudioStreamPacketDescription *outPacketDescriptions#>, <#SInt64 inStartingPacket#>,
//        <#UInt32 *ioNumPackets#>, <#void *outBuffer#>)
//        extract packet data, not sure if i'm setting this up properly
        AudioFileReadPackets(fileID, false, &ioNumBytes, NULL, packetIndex, &totPack32, outBuffer);
//        get buffer data and pass into mutable array
        data = outBuffer[packetIndex];
        data2=data;
        arrayData = [[NSNumber alloc] initWithInt:data2];
        [readArray addObject:arrayData];
//        printf("%lld:%d\n",packetIndex,data);
        printf("%d,",data);

    }

Also, I'm using this method to start the recorder...

[newAudioRecorder recordForDuration:timer];

Thots? I'm a noob, so any info is greatly appreciated!

Upvotes: 1

Views: 170

Answers (1)

hotpaw2
hotpaw2

Reputation: 70673

You may be recording 16-bit samples, but trying to read 32-bit samples from the file data, thus only finding half as many samples (the rest may be garbage).

Upvotes: 1

Related Questions