2012-04-24 25 views
7

Tôi đang cố gắng kết nối AudioUnilePlayer AudioUnit với Thiết bị âm thanh AU3DMixerEmbedded, nhưng tôi không thành công.Làm cách nào để kết nối AudioUnilePlayer AudioUnit với 3DMixer?

Đây là những gì tôi đang làm:

  1. tạo AUGraph với NewAUGraph()

  2. mở đồ thị

  3. initalize đồ thị

  4. Thêm 3 nút:

    • outputNode: kAudioUnitSubType_RemoteIO
    • mixerNode: kAudioUnitSubType_AU3DMixerEmbedded
    • filePlayerNode: kAudioUnitSubType_AudioFilePlayer
  5. Kết nối các nút:

    • filePlayerNode -> mixerNode
    • mixerNode -> outputNode
  6. Cấu hình Audio Đơn vị filePlayer để chơi các tập tin cần thiết

  7. Bắt đầu đồ thị

này không hoạt động: nó balks tại AUGraphInitialize với lỗi 10.868 (kAudioUnitErr_FormatNotSupported). Tôi nghĩ rằng vấn đề là do định dạng âm thanh không khớp giữa filePlayer và máy trộn. Tôi nghĩ rằng điều này bởi vì: - Nếu tôi nhận xét kết nối tệpPlayerNode đến mixerNode (AUGraphConnectNodeInput(_graph, filePlayerNode, 0, mixerNode, 0)) và nhận xét bước 6 thì không có lỗi nào được báo cáo. - Nếu tôi thay thế bước 3 bằng cách kết nối tệpPlayerNode trực tiếp với outputNode (AUGraphConnectNodeInput(_graph, filePlayerNode, 0, outputNode, 0)) thì phát âm thanh.

Tôi đang thiếu các bước nào khi kết nối tệpPlayerNode với mixerNode?

Đây là mã đầy đủ. Nó dựa trên mã mẫu của Apple và các mẫu khác mà tôi đã tìm thấy từ interwebs. (AUGraphStart được gọi sau):

- (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

Yêu thích việc sử dụng các khối '{...}' để bao bọc các biến trung gian và tổ chức mã ... –

+0

Chụp lâu, nhưng tôi cũng gặp vấn đề tương tự. Định dạng được chấp nhận cuối cùng là gì? –

+1

cảm ơn mã. :). btw nó hoạt động cho tôi. Tôi vừa thêm AUGraphStart (đồ thị) –

Trả lời

3

Tôi không thấy trong mã của bạn, nơi bạn thiết lập các kAudioUnitProperty_StreamFormat thích hợp cho các đơn vị âm thanh. Bạn cũng sẽ phải kiểm tra mã kết quả lỗi để xem cài đặt định dạng luồng bạn chọn có thực sự được hỗ trợ bởi đơn vị âm thanh đang được định cấu hình hay không. Nếu không, hãy thử một định dạng khác.

0

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

Hãy thử làm theo cách này nếu nó có thể help.Just để biết thông tin trái nút là đầu vào trong nút bên phải. do đó, trong dòng đầu tiên nút máy nghe nhạc được nhập vào nút trộn, bây giờ nút trộn chứa cả máy nghe nhạc và máy trộn để thêm nút trộn vào nút đầu ra.

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