2012-04-24 17 views
7

我正嘗試將AudioFilePlayer AudioUnit連接到AU3DMixerEmbedded Audio Unit,但我沒有成功。如何將AudioFilePlayer AudioUnit連接到3DMixer?

下面是我在做什麼:

  1. 創建AUGraphNewAUGraph()

  2. 打開圖形

  3. Initalize圖

  4. 添加三個節點:

    • outputNode:kAudioUnitSubType_RemoteIO
    • mixerNode:kAudioUnitSubType_AU3DMixerEmbedded
    • filePlayerNode:kAudioUnitSubType_AudioFilePlayer
  5. 連接節點:

    • filePlayerNode - > mixerNode
    • mixerNode - > outputNode
  6. 配置filePlayer音頻單元發揮所需的文件

  7. 啓動圖形

這不起作用:它不太願意AUGraphInitialize錯誤10868(kAudioUnitErr_FormatNotSupported)。我認爲這個問題是由於filePlayer和調音臺之間的音頻格式不匹配造成的。我認爲這是因爲: - 如果我註釋掉將filePlayerNode連接到mixerNode(AUGraphConnectNodeInput(_graph, filePlayerNode, 0, mixerNode, 0))並註釋掉第6步,則不會報告任何錯誤。 - 如果將filePlayerNode直接連接到outputNode(AUGraphConnectNodeInput(_graph, filePlayerNode, 0, outputNode, 0)),則替換第3步,然後播放音頻。

我在將filePlayerNode連接到mixerNode時缺少哪些步驟?

下面是完整的代碼。它基於蘋果公司的示例代碼和我從互聯網上找到的其他樣本。 (AUGraphStart被稱爲後者):

- (id)init 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     { 
      //create a new AUGraph 
      CheckError(NewAUGraph(&_graph), "NewAUGraph failed");   
      // opening the graph opens all contained audio units but does not allocate any resources yet    
      CheckError(AUGraphOpen(_graph), "AUGraphOpen failed");     
      // now initialize the graph (causes resources to be allocated) 
      CheckError(AUGraphInitialize(_graph), "AUGraphInitialize failed");      
     } 

     AUNode outputNode; 
     { 
      AudioComponentDescription outputAudioDesc = {0}; 
      outputAudioDesc.componentManufacturer = kAudioUnitManufacturer_Apple;    
      outputAudioDesc.componentType = kAudioUnitType_Output; 
      outputAudioDesc.componentSubType = kAudioUnitSubType_RemoteIO; 
      // adds a node with above description to the graph 
      CheckError(AUGraphAddNode(_graph, &outputAudioDesc, &outputNode), "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed"); 
     } 

     AUNode mixerNode; 
     { 
      AudioComponentDescription mixerAudioDesc = {0}; 
      mixerAudioDesc.componentManufacturer = kAudioUnitManufacturer_Apple;         
      mixerAudioDesc.componentType = kAudioUnitType_Mixer; 
      mixerAudioDesc.componentSubType = kAudioUnitSubType_AU3DMixerEmbedded; 
      mixerAudioDesc.componentFlags = 0; 
      mixerAudioDesc.componentFlagsMask = 0; 
      // adds a node with above description to the graph 
      CheckError(AUGraphAddNode(_graph, &mixerAudioDesc, &mixerNode), "AUGraphAddNode[kAudioUnitSubType_AU3DMixerEmbedded] failed");    
     } 

     AUNode filePlayerNode;    
     { 
      AudioComponentDescription fileplayerAudioDesc = {0};    
      fileplayerAudioDesc.componentType = kAudioUnitType_Generator; 
      fileplayerAudioDesc.componentSubType = kAudioUnitSubType_AudioFilePlayer; 
      fileplayerAudioDesc.componentManufacturer = kAudioUnitManufacturer_Apple; 
      // adds a node with above description to the graph 
      CheckError(AUGraphAddNode(_graph, &fileplayerAudioDesc, &filePlayerNode), "AUGraphAddNode[kAudioUnitSubType_AudioFilePlayer] failed"); 
     } 

     //Connect the nodes 
     { 
      // connect the output source of the file player AU to the input source of the output node    
//   CheckError(AUGraphConnectNodeInput(_graph, filePlayerNode, 0, outputNode, 0), "AUGraphConnectNodeInput");       

      CheckError(AUGraphConnectNodeInput(_graph, filePlayerNode, 0, mixerNode, 0), "AUGraphConnectNodeInput"); 
      CheckError(AUGraphConnectNodeInput(_graph, mixerNode, 0, outputNode, 0), "AUGraphConnectNodeInput");          
     } 



     // configure the file player 
     // tell the file player unit to load the file we want to play 
     { 
      //????? 
      AudioStreamBasicDescription inputFormat; // input file's data stream description 
      AudioFileID inputFile; // reference to your input file    

      // open the input audio file and store the AU ref in _player 
      CFURLRef songURL = (__bridge CFURLRef)[[NSBundle mainBundle] URLForResource:@"monoVoice" withExtension:@"aif"]; 
      CheckError(AudioFileOpenURL(songURL, kAudioFileReadPermission, 0, &inputFile), "AudioFileOpenURL failed"); 

      //create an empty MyAUGraphPlayer struct 
      AudioUnit fileAU; 

      // get the reference to the AudioUnit object for the file player graph node 
      CheckError(AUGraphNodeInfo(_graph, filePlayerNode, NULL, &fileAU), "AUGraphNodeInfo failed"); 

      // get and store the audio data format from the file 
      UInt32 propSize = sizeof(inputFormat); 
      CheckError(AudioFileGetProperty(inputFile, kAudioFilePropertyDataFormat, &propSize, &inputFormat), "couldn't get file's data format");    

      CheckError(AudioUnitSetProperty(fileAU, kAudioUnitProperty_ScheduledFileIDs, kAudioUnitScope_Global, 0, &(inputFile), sizeof((inputFile))), "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFileIDs] failed"); 

      UInt64 nPackets; 
      UInt32 propsize = sizeof(nPackets); 
      CheckError(AudioFileGetProperty(inputFile, kAudioFilePropertyAudioDataPacketCount, &propsize, &nPackets), "AudioFileGetProperty[kAudioFilePropertyAudioDataPacketCount] failed"); 

      // tell the file player AU to play the entire file 
      ScheduledAudioFileRegion rgn; 
      memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp)); 
      rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid; 
      rgn.mTimeStamp.mSampleTime = 0; 
      rgn.mCompletionProc = NULL; 
      rgn.mCompletionProcUserData = NULL; 
      rgn.mAudioFile = inputFile; 
      rgn.mLoopCount = 1; 
      rgn.mStartFrame = 0; 
      rgn.mFramesToPlay = nPackets * inputFormat.mFramesPerPacket; 

      CheckError(AudioUnitSetProperty(fileAU, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0,&rgn, sizeof(rgn)), "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFileRegion] failed"); 

      // prime the file player AU with default values 
      UInt32 defaultVal = 0; 
      CheckError(AudioUnitSetProperty(fileAU, kAudioUnitProperty_ScheduledFilePrime, kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal)), "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFilePrime] failed"); 

      // tell the file player AU when to start playing (-1 sample time means next render cycle) 
      AudioTimeStamp startTime; 
      memset (&startTime, 0, sizeof(startTime)); 
      startTime.mFlags = kAudioTimeStampSampleTimeValid; 
      startTime.mSampleTime = -1; 
      CheckError(AudioUnitSetProperty(fileAU, kAudioUnitProperty_ScheduleStartTimeStamp, kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)), "AudioUnitSetProperty[kAudioUnitProperty_ScheduleStartTimeStamp]"); 

      // file duration 
      //double duration = (nPackets * _player.inputFormat.mFramesPerPacket)/_player.inputFormat.mSampleRate; 
     }    


    } 
    return self; 
} 
+4

喜歡使用'{...}'塊來包裝中間變量並組織代碼... – 2012-08-14 17:36:32

+0

遠射,但我遇到同樣的問題。最終的可接受格式是什麼? – 2012-12-09 03:38:09

+1

感謝您的代碼。 :)。順便說一句,它適用於我。我剛添加AUGraphStart(圖) – 2014-08-17 12:22:57

回答

3

我沒有在你的代碼看到你設置相應的kAudioUnitProperty_StreamFormat的音頻單元。您還必須檢查錯誤結果代碼,以確定您選擇的流格式設置是否實際上由正在配置的音頻設備支持。如果不是,請嘗試其他格式。

0

(AUGraphConnectNodeInput(_graph,filePlayerNode,0,mixerNode,0))(AUGraphConnectNodeInput(_graph,mixerNode,0,outputNode,0))

嘗試這樣的方式,如果它可以help.Just信息左節點被輸入到正確的節點中。所以在第一行中,播放器節點被輸入到混合器節點,現在混合器節點包含播放器和混合器,因此將混合器節點添加到輸出節點。