2017-01-15 4 views
1

In dem Bemühen, in MacOS-Programmierung zu gelangen, versuche ich ein einfaches Programm zu machen, das Audio von einem Eingabegerät aufnehmen würde (zB das eingebaute Mikrofon auf meinem MacBook Pro) . Ich habe ein Objective-C Cocoa-Projekt in Xcode erstellt und der Code ist eine leicht angepasste Version von this tutorial from developer.apple.com.Eingangswarteschlange Callback, aber keine Daten

Hier ist mein Code:

// AppDelegate.m: 

#include <AudioToolbox/AudioToolbox.h> 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 

    struct AQRecorderState S; 

#define PRINT_R do{\ 
printf("%d: r = %d\n",__LINE__, r);\ 
}while(0) 

    AudioStreamBasicDescription *fmt = &S.mDataFormat; 

    fmt->mFormatID   = kAudioFormatLinearPCM; 
    fmt->mSampleRate  = 44100.0; 
    fmt->mChannelsPerFrame = 1; 
    fmt->mBitsPerChannel = 32; 
    fmt->mBytesPerFrame = fmt->mChannelsPerFrame * sizeof (float); 
    fmt->mFramesPerPacket = 1; 
    fmt->mBytesPerPacket = fmt->mBytesPerFrame * fmt->mFramesPerPacket; 
    fmt->mFormatFlags  = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved; 

    OSStatus r = 0; 

    r = AudioQueueNewInput(&S.mDataFormat, HandleInputBuffer, &S, NULL, kCFRunLoopCommonModes, 0, &S.mQueue); 

    PRINT_R; 

    UInt32 dataFormatSize = sizeof (S.mDataFormat); 

    r = AudioQueueGetProperty ( 
         S.mQueue, 
         kAudioConverterCurrentInputStreamDescription, 
         &S.mDataFormat, 
         &dataFormatSize 
         ); 

    S.bufferByteSize = 22050;  

    for (int i = 0; i < NUM_BUFFERS; ++i) {   
     r = AudioQueueAllocateBuffer(S.mQueue, S.bufferByteSize, &S.mBuffers[i]); 
     PRINT_R; 

     r = AudioQueueEnqueueBuffer(S.mQueue, S.mBuffers[i], 0, NULL); 
     PRINT_R; 
    } 

    S.mCurrentPacket = 0;   
    S.mIsRunning = true;   

    r = AudioQueueStart(S.mQueue, NULL); 
    PRINT_R; 

    r = AudioQueueStop(S.mQueue, true); 
    S.mIsRunning = false; 

    PRINT_R; 

    r = AudioQueueDispose(S.mQueue, true); 
} 

Hier ist meine Eingangscallback-Funktion (in einer separaten C-Datei definiert):

void HandleInputBuffer ( 
          void        *aqData,    
          AudioQueueRef      inAQ,     
          AudioQueueBufferRef     inBuffer,    
          const AudioTimeStamp    *inStartTime,   
          UInt32        inNumPackets,   
          const AudioStreamPacketDescription *inPacketDesc   
) { 

    struct AQRecorderState *pAqData = (struct AQRecorderState *) aqData;    

    if (inNumPackets == 0 && pAqData->mDataFormat.mBytesPerPacket != 0) { 
     inNumPackets = 
     inBuffer->mAudioDataByteSize/pAqData->mDataFormat.mBytesPerPacket; 
    } 
    printf("%f\n", *(float*)inBuffer->mAudioData); 
    if (pAqData->mIsRunning == 0)          
     return; 

    AudioQueueEnqueueBuffer(pAqData->mQueue, inBuffer, 0, NULL); 
} 

Wenn das Programm ausgeführt wird, alle der Core Audio-Funktionsaufrufe 0 zurück, die (glaube ich) für „kein Fehler“, und HandleInputBuffer wird NUM_BUFFERS mal in sehr schneller Folge oder fast sofort genannt (die meisten definitiv nicht alle 0,5 Se cs wie die Puffergröße von 22050 würde bei dieser Abtastrate vorschlagen, und alle ersten Abtastwerte sind 0,0. Was fehlt mir hier?

+0

Mein C wird verrostet. Müssen Sie nicht "Malloc" 'S' zuordnen? Auch die Formatwerte sehen für mich irgendwie willkürlich aus. Warum 32 Bit/Kanal? Warum diese formatFlags? – shallowThought

+0

Ach ja, beim Aufruf von 'AudioQueueNewInput' mit ungültigen Werten im ASBD wird eine Fehlermeldung (" fmt? ") Ausgegeben, die die Standardwerte des Standard-Eingabegerätes enthält und von wo ich die Werte herbekomme. Ich glaube auch, 'AudioQueueAllocateBuffer' macht die Zuweisung – ehoopz

+0

' AudioQueueNewInput' arbeitet mit 'fmt-> mBitsPerChannel = 16' und' fmt-> mFormatFlags = kAudioFormatFlagIsSignedInteger' aber immer noch keine Eingabe. Ich wundere mich irgendwie, warum es "io: 44100 Hz, 32-Bit Float" für das eingebaute Mikrofon sagt, obwohl – ehoopz

Antwort

0

S.bufferByteSize ist in Bytes, nicht Frames, also 22050 Bytes ist keine halbe Sekunde, aber 22050/sizeof(float) Frames, also etwa eine Achtelsekunde.

Wenn Sie eine halbe Sekunde, versuchen

S.bufferByteSize = fmt->mSampleRate * fmt->mBytesPerFrame/2; 

In Ihrem obigen Code (und auch im git Repo Sie verbunden sind), erhalten Sie sofort AudioQueueStop und AudioQueueDispose die Audio-Warteschlange nach AudioQueueStart es ing. Tu das nicht.

+0

Ganz wahr, danke! Aber mein Problem wird leider nicht gelöst :(Der Callback wird immer noch 'NUM_BUFFERS' genannt und zwar sofort und es werden keine Daten empfangen. – ehoopz

+0

Hast du dir die NSLog-Zeitstempel angeschaut? Woher weißt du, dass es keine Daten gibt? –

+0

Yeah, I have. Zum Beispiel sahen sie so aus, als ich sie zuletzt ausgeführt habe: "2017-01-16 02: 47: 11.439407", "2017-01-16 02: 47: 11.439440", "2017-01-16 02: 47: 11.439462" , 2017-01-16 02: 47: 11.439473', '2017-01-16 02: 47: 11.439483',' 2017-01-16 02: 47: 11.439492' mit 'NUM_BUFFERS = 6' und' bufferByteSize = 44100 * 4' – ehoopz

Verwandte Themen