• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: AudioQueueProcessingTap for input (recording) queue?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AudioQueueProcessingTap for input (recording) queue?


  • Subject: Re: AudioQueueProcessingTap for input (recording) queue?
  • From: Chris Adamson <email@hidden>
  • Date: Thu, 02 Oct 2014 11:22:35 -0400

OK, so the headers make it look like an AudioQueueProcessingTap on an input (record) queue should be possible. In fact, the code below does work well enough to reach both callbacks (the regular queue callback that gets AAC, and the tap callback that gets LPCM) on the simulator, though I’m not looking at the callback data yet, so maybe it’s NULL and I’m just fooling myself.

On the device… eh, not so good. AudioQueueProcessingTapNew() returns paramErr (-50) on the simulator and the device if the flags parameter is kAudioQueueProcessingTap_Siphon. If flags is kAudioQueueProcessingTap_PreEffects or kAudioQueueProcessingTap_PostEffects, it works on simulator, but on the device (this is on an iPhone 4 running iOS 7.1.2), it gives:

2014-10-02 11:14:49.631 RecordingQueueTapExperiment[937:60b] 11:14:49.631 ERROR:     [0x3d2b618c] 49: vm_map failed: 0x4 ((os/kern) invalid argument)
2014-10-02 11:14:49.634 RecordingQueueTapExperiment[937:60b] created tap, maxFrames is 0, status is 4

So, that doesn’t exactly inspire confidence.

—Chris


//
//  ViewController.m
//  RecordingQueueTapExperiment
//
//  Created by Chris Adamson on 10/1/14.
//

#define USE_AUDIO_QUEUE_PROCESSING_TAP

#import "ViewController.h"
@import AudioToolbox;
@import AVFoundation;

static const UInt32 kNumQueueBuffers = 3;
static const UInt32 kDefaultQueueBufferSize = 0x4000; // actually, AAC will want 32K


@interface ViewController () {
    AudioQueueBufferRef recordingQueueBuffers[kNumQueueBuffers];
}
@property AudioQueueRef recordingQueue;
@property AudioQueueProcessingTapRef recordingQueueTap;
@property UInt32 recordingQueueTapMaxFrames;
@property AudioStreamBasicDescription recordingQueueOutputFormat;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSError *avErr = nil;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
                                           error:&avErr];
    NSLog (@"set audio category, avErr is %@", avErr);

    

    

    __weak ViewController *weakSelf = self;
    [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
        if (granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf createRecordingQueue];
            });
        }
    }];

}


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

#pragma mark create queue
-(void) createRecordingQueue {

    

    OSStatus status = noErr;

    // create recording queue to produce AAC
    AudioStreamBasicDescription aacFormat = {0};
    aacFormat.mFormatID = kAudioFormatMPEG4AAC;
    aacFormat.mSampleRate = 44100.0;
    aacFormat.mChannelsPerFrame = 1;

    

    status = AudioQueueNewInput(&aacFormat,
                                audioQueueInputCallback,
                                (__bridge void *)(self),
                                NULL,
                                NULL,
                                0,
                                &_recordingQueue);
    NSLog (@"created queue, status is %ld", status);

#ifdef USE_AUDIO_QUEUE_PROCESSING_TAP
    // create tap to get LPCM before the AAC encode
    // problem: if inFlags==kAudioQueueProcessingTap_Siphon, we get status==-50.
    // if pre- or post-effects, works on the simulator but not the device:
    // "ERROR:     [0x3d2b618c] 49: vm_map failed: 0x4 ((os/kern) invalid argument)" and status==4
    status = AudioQueueProcessingTapNew(_recordingQueue,
                                        audioQueueProcessingTapCallback,
                                        (__bridge void*) self,
                                        kAudioQueueProcessingTap_PreEffects,
                                        &_recordingQueueTapMaxFrames,
                                        &_recordingQueueOutputFormat,
                                        &_recordingQueueTap);
    NSLog (@"created tap, maxFrames is %ld, status is %ld", _recordingQueueTapMaxFrames, status);
#endif

    

    // commenting this out because it gives -50 on the device (why?)
//    UInt32 maxPacketSize = 0;
//    UInt32 propSize = sizeof(maxPacketSize);
//    status = AudioQueueGetProperty(_recordingQueue,
//                                   kAudioQueueProperty_MaximumOutputPacketSize,
//                                   &maxPacketSize,
//                                   &propSize);
//    maxPacketSize = MAX(maxPacketSize, kDefaultQueueBufferSize);
//    NSLog (@"maxPacketSize is %ld, status is %ld", maxPacketSize, status);

    // workaround for inability to get kAudioQueueProperty_MaximumOutputPacketSize
    UInt32 maxPacketSize = kDefaultQueueBufferSize;

    

    // enqueue empty buffers
    for (int i=0; i<kNumQueueBuffers; i++) {
        status = AudioQueueAllocateBuffer(_recordingQueue,
                                          maxPacketSize,
                                          &recordingQueueBuffers[i]);
        if (status == noErr) {
            status = AudioQueueEnqueueBuffer(_recordingQueue,
                                             recordingQueueBuffers[i],
                                             0,
                                             NULL);
            NSLog (@"enqueued buffer %d, status is %ld", i, status);
        }
    }

    

    // start (this should be on a button or something)
    status = AudioQueueStart(_recordingQueue,
                             NULL);
    NSLog (@"started queue, status is %ld" , status);

    

    

}

#pragma mark queue callbacks
static void audioQueueInputCallback ( void *inUserData,
                              AudioQueueRef inAQ,
                              AudioQueueBufferRef inBuffer,
                              const AudioTimeStamp *inStartTime,
                              UInt32 inNumberPacketDescriptions,
                              const AudioStreamPacketDescription *inPacketDescs ) {
    NSLog (@"1. - audioQueueInputCallback");
    OSStatus status = noErr;
    status = AudioQueueEnqueueBuffer(inAQ,
                                     inBuffer,
                                     0,
                                     NULL);

    

}


#pragma mark tap callbacks
static void audioQueueProcessingTapCallback (
                                      void *                          inClientData,
                                      AudioQueueProcessingTapRef      inAQTap,
                                      UInt32                          inNumberFrames,
                                      AudioTimeStamp *                ioTimeStamp,
                                      UInt32 *                        ioFlags,
                                      UInt32 *                        outNumberFrames,
                                      AudioBufferList *               ioData) {
    NSLog (@"2. - audioQueueProcessingTapCallback");

    UInt32 getSourceFlags = 0;
    UInt32 getSourceFrames = 0;
    OSStatus status = noErr;
    // NOTE: docs say don't call get source audio if tap type is siphon
    status = AudioQueueProcessingTapGetSourceAudio(inAQTap,
                                                   inNumberFrames,
                                                   ioTimeStamp,
                                                   &getSourceFlags,
                                                   &getSourceFrames,
                                                   ioData);
    NSLog (@"3. - called AudioQueueProcessingTapGetSourceAudio, status is %ld", status);
}



@end

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

References: 
 >AudioQueueProcessingTap for input (recording) queue? (From: Chris Adamson <email@hidden>)

  • Prev by Date: AudioQueueProcessingTap for input (recording) queue?
  • Next by Date: "Pop" at the end of AUSampler sample
  • Previous by thread: AudioQueueProcessingTap for input (recording) queue?
  • Next by thread: "Pop" at the end of AUSampler sample
  • Index(es):
    • Date
    • Thread