/// <summary> /// Updates internal state /// </summary> internal void Update() { if (this.Effect.GameAudio.UseReverb && !isReverbSubmixEnabled) { var sendFlags = this.Effect.GameAudio.UseReverbFilter ? VoiceSendFlags.UseFilter : VoiceSendFlags.None; var outputVoices = new VoiceSendDescriptor[] { new VoiceSendDescriptor { OutputVoice = this.Effect.GameAudio.MasteringVoice, Flags = sendFlags }, new VoiceSendDescriptor { OutputVoice = this.Effect.GameAudio.ReverbVoice, Flags = sendFlags } }; voice.SetOutputVoices(outputVoices); isReverbSubmixEnabled = true; } if (this.Effect.GameAudio.UseAudio3D) { this.Apply3D(); } this.SetPanOutputMatrix(); }
public void SetOutputVoices(VoiceSendDescriptor[] descriptors) { if (m_currentDescriptor != descriptors) { m_voice.SetOutputVoices(descriptors); m_currentDescriptor = descriptors; } }
internal void PlatformSetReverbMix(float mix) { // At least for XACT we can't go over 2x the volume on the mix. _reverbMix = MathHelper.Clamp(mix, 0, 2); // If we have no voice then nothing more to do. if (_voice == null) { return; } if (!(_reverbMix > 0.0f)) { _voice.SetOutputVoices(new VoiceSendDescriptor(SoundEffect.MasterVoice)); } else { _voice.SetOutputVoices(new VoiceSendDescriptor(SoundEffect.ReverbVoice), new VoiceSendDescriptor(SoundEffect.MasterVoice)); } UpdateOutputMatrix(); }
private void SetupVoice(AudioFormat format) { WaveFormat wFmt = new WaveFormat(format.SampleRate, format.BitsPerSample, format.Channels); SourceVoice = new SourceVoice(_engine.Device, wFmt); if (_submixer != null) { var vsDesc = new VoiceSendDescriptor(_submixer.SubMixerVoice); SourceVoice.SetOutputVoices(new VoiceSendDescriptor[] { vsDesc }); } SourceVoice.SetVolume(_volume); }
public VoicePool(XAudio2 xAudio2, Voice masterVoice) { _objects = new ConcurrentDictionary <WaveFormat, ConcurrentBag <SourceVoiceEx> >(); _objectGenerator = format => { var newVoice = new SourceVoice(xAudio2, format, VoiceFlags.None, 3.0f, true); newVoice.SetOutputVoices(new[] { new VoiceSendDescriptor(masterVoice) }); var newId = Interlocked.Increment(ref _nextOperationId); var sourceVoiceEx = new SourceVoiceEx(newVoice, Guid.NewGuid(), format, newId); return(sourceVoiceEx); }; }
public void NoteOn(byte num, byte key, byte velocity) { try { Instrument instrument = instrumentTable[new Tuple <byte, byte>(Bank, Instrument)]; int value = instrument.GetSampleEntry(key).Value; Sample sample = soundData.SampleBanks[soundData.InstrumentBanks[Bank].Wsys][(short)instrument.Samples[value].Id]; AudioBuffer audioBuffer = new AudioBuffer(); audioBuffer.AudioBytes = sample.Data.Length; audioBuffer.Stream = new DataStream(sample.Data.Length, canRead: true, canWrite: true); audioBuffer.Stream.Write(sample.Data, 0, sample.Data.Length); audioBuffer.PlayBegin = 0; audioBuffer.PlayLength = 0; audioBuffer.LoopCount = (sample.IsLooping ? 255 : 0); audioBuffer.LoopBegin = sample.LoopStart; audioBuffer.LoopLength = 0; WaveFormat sourceFormat = new WaveFormat(sample.SamplesPerSecond, sample.BitsPerSample, sample.Channels); SourceVoice sourceVoice = new SourceVoice(engine, sourceFormat, VoiceFlags.None, 1024f); sourceVoice.SetOutputVoices(new VoiceSendDescriptor(submix)); sourceVoice.SubmitSourceBuffer(audioBuffer, null); float num2 = XAudio2.SemitonesToFrequencyRatio((!instrument.IsPercussion) ? (key - sample.RootKey) : 0) * instrument.Samples[value].FrequenyMultiplier * instrument.FrequencyMultiplier; sourceVoice.SetFrequencyRatio(num2); sourceVoice.SetVolume(ValueToAmplitude(velocity)); NoteData noteData = new NoteData(sourceVoice, num2, velocity, instrument.IsPercussion); if (instrument.IsPercussion) { noteData.PercussionPan = instrument.Samples[value].Pan.Value; sbyte b = (sbyte)(noteData.PercussionPan - 63); sourceVoice.SetOutputMatrix(1, 2, new float[2] { 0.5f - (float)b / 127f, 0.5f + (float)b / 127f }); } else { sourceVoice.SetOutputMatrix(1, 2, outputMatrix); } noteData.BufferStream = audioBuffer.Stream; noteData.Voice.Start(); voiceTable.Add(num, noteData); sourceFormat = null; GC.Collect(); } catch { } }
private void PlaySound(int soundID, Emitter emitter, float volume, LinkedSoundList list, ref VoiceSendDescriptor voiceSendDescriptor, Action <IntPtr>?onFxEnd = null) { if (!_soundBuffer.TryGetValue(soundID, out SoundBuffer buffer)) { return; } SourceVoice sourceVoice = new SourceVoice(_xAudio2, buffer.Format, VoiceFlags.None, true); sourceVoice.SetVolume(volume); sourceVoice.SubmitSourceBuffer(buffer.AudioBuffer, buffer.DecodedPacketsInfo); sourceVoice.SetOutputVoices(voiceSendDescriptor); LinkedSoundList.Sound sound = new LinkedSoundList.Sound(emitter, sourceVoice); list.Add(sound); sourceVoice.BufferEnd += _ => { list.Remove(sound); sourceVoice.DestroyVoice(); }; if (onFxEnd != null) { sourceVoice.BufferEnd += onFxEnd; } sourceVoice.Start(); DspSettings settings = _x3DAudio.Calculate( _listener, sound.Emitter, CalculateFlags.Matrix | CalculateFlags.Doppler, buffer.Format.Channels, _inputChannelCount); sound.SourceVoice.SetOutputMatrix(buffer.Format.Channels, _inputChannelCount, settings.MatrixCoefficients); sound.SourceVoice.SetFrequencyRatio(settings.DopplerFactor); }
/// <summary> /// Dispose resources /// </summary> /// <param name="disposing">Free managed resources</param> protected virtual void Dispose(bool disposing) { if (disposing) { if (voice != null) { voice.BufferStart -= SourceVoice_BufferStart; voice.BufferEnd -= SourceVoice_BufferEnd; voice.LoopEnd -= SourceVoice_LoopEnd; } voice?.Stop(0); voice?.FlushSourceBuffers(); if (isReverbSubmixEnabled) { voice?.SetOutputVoices(null); isReverbSubmixEnabled = false; } voice?.DestroyVoice(); voice?.Dispose(); voice = null; } }
private void Apply3D(Vector3 listenerForward, Vector3 listenerUp, Vector3 listenerPosition, Vector3 listenerVelocity, Vector3 emitterForward, Vector3 emitterUp, Vector3 emitterPosition, Vector3 emitterVelocity) { if (!Effect.AudioManager.IsSpatialAudioEnabled) { throw new InvalidOperationException("Spatial audio must be enabled first."); } if (emitter == null) { emitter = new Emitter(); } emitter.OrientFront = emitterForward; emitter.OrientTop = emitterUp; emitter.Position = emitterPosition; emitter.Velocity = emitterVelocity; emitter.DopplerScaler = SoundEffect.DopplerScale; emitter.CurveDistanceScaler = SoundEffect.DistanceScale; emitter.ChannelCount = Effect.Format.Channels; //TODO: work out what ChannelAzimuths is supposed to be. if (emitter.ChannelCount > 1) { emitter.ChannelAzimuths = new float[emitter.ChannelCount]; } if (listener == null) { listener = new Listener(); } listener.OrientFront = listenerForward; listener.OrientTop = listenerUp; listener.Position = listenerPosition; listener.Velocity = listenerVelocity; if (dspSettings == null) { dspSettings = new DspSettings(Effect.Format.Channels, Effect.AudioManager.MasteringVoice.VoiceDetails.InputChannelCount); } CalculateFlags flags = CalculateFlags.Matrix | CalculateFlags.Doppler | CalculateFlags.LpfDirect; if ((Effect.AudioManager.Speakers & Speakers.LowFrequency) > 0) { // On devices with an LFE channel, allow the mono source data to be routed to the LFE destination channel. flags |= CalculateFlags.RedirectToLfe; } if (Effect.AudioManager.IsReverbEffectEnabled) { flags |= CalculateFlags.Reverb | CalculateFlags.LpfReverb; if (!isReverbSubmixEnabled) { VoiceSendFlags sendFlags = Effect.AudioManager.IsReverbFilterEnabled ? VoiceSendFlags.UseFilter : VoiceSendFlags.None; VoiceSendDescriptor[] outputVoices = new VoiceSendDescriptor[] { new VoiceSendDescriptor { OutputVoice = Effect.AudioManager.MasteringVoice, Flags = sendFlags }, new VoiceSendDescriptor { OutputVoice = Effect.AudioManager.ReverbVoice, Flags = sendFlags } }; voice.SetOutputVoices(outputVoices); isReverbSubmixEnabled = true; } } Effect.AudioManager.Calculate3D(listener, emitter, flags, dspSettings); voice.SetFrequencyRatio(dspSettings.DopplerFactor); voice.SetOutputMatrix(Effect.AudioManager.MasteringVoice, dspSettings.SourceChannelCount, dspSettings.DestinationChannelCount, dspSettings.MatrixCoefficients); if (Effect.AudioManager.IsReverbEffectEnabled) { if (reverbLevels == null || reverbLevels.Length != Effect.Format.Channels) { reverbLevels = new float[Effect.Format.Channels]; } for (int i = 0; i < reverbLevels.Length; i++) { reverbLevels[i] = dspSettings.ReverbLevel; } voice.SetOutputMatrix(Effect.AudioManager.ReverbVoice, Effect.Format.Channels, 1, reverbLevels); } if (Effect.AudioManager.IsReverbFilterEnabled) { FilterParameters filterDirect = new FilterParameters { Type = FilterType.LowPassFilter, // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here Frequency = 2.0f * (float)Math.Sin(X3DAudio.PI / 6.0f * dspSettings.LpfDirectCoefficient), OneOverQ = 1.0f }; voice.SetOutputFilterParameters(Effect.AudioManager.MasteringVoice, filterDirect); if (Effect.AudioManager.IsReverbEffectEnabled) { FilterParameters filterReverb = new FilterParameters { Type = FilterType.LowPassFilter, // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here Frequency = 2.0f * (float)Math.Sin(X3DAudio.PI / 6.0f * dspSettings.LpfReverbCoefficient), OneOverQ = 1.0f }; voice.SetOutputFilterParameters(Effect.AudioManager.ReverbVoice, filterReverb); } } }