2012-04-24 15 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信息左节点被输入到正确的节点中。所以在第一行中,播放器节点被输入到混合器节点,现在混合器节点包含播放器和混合器,因此将混合器节点添加到输出节点。