Example #1
0
        public AudioVoice(AudioEngine engine, SoundEffectInstance effectInstance, WaveFormat desiredFormat)
        {
            if (engine == null)
            {
                throw new ArgumentNullException("engine");
            }
            if (desiredFormat == null)
            {
                throw new ArgumentNullException("desiredFormat");
            }

            audioEngine         = engine;
            soundEffectInstance = effectInstance;
            waveFormat          = desiredFormat;
            BusIndexMixer       = uint.MaxValue;

            if (desiredFormat.BitsPerSample != 16)
            {
                throw new AudioSystemInternalException("Invalid Audio Format. " + desiredFormat.BitsPerSample + " bits by sample is not supported.");
            }

            lock (StaticMembersLock)
            {
                if (nbOfInstances == 0)
                {
                    // Create the Audio Graph
                    audioGraph = new AUGraph();

                    // Open the graph (does not initialize it yet)
                    audioGraph.Open();

                    // Create the AudioComponentDescrition corresponding to the IO Remote output and MultiChannelMixer
                    var remoteInOutComponentDesc       = AudioComponentDescription.CreateOutput(AudioTypeOutput.Remote);
                    var mixerMultiChannelComponentDesc = AudioComponentDescription.CreateMixer(AudioTypeMixer.MultiChannel);
                    var mixer3DComponentDesc           = AudioComponentDescription.CreateMixer(AudioTypeMixer.Spacial);

                    // Add the Audio Unit nodes to the AudioGraph
                    var outputUnitNodeId   = audioGraph.AddNode(remoteInOutComponentDesc);
                    var idChannelMixerNode = audioGraph.AddNode(mixerMultiChannelComponentDesc);
                    var id3DMixerNode      = audioGraph.AddNode(mixer3DComponentDesc);

                    // Connect the nodes together
                    CheckGraphError(audioGraph.ConnnectNodeInput(idChannelMixerNode, 0, outputUnitNodeId, 0), "Connection of the graph node failed.");
                    CheckGraphError(audioGraph.ConnnectNodeInput(id3DMixerNode, 0, idChannelMixerNode, MaxNumberOfTracks), "Connection of the graph node failed.");

                    // Get the MixerUnit objects
                    unitChannelMixer = audioGraph.GetNodeInfo(idChannelMixerNode);
                    unit3DMixer      = audioGraph.GetNodeInfo(id3DMixerNode);

                    // Set the mixers' output formats (the stream format is propagated along the linked input during the graph initialization)
                    var desiredSampleRate = (engine.AudioSampleRate != 0) ? engine.AudioSampleRate : AudioUnitOutputSampleRate;
                    unit3DMixer.SetAudioFormat(CreateLinear16BitsPcm(2, desiredSampleRate), AudioUnitScopeType.Output);
                    unitChannelMixer.SetAudioFormat(CreateLinear16BitsPcm(2, desiredSampleRate), AudioUnitScopeType.Output);

                    // set the element count to the max number of possible tracks before initializing the audio graph
                    CheckUnitStatus(unitChannelMixer.SetElementCount(AudioUnitScopeType.Input, MaxNumberOfTracks + 1), string.Format("Failed to set element count on ChannelMixer [{0}]", MaxNumberOfTracks + 1)); // +1 for the 3DMixer output
                    CheckUnitStatus(unit3DMixer.SetElementCount(AudioUnitScopeType.Input, MaxNumberOfTracks), string.Format("Failed to set element count on 3DMixer [{0}]", MaxNumberOfTracks));

                    // set a null renderer callback to the channel and 3d mixer input bus
                    for (uint i = 0; i < MaxNumberOfTracks; i++)
                    {
                        CheckUnitStatus((AudioUnitStatus)SetInputRenderCallbackToNull(unit3DMixer.Handle, i), "Failed to set the render callback");
                        CheckUnitStatus((AudioUnitStatus)SetInputRenderCallbackToNull(unitChannelMixer.Handle, i), "Failed to set the render callback");
                    }

                    // Initialize the graph (validation of the topology)
                    CheckGraphError(audioGraph.Initialize(), "The audio graph initialization failed.");

                    // Start audio rendering
                    CheckGraphError(audioGraph.Start(), "Audio Graph could not start.");

                    // disable all the input bus at the beginning
                    for (uint i = 0; i < MaxNumberOfTracks; i++)
                    {
                        CheckUnitStatus(unitChannelMixer.SetParameter(AudioUnitParameterType.MultiChannelMixerEnable, 0f, AudioUnitScopeType.Input, i), "Failed to enable/disable the ChannelMixerInput.");
                        CheckUnitStatus(unit3DMixer.SetParameter((AudioUnitParameterType)_3DMixerParametersIds.Enable, 0f, AudioUnitScopeType.Input, i), "Failed to enable/disable the 3DMixerInput.");
                    }

                    // At initialization all UnitElement are available.
                    availableMixerBusIndices = new Queue <uint>();
                    for (uint i = 0; i < MaxNumberOfTracks; i++)
                    {
                        availableMixerBusIndices.Enqueue(i);
                    }
                }
                ++nbOfInstances;

                // Create a AudioDataRendererInfo for the sounds.
                pAudioDataRendererInfo = (AudioDataRendererInfo *)Utilities.AllocateClearedMemory(sizeof(AudioDataRendererInfo));
                pAudioDataRendererInfo->HandleChannelMixer = unitChannelMixer.Handle;
                pAudioDataRendererInfo->Handle3DMixer      = unit3DMixer.Handle;
            }
        }
Example #2
0
        public static AudioComponent FindComponent(AudioTypeMixer mixer)
        {
            var cd = AudioComponentDescription.CreateMixer(mixer);

            return(FindComponent(ref cd));
        }
        public void InitializeAUGraph()
        {
            Debug.Print("Initialize");

            LoadFiles();

            graph = new AUGraph();

            // create two AudioComponentDescriptions for the AUs we want in the graph

            // output unit
            var outputNode = graph.AddNode(AudioComponentDescription.CreateOutput(AudioTypeOutput.Remote));

            // mixer node
            var mixerNode = graph.AddNode(AudioComponentDescription.CreateMixer(AudioTypeMixer.MultiChannel));

            // connect a node's output to a node's input
            if (graph.ConnnectNodeInput(mixerNode, 0, outputNode, 0) != AUGraphError.OK)
            {
                throw new ApplicationException();
            }

            // open the graph AudioUnits are open but not initialized (no resource allocation occurs here)
            if (graph.TryOpen() != 0)
            {
                throw new ApplicationException();
            }

            mixer = graph.GetNodeInfo(mixerNode);

            // set bus count
            const uint numbuses = 2;

            Debug.Print("Set input bus count {0}", numbuses);

            if (mixer.SetElementCount(AudioUnitScopeType.Input, numbuses) != AudioUnitStatus.OK)
            {
                throw new ApplicationException();
            }

            AudioStreamBasicDescription desc;

            for (uint i = 0; i < numbuses; ++i)
            {
                // setup render callback
                if (graph.SetNodeInputCallback(mixerNode, i, HandleRenderDelegate) != AUGraphError.OK)
                {
                    throw new ApplicationException();
                }

                // set input stream format to what we want
                desc = mixer.GetAudioFormat(AudioUnitScopeType.Input, i);
                //desc.ChangeNumberChannels(2, false);
                desc.SampleRate = GraphSampleRate;

                mixer.SetAudioFormat(desc, AudioUnitScopeType.Input, i);
            }

            // set output stream format to what we want
            desc = mixer.GetAudioFormat(AudioUnitScopeType.Output);

            //desc.ChangeNumberChannels(2, false);
            desc.SampleRate = GraphSampleRate;

            mixer.SetAudioFormat(desc, AudioUnitScopeType.Output);

            // now that we've set everything up we can initialize the graph, this will also validate the connections
            if (graph.Initialize() != AUGraphError.OK)
            {
                throw new ApplicationException();
            }
        }