Simplest way to capture raw audio from audio input for real time processing on a mac

前端 未结 2 1145
粉色の甜心
粉色の甜心 2021-01-01 05:00

What is the simplest way to capture audio from the built in audio input and be able to read the raw sampled values (as in a .wav) in real time as they come in when requested

相关标签:
2条回答
  • 2021-01-01 05:12

    It depends how ' real-time ' you need it

    if you need it very crisp, go down right at the bottom level and use audio units. that means setting up an INPUT callback. remember, when this fires you need to allocate your own buffers and then request the audio from the microphone.

    ie don't get fooled by the presence of a buffer pointer in the parameters... it is only there because Apple are using the same function declaration for the input and render callbacks.

    here is a paste out of one of my projects:

    OSStatus dataArrivedFromMic(
                        void                        * inRefCon, 
                        AudioUnitRenderActionFlags  * ioActionFlags, 
                        const AudioTimeStamp        * inTimeStamp, 
                        UInt32                      inBusNumber, 
                        UInt32                      inNumberFrames, 
                        AudioBufferList             * dummy_notused )
    {    
        OSStatus status;
    
        RemoteIOAudioUnit* unitClass = (RemoteIOAudioUnit *)inRefCon;
    
        AudioComponentInstance myUnit = unitClass.myAudioUnit;
    
        AudioBufferList ioData;
        {
            int kNumChannels = 1; // one channel...
    
            enum {
                kMono = 1,
                kStereo = 2
            };
    
            ioData.mNumberBuffers = kNumChannels;
    
            for (int i = 0; i < kNumChannels; i++) 
            {
                int bytesNeeded = inNumberFrames * sizeof( Float32 );
    
                ioData.mBuffers[i].mNumberChannels = kMono;
                ioData.mBuffers[i].mDataByteSize = bytesNeeded;
                ioData.mBuffers[i].mData = malloc( bytesNeeded );
            }
        }
    
        // actually GET the data that arrived
        status = AudioUnitRender( (void *)myUnit, 
                                 ioActionFlags, 
                                 inTimeStamp, 
                                 inBusNumber, 
                                 inNumberFrames, 
                                 & ioData );
    
    
        // take MONO from mic
        const int channel = 0;
        Float32 * outBuffer = (Float32 *) ioData.mBuffers[channel].mData;
    
        // get a handle to our game object
        static KPRing* kpRing = nil;
        if ( ! kpRing )
        {
            //AppDelegate *  appDelegate = [UIApplication sharedApplication].delegate;
    
            kpRing = [Game singleton].kpRing;
    
            assert( kpRing );
        }
    
        // ... and send it the data we just got from the mic
        [ kpRing floatsArrivedFromMic: outBuffer
                                count: inNumberFrames ];
    
        return status;
    }
    
    0 讨论(0)
  • 2021-01-01 05:29

    Try the AudioQueue Framework for this. You mainly have to perform 3 steps:

    1. setup an audio format how to sample the incoming analog audio
    2. start a new recording AudioQueue with AudioQueueNewInput()
    3. Register a callback routine which handles the incoming audio data packages

    In step 3 you have a chance to analyze the incoming audio data with AudioQueueGetProperty()

    It's roughly like this:

    static void HandleAudioCallback (void                               *aqData,
                                     AudioQueueRef                      inAQ,
                                     AudioQueueBufferRef                inBuffer, 
                                     const AudioTimeStamp               *inStartTime, 
                                     UInt32                             inNumPackets, 
                                     const AudioStreamPacketDescription *inPacketDesc) {
        // Here you examine your audio data
    }
    
    static void StartRecording() {
        // now let's start the recording
        AudioQueueNewInput (&aqData.mDataFormat,  // The sampling format how to record
                            HandleAudioCallback,  // Your callback routine
                            &aqData,              // e.g. AudioStreamBasicDescription
                            NULL,
                            kCFRunLoopCommonModes, 
                            0, 
                            &aqData.mQueue);      // Your fresh created AudioQueue
        AudioQueueStart(aqData.mQueue,
                        NULL);
    }
    

    I suggest the Apple AudioQueue Services Programming Guide for detailled information about how to start and stop the AudioQueue and how to setup correctly all ther required objects.

    You may also have a closer look into Apple's demo prog SpeakHere. But this is IMHO a bit confusing to start with.

    0 讨论(0)
提交回复
热议问题