2012-11-09 5 views
7

ich habe ein Problem;)AUGraph Aufzeichnung und Wiedergabe mit RemoteIO und MultiChannelMixer

Ich möchte Audio vom Mikrofon aufzunehmen und auf das Dateisystem mit erweiterten Audio File Services zu schreiben und auch das aufgezeichnete Material zu spielen. Wenn ich nur die remoteIO mit zwei Callbacks eine zum Lesen eines für schreiben verwenden, funktioniert es.

Für die Lautstärkeregelung möchte ich den MultiChannelMixer und den AUGraph verwenden. ist es möglich, dass Sie die Wiedergabe und Aufnahme mit dem gleichen Mixer und der RemoteIO realisieren?

Ich denke, es so aussehen muss:

RemotIO Input ->  -> Write Callback 
        Mixer 
RemoteIO Output <-  <- Read Callback 

i erstellen zwei AUNodes (RemoteIO und MultiChannelMixer), wie muss ich die Rückrufe und die Verbindungen eingestellt, die ein Rückruf der Audiodata vom Mikrofon liefern und eine andere liest die Daten aus einer Datei und beide Wege gehen durch den Mischer?

Das Lesen und Schreiben ist nicht das Problem, nur die Konfiguration der Knoten!

... und die Ausgabe von CAShow:

AudioUnitGraph 0x8AEE000: 
    Member Nodes: 
    node 1: 'aumx' 'mcmx' 'appl', instance 0x865a510 O I 
    node 2: 'auou' 'rioc' 'appl', instance 0x865d0a0 O I 
    Connections: 
    node 1 bus 0 => node 2 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer] 
    node 2 bus 1 => node 1 bus 1 [ 2 ch, 44100 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer] 
    Input Callbacks: 
    {0x4150, 0x7573340} => node 2 bus 1 [2 ch, 44100 Hz] 
    {0x4330, 0x7573340} => node 1 bus 0 [2 ch, 44100 Hz] 
    CurrentState: 
    mLastUpdateError=0, eventsToProcess=F, isRunning=F 

hier ist der Setup-Code:

OSStatus setupErr = noErr; 

AudioComponentDescription mixerDescription; 
AudioComponentDescription ioDescription; 

// the AUNodes 
AUNode mixerNode; 
AUNode ioNode; 

// the graph 
setupErr = NewAUGraph(&_graph); 
NSAssert(setupErr == noErr, @"Couldn't create graph"); 

// the mixer 
mixerDescription.componentFlags = 0; 
mixerDescription.componentFlagsMask = 0; 
mixerDescription.componentType = kAudioUnitType_Mixer; 
mixerDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer; 
mixerDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 

// the io 
ioDescription.componentFlags = 0; 
ioDescription.componentFlagsMask = 0; 
ioDescription.componentType = kAudioUnitType_Output; 
ioDescription.componentSubType = kAudioUnitSubType_RemoteIO; 
ioDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 

// add mixer Node 
setupErr = AUGraphAddNode(self.graph, &mixerDescription, &mixerNode); 
NSAssert(setupErr == noErr, @"Couldn't create master mixer"); 

// add io Node 
setupErr = AUGraphAddNode(self.graph, &ioDescription, &ioNode); 
NSAssert(setupErr == noErr, @"Couldn't create io node"); 

// open Graph 
setupErr = AUGraphOpen(self.graph); 
NSAssert(setupErr == noErr, @"Couldn't open graph"); 

// get the mixer info 
setupErr = AUGraphNodeInfo(self.graph, mixerNode, &mixerDescription, &_mixer); 
NSAssert(setupErr == noErr, @"Couldn't get master mixer info"); 

// get the io info 
setupErr = AUGraphNodeInfo(self.graph, ioNode, &ioDescription, &_io); 
NSAssert(setupErr == noErr, @"Couldn't get io Node info"); 

// enable io input 
UInt32 enableFlag = 1; 
setupErr = AudioUnitSetProperty(self.io, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &enableFlag, sizeof(enableFlag)); 
NSAssert(setupErr == noErr, @"Couldn't enable io input"); 

// set up the mixers input callbacks 
AURenderCallbackStruct outputCallbackStruct; 
outputCallbackStruct.inputProc = outputCallback; 
outputCallbackStruct.inputProcRefCon = self; 

AURenderCallbackStruct inputCallbackStruct; 
inputCallbackStruct.inputProc = inputCallback; 
inputCallbackStruct.inputProcRefCon = self; 

setupErr = AUGraphConnectNodeInput(self.graph, mixerNode, 0, ioNode, 0); 
NSAssert(setupErr == noErr, @"Couldn't connect mixer output to io output"); 
setupErr = AUGraphConnectNodeInput(self.graph, ioNode, 1, mixerNode, 1); 
NSAssert(setupErr == noErr, @"Couldn't connect io input to mixer input"); 

// set output Callback 
setupErr = AUGraphSetNodeInputCallback(self.graph, ioNode, 1, &outputCallbackStruct); 
NSAssert(setupErr == noErr, @"Error setting io output callback"); 

// set input Callback 
setupErr = AUGraphSetNodeInputCallback(self.graph, mixerNode, 0, &inputCallbackStruct); 
NSAssert(setupErr == noErr, @"Error setting mixer input callback"); 

// describe format 
AudioStreamBasicDescription audioFormat = {0}; 
audioFormat.mSampleRate     = 44100.00; 
audioFormat.mFormatID     = kAudioFormatLinearPCM; 
audioFormat.mFormatFlags    = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
audioFormat.mFramesPerPacket   = 1; 
audioFormat.mChannelsPerFrame   = 2; 
audioFormat.mBitsPerChannel    = 16; 
audioFormat.mBytesPerPacket    = 4; 
audioFormat.mBytesPerFrame    = 4; 

// set the rio input properties 
setupErr = AudioUnitSetProperty(self.io, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &audioFormat, sizeof(audioFormat)); 
NSAssert(setupErr == noErr, @"Error setting RIO input property"); 

// set the rio output properties 
setupErr = AudioUnitSetProperty(self.io, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &audioFormat, sizeof(audioFormat)); 
NSAssert(setupErr == noErr, @"Error setting RIO output property"); 

// set the master fader output properties 
setupErr = AudioUnitSetProperty(self.mixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Global, kOutputBus, &audioFormat, sizeof(audioFormat)); 
NSAssert(setupErr == noErr, @"Error setting master output property"); 

// set the master fader input properties 
setupErr = AudioUnitSetProperty(self.mixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Global, kOutputBus, &audioFormat, sizeof(audioFormat)); 
NSAssert(setupErr == noErr, @"Error setting master input1 property"); 

// initialize Graph 
setupErr = AUGraphInitialize(self.graph); 
NSAssert(setupErr == noErr, @"Error initializing graph - error code"); 

CAShow(self.graph); 

// start Graph 
setupErr = AUGraphStart(self.graph); 
NSAssert(setupErr == noErr, @"Error starting graph. - error code"); 

ich hoffe, dass Sie mein Problem verstehen :) Dank ..

Update: Noch etwas, um mein Problem zu beschreiben!

Aufnahme: RemoteIO InputScope Bus 0 -> Mixer Input Bus 0 -> Mixer Output Bus 0 -> Schreibe Callback -> Datei Wiedergabe: Datei -> Read Callback -> Mixer Input Bus 1 -> Mixer Output Bus 0 - > RemoteIO OutputScope Bus 1

Connection Plan

Antwort

7

Sie benötigen AUGraph mit drei Knoten (Einheiten) erstellen:

  1. File Player (kAudioUnitSubType_AudioFilePlayer)
  2. RemoteIO
  3. Mixer

sie wie folgt verbinden:

AUGraphConnectNodeInput(m_graph, m_player, 0, m_mixerNode, 0); // player -> mixer 
AUGraphConnectNodeInput(m_graph, m_mixerNode, 0, m_rioNode, 0); // mixer -> output 
AUGraphConnectNodeInput(m_graph, m_rioNode, 1, m_mixerNode, 1); // input -> mixer 

Enable-Eingang auf RIO:

UInt32 enable = 1; 
AudioUnitSetProperty(m_rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enable, sizeof(UInt32)); 

Mischer Ausgabeformat Holen und als Client-Format für Extended Audiodatei gesetzt:

AudioStreamBasicDescription mixerASBD; 
UInt32 prop = sizeof(mixerASBD); 
AudioUnitGetProperty(m_mixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &mixerASBD, &prop); 
ExtAudioFileSetProperty(extAudioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(mixerASBD), &mixerASBD); 

definieren Rückruf machen:

static OSStatus mixerCallBack(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber,UInt32 inNumberFrames, AudioBufferList *ioData) { 
    if ((*ioActionFlags) & kAudioUnitRenderAction_PostRender) 
     return (ExtAudioFileWrite(extAudioFile, inNumberFrames, ioData)); 

    return noErr; 
} 

Add Rückruf für Ausgangsdaten von Mischer:

AudioUnitAddRenderNotify(m_mixerUnit, mixerCallBack, NULL); 

Das ist alles. Sie müssen Audiodateien zur Wiedergabe auf der FilePlayer-Einheit einplanen.