Example #1
0
        //prevent creation of SoundEffectInstance to the user
        internal SoundEffectInstance(SoundEffect correspSoundEffect)
        {
            AttachEngine(correspSoundEffect.AudioEngine);
            soundEffect = correspSoundEffect;
            
            if (EngineState != AudioEngineState.Invalidated)
                CreateVoice(soundEffect.WaveFormat);

            ResetStateToDefault();
        }
Example #2
0
        /// <summary>
        /// Create and Load a sound effect from an input wav stream.
        /// </summary>
        /// <param name="engine">Name of the audio engine in which to create the sound effect</param>
        /// <param name="stream">A stream corresponding to a wav file.</param>
        /// <returns>A new instance soundEffect ready to be played</returns>
        /// <exception cref="ArgumentNullException"><paramref name="engine"/> or <paramref name="stream"/> is null.</exception>
        /// <exception cref="NotSupportedException">The wave file or has more than 2 channels or is not encoded in 16bits.</exception>
        /// <exception cref="InvalidOperationException">The content of the stream does not correspond to a valid wave file.</exception>
        /// <exception cref="OutOfMemoryException">There is not enough memory anymore to load the specified file in memory. </exception>
        /// <exception cref="ObjectDisposedException">The audio engine has already been disposed</exception>
        /// <remarks>Supported WAV files' audio format is the 16bits PCM format.</remarks>
        public static SoundEffect Load(AudioEngine engine, Stream stream)
        {
            if(engine == null)
                throw new ArgumentNullException("engine");

            var newSdEff = new SoundEffect(engine);
            newSdEff.Load(stream);

            return newSdEff;
        }
        /// <summary>
        /// Detach a <see cref="SoundEffect"/> from this emitter component.
        /// Once detach the controller previously associated to the SoundEffect is invalid.
        /// </summary>
        /// <param name="soundEffect">The soundEffect to detach.</param>
        /// <exception cref="ArgumentNullException">The provided <paramref name="soundEffect"/> is null.</exception>
        /// <exception cref="ArgumentException">The provided <paramref name="soundEffect"/> is not currently attached to the emitter component.</exception>
        public void DetachSoundEffect(SoundEffect soundEffect)
        {
            if (soundEffect == null)
            {
                throw new ArgumentNullException("soundEffect");
            }
            if (!SoundEffectToController.ContainsKey(soundEffect))
            {
                throw new ArgumentException("The provided soundEffect is not currently attached to this emitter component.");
            }

            var oldController = SoundEffectToController[soundEffect];
            SoundEffectToController.Remove(soundEffect);
            if (ControllerCollectionChanged != null)
                ControllerCollectionChanged.Invoke(this, new ControllerCollectionChangedEventArgs(Entity, oldController, NotifyCollectionChangedAction.Remove));
        }
        /// <summary>
        /// Attach a <see cref="SoundEffect"/> to this emitter component.
        /// Once attached a <see cref="AudioEmitterSoundController"/> can be queried using <see cref="GetSoundEffectController"/> to control the attached SoundEffect.
        /// </summary>
        /// <param name="soundEffect">The SoundEffect to attach</param>
        /// <exception cref="ArgumentNullException">The provided <paramref name="soundEffect"/> is null.</exception>
        /// <exception cref="InvalidOperationException">The provided <paramref name="soundEffect"/> can not be localized (contains more than one channel).</exception>
        /// <remarks>Attaching a soundEffect already attached has no effects.</remarks>
        public void AttachSoundEffect(SoundEffect soundEffect)
        {
            if (soundEffect == null)
            {
                throw new ArgumentNullException("soundEffect");
            }
            if (soundEffect.WaveFormat.Channels > 1)
            {
                throw new InvalidOperationException("The provided SoundEffect has more than one channel. It can not be localized in the 3D scene.");
            }

            if(SoundEffectToController.ContainsKey(soundEffect))
                return;

            var newController = new AudioEmitterSoundController(this, soundEffect);
            SoundEffectToController[soundEffect] = newController;
            if(ControllerCollectionChanged != null)
                ControllerCollectionChanged.Invoke(this, new ControllerCollectionChangedEventArgs(Entity, newController, NotifyCollectionChangedAction.Add ));
        }
        /// <summary>
        /// Return a <see cref="AudioEmitterSoundController"/> that can be used to control the provided <see cref="SoundEffect"/>.
        /// </summary>
        /// <param name="soundEffect">The soundEffect that the user want to control.</param>
        /// <returns>The controller that can control the <paramref name="soundEffect"/></returns>
        /// <exception cref="ArgumentNullException">The provided <paramref name="soundEffect"/> is null.</exception>
        /// <exception cref="ArgumentException">The provided <paramref name="soundEffect"/> is not attached to this component.</exception>
        /// <remarks>The return AudioEmitterSoundController is valid as long as 
        /// (1) the associated soundEffect is attached to the emitter, 
        /// (2) the associated soundEffect is not disposed and,
        /// (3) the emitter component's entity is present into Entity system.</remarks>
        public AudioEmitterSoundController GetSoundEffectController(SoundEffect soundEffect)
        {
            if (soundEffect == null)
            {
                throw new ArgumentNullException("soundEffect");
            }
            if (!SoundEffectToController.ContainsKey(soundEffect))
            {
                throw new ArgumentException("The provided soundEffect has not been attached to the EmitterComponent.");
            }

            return SoundEffectToController[soundEffect];
        }
Example #6
0
 //prevent creation of SoundEffectInstance to the user and other classes
 internal SoundEffectInstance()
 {
     soundEffect = null;
 }
Example #7
0
        public void SetAudioData(SoundEffect soundEffect)
        {
            BusIndexMixer = uint.MaxValue; // invalid index value (when no bus are free)

            // find a available bus indices for this instance.
            if (availableMixerBusIndices.Count > 0)
                BusIndexMixer = availableMixerBusIndices.Dequeue();
            else
            {
                // force the update of all sound effect instance to free bus indices
                audioEngine.ForceSoundEffectInstanceUpdate();

                // retry to get an free bus index
                if (availableMixerBusIndices.Count > 0)
                {
                    BusIndexMixer = availableMixerBusIndices.Dequeue();
                }
                else // try to stop another instance
                {
                    // try to get a sound effect to stop
                    var soundEffectToStop = audioEngine.GetLeastSignificativeSoundEffect();
                    if (soundEffectToStop == null) // no available sound effect to stop -> give up the creation of the track
                        return;

                    // stop the sound effect instances and retry to get an available track
                    soundEffectToStop.StopAllInstances();

                    // retry to get an free bus index
                    if (availableMixerBusIndices.Count > 0)
                        BusIndexMixer = availableMixerBusIndices.Dequeue();
                    else
                        return;
                }
            }

            // Set the audio stream format of the current mixer input bus.
            unitChannelMixer.SetAudioFormat(CreateLinear16BitsPcm(waveFormat.Channels, waveFormat.SampleRate), AudioUnitScopeType.Input, BusIndexMixer);

            // set the channel input bus callback
            CheckUnitStatus((AudioUnitStatus)SetInputRenderCallbackToChannelMixerDefault(unitChannelMixer.Handle, BusIndexMixer, (IntPtr)pAudioDataRendererInfo), "Failed to set the render callback");
                    
            ResetChannelMixerParameter();

            // initialize the 3D mixer input bus, if the sound can be used as 3D sound.
            if (waveFormat.Channels == 1)
            {
                // Set the audio stream format of the current mixer input bus.
                unit3DMixer.SetAudioFormat(CreateLinear16BitsPcm(waveFormat.Channels, waveFormat.SampleRate), AudioUnitScopeType.Input, BusIndexMixer);

                // set the 3D mixer input bus callback
                CheckUnitStatus((AudioUnitStatus)SetInputRenderCallbackTo3DMixerDefault(unit3DMixer.Handle, BusIndexMixer, (IntPtr)pAudioDataRendererInfo), "Failed to set the render callback");

                Reset3DMixerParameter();
            }

            // Disable the input by default so that it started in Stopped mode.
            EnableMixerCurrentInput(false);

            // set render info data 
            pAudioDataRendererInfo->AudioDataBuffer = soundEffect.WaveDataPtr;
            pAudioDataRendererInfo->TotalNumberOfFrames = (soundEffect.WaveDataSize / waveFormat.BlockAlign);
            pAudioDataRendererInfo->NumberOfChannels = waveFormat.Channels;

            // reset playback to the beginning of the track and set the looping status
            pAudioDataRendererInfo->CurrentFrame = 0;
            SetLoopingPoints(0, int.MaxValue, 0, pAudioDataRendererInfo->IsInfiniteLoop);
            SetVolume(soundEffectInstance.Volume);
            SetPan(soundEffectInstance.Pan);
        }
 //prevent creation of SoundEffectInstance to the user and other classes
 internal SoundEffectInstance(AudioEngine engine)
     : base(engine)
 {
     soundEffect = null;
 }