//prevent creation of SoundEffectInstance to the user internal SoundEffectInstance(SoundEffect correspSoundEffect) { AttachEngine(correspSoundEffect.AudioEngine); soundEffect = correspSoundEffect; if (EngineState != AudioEngineState.Invalidated) CreateVoice(soundEffect.WaveFormat); ResetStateToDefault(); }
/// <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]; }
//prevent creation of SoundEffectInstance to the user and other classes internal SoundEffectInstance() { soundEffect = null; }
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; }