2012-11-09 23 views
7

tôi có một vấn đề;)AUGraph Ghi and Play với RemoteIO và MultiChannelMixer

tôi muốn ghi lại âm thanh từ Mic và Viết nó vào hệ thống tập tin với Extended Audio File Services và cũng chơi ghi Stuff. nếu tôi chỉ sử dụng remoteIO với hai callbacks một cho đọc một để viết nó hoạt động.

Đối với Volumen Control, tôi muốn sử dụng MultiChannelMixer và AUGraph. có thể bạn nhận ra việc phát lại và ghi bằng cùng một bộ trộn và RemoteIO không?

tôi nghĩ rằng nó phải giống như thế này:

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

tôi tạo ra hai AUNodes (RemoteIO và MultiChannelMixer), làm thế nào phải tôi đặt Callback và Connections rằng một Callback cung cấp những AudioData từ mic và một khác đọc dữ liệu từ một tập tin và cả hai đường dẫn đi qua máy trộn?

Đọc và viết không phải là vấn đề, chỉ cấu hình các nút!

... và đầu ra của 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 

đây là mã thiết lập:

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

tôi hy vọng bạn hiểu vấn đề của tôi :) Cảm ơn ..

Cập nhật: Một số nội dung khác để mô tả Vấn đề của tôi!

Ghi: RemoteIO InputScope Bus 0 -> Mixer Input Bus 0 -> Mixer Output Bus 0 -> Write Callback -> File Phát lại: File -> Read Callback -> Mixer Input Bus 1 -> Mixer Output Bus 0 - > RemoteIO OutputScope Bus 1

Connection Plan

Trả lời

7

Bạn cần tạo AUGraph với ba nút (đơn vị):

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

Kết nối chúng như thế này:

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 đầu vào RIO:

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

Nhận dạng đầu ra trộn và thiết lập nó như là định dạng của khách hàng cho Extended Audio File:

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

Xác định làm callback:

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 callback cho dữ liệu đầu ra từ máy trộn:

AudioUnitAddRenderNotify(m_mixerUnit, mixerCallBack, NULL); 

Đó là tất cả. Bạn cần lên lịch các tệp âm thanh cho đơn vị FilePlayer để phát.

Các vấn đề liên quan