How do I connect an AudioFilePlayer AudioUnit to a 3DMixer?

I am trying to connect an AudioFilePlayer AudioUnit to an AU3DMixerEmbedded Audio Unit, but I'm having no success.

Here's what I'm doing:

  • create an AUGraph with NewAUGraph()

  • Open the graph

  • Initalize the graph

  • Add 3 nodes:

  • outputNode: kAudioUnitSubType_RemoteIO
  • mixerNode: kAudioUnitSubType_AU3DMixerEmbedded
  • filePlayerNode: kAudioUnitSubType_AudioFilePlayer
  • Connect the nodes:

  • filePlayerNode -> mixerNode
  • mixerNode -> outputNode
  • Configure the filePlayer Audio Unit to play the required file

  • Start the graph

  • This doesn't work: it balks at AUGraphInitialize with error 10868 (kAudioUnitErr_FormatNotSupported). I think the problem is due to audio format mismatch between the filePlayer and the mixer. I think this because: - If I comment out connecting the filePlayerNode to the mixerNode ( AUGraphConnectNodeInput(_graph, filePlayerNode, 0, mixerNode, 0) ) and comment out step 6 then no errors are reported. - If I replace step 3 with connecting the filePlayerNode directly to the outputNode ( AUGraphConnectNodeInput(_graph, filePlayerNode, 0, outputNode, 0) ) then the audio plays.

    What steps am I missing in connecting the filePlayerNode to the mixerNode?

    Here's the code in full. It's based on Apple's sample code and other samples I've found from the interwebs. ( AUGraphStart is called latter):

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

    I don't see in your code where you set the appropriate kAudioUnitProperty_StreamFormat for the audio units. You will also have to check the error result codes to see if the stream format setting you choose is actually supported by the audio unit being configured. If not, try another format.


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

    Try doing this way if it can help.Just for information the left node is input in the right node. so in first line the player node is input to the mixer node, now mixer node contains both player and mixer so add mixer node to output node.

    链接地址: http://www.djcxy.com/p/10684.html

    上一篇: 数据库版本部署。 实体框架迁移vs SSDT DacPacs

    下一篇: 如何将AudioFilePlayer AudioUnit连接到3DMixer?