Самый простой способ захвата необработанного звука с аудио входа для обработки в реальном времени на Mac - PullRequest
4 голосов
/ 18 мая 2011

Какой самый простой способ захватить звук со встроенного аудиовхода и иметь возможность читать необработанные выборочные значения (как в .wav) в режиме реального времени, когда они поступают по запросу, например, чтение из сокета.

Надеемся, код, который использует одну из платформ Apple (Audio Queues).Документация не очень понятна, и то, что мне нужно, очень просто.

Ответы [ 2 ]

7 голосов
/ 16 июня 2011

Попробуйте для этого AudioQueue Framework. В основном вам нужно выполнить 3 шага:

  1. настройка формата аудио, как сэмплировать входящее аналоговое аудио
  2. начать новую запись AudioQueue с AudioQueueNewInput ()
  3. Регистрация процедуры обратного вызова, которая обрабатывает входящие пакеты аудиоданных

На шаге 3 у вас есть возможность проанализировать входящие аудиоданные с помощью AudioQueueGetProperty ()

Это примерно так:

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);
}

Я предлагаю Руководство по программированию служб Apple AudioQueue для получения подробной информации о том, как запустить и остановить AudioQueue и как правильно настроить все необходимые объекты.

Вы также можете ближе познакомиться с демонстрационной прогой Apple SpeakHere. Но это ИМХО немного запутанно для начала.

2 голосов
/ 24 июня 2011

Зависит от того, насколько «в режиме реального времени» вам это нужно.

. Если вам нужно очень четкое изображение, спуститесь прямо на нижний уровень и используйте аудиоустройства.это означает настройку обратного вызова INPUT.помните, что когда это срабатывает, вам нужно выделить свои собственные буферы, а затем запросить звук у микрофона.

т.е. не обманывайте себя наличием указателя буфера в параметрах ... он только тампотому что Apple использует одно и то же объявление функции для обратных вызовов input и render.

- вот вставка из одного из моих проектов:

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;
}
...