/// <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();
        }
예제 #2
0
 public void SetOutputVoices(VoiceSendDescriptor[] descriptors)
 {
     if (m_currentDescriptor != descriptors)
     {
         m_voice.SetOutputVoices(descriptors);
         m_currentDescriptor = descriptors;
     }
 }
예제 #3
0
        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();
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
            };
        }
예제 #6
0
파일: Playback.cs 프로젝트: XAYRGA/JPlay
 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
     {
     }
 }
예제 #7
0
        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;
            }
        }
예제 #9
0
        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);
                }
            }
        }