How to connect AudioFilePlayer AudioUnit to 3DMixer?

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

That's what I'm doing:

  • create an AUGraph using NewAUGraph()

  • Open chart

  • Initialize schedule

  • Add 3 nodes:

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

    • filePlayerNode → mixerNode
    • mixerNode -> outputNode
  • Configure FilePlayer sound module to play the desired file

  • Start schedule

This does not work: it aborts when AUGraphInitialize fails with error 10868 (kAudioUnitErr_FormatNotSupported). I think the problem is due to a mismatch in the audio format between the file player and the mixer. I think this is because: - If I comment on the connection of filePlayerNode to mixerNode ( AUGraphConnectNodeInput(_graph, filePlayerNode, 0, mixerNode, 0) ) and comment on step 6, no error messages are reported. - If I replaced step 3 by connecting filePlayerNode directly to outputNode ( AUGraphConnectNodeInput(_graph, filePlayerNode, 0, outputNode, 0) ), then the sound is played.

What steps am I missing when connecting filePlayerNode to mixerNode?

Here is the full code. This is based on Apple code sample and other samples I found from interwebs. ( AUGraphStart is called the last):

 - (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 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 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; } 
+7
source share
2 answers

I do not see in your code where you set the corresponding kAudioUnitProperty_StreamFormat for audio devices. You will also need to check the error result codes to make sure that the stream format you select is actually supported by your tuned audio device. If not, try a different format.

+3
source

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

Try this if it can help. To get information on the left node, the right node is entered. therefore, in the first line, the node player is entered into the node mixer, now the node mixer contains both the player and the mixer, so add a node mixer to output the node.

0
source

All Articles