private void Apply3DImpl(AudioListener listener, AudioEmitter emitter)
        {
            var vectDirWorldBase = emitter.Position - listener.Position;
            var baseChangeMat = Matrix.Identity;
            baseChangeMat.Row2 = new Vector4(listener.Up, 0);
            baseChangeMat.Row3 = new Vector4(listener.Forward, 0);
            baseChangeMat.Row1 = new Vector4(Vector3.Cross(listener.Up, listener.Forward), 0);

            var vectDirListBase = Vector3.TransformNormal(vectDirWorldBase, baseChangeMat);
            var azimut = 180f * (float)(Math.Atan2(vectDirListBase.X, vectDirListBase.Z)/Math.PI);
            var elevation = 180f * (float)(Math.Atan2(vectDirListBase.Y, new Vector2(vectDirListBase.X, vectDirListBase.Z).Length())/Math.PI);
            var distance = vectDirListBase.Length();

            ComputeDopplerFactor(listener,emitter);

            AudioVoice.Apply3D(azimut, elevation, distance / emitter.DistanceScale, MathUtil.Clamp((float)Math.Pow(2, Pitch) * dopplerPitchFactor, 0.5f, 2f));
        }
Exemplo n.º 2
0
        internal void Apply3DImpl(AudioListener listener, AudioEmitter emitter)
        {
            //////////////////////////////////////////////////////////////
            // 1. First let's calculate the parameters to set to the voice
            var inputChannels = soundEffect.WaveFormat.Channels;
            var outputChannels = MasterVoice.VoiceDetails.InputChannelCount;

            if (inputChannels != 1 || outputChannels != 2)
                throw new AudioSystemInternalException("Error in Apply3DImpl only mono sounds are supposed to be localizable");

            var list = new Listener
                {
                    Position = listener.Position.ToSharpDX(), 
                    Velocity = listener.Velocity.ToSharpDX(),
                    OrientFront = listener.Forward.ToSharpDX(),
                    OrientTop = listener.Up.ToSharpDX()
                };
            var emit = new Emitter
                {
                    Position = emitter.Position.ToSharpDX(),
                    Velocity = emitter.Velocity.ToSharpDX(),
                    DopplerScaler = emitter.DopplerScale,
                    CurveDistanceScaler = emitter.DistanceScale,
                    ChannelRadius = 0f, // Multi-channels localizable sound are considered as source of multiple sounds coming from the same location.
                    ChannelCount = inputChannels
                };
            
            var dspSettings = new DspSettings(inputChannels, outputChannels);

            AudioEngine.X3DAudio.Calculate(list, emit, CalculateFlags.Matrix | CalculateFlags.LpfDirect, dspSettings);

            /////////////////////////////////////////////////////////////
            // 2. Now let's set the voice parameters to simulate a 3D voice.

            // 2.1 The Doppler effect due to the difference of speed between the emitter and listener
            ComputeDopplerFactor(listener, emitter);
            UpdatePitch();

            // 2.2 The channel attenuations due to the source localization.
            localizationChannelVolumes = new[] { dspSettings.MatrixCoefficients[0], dspSettings.MatrixCoefficients[1] };    // only mono sound can be localized so matrix should be 2*1
            UpdateStereoVolumes();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Applies 3D positioning to the sound. 
        /// More precisely adjust the channel volumes and pitch of the sound, 
        /// such that the sound source seems to come from the <paramref name="emitter"/> to the listener/>.
        /// </summary>
        /// <param name="emitter">The emitter that correspond to this sound</param>
        /// <remarks>
        /// <see cref="Apply3D"/> can be used only on mono-sounds.
        /// <para>
        /// The final resulting pitch depends on the listener and emitter relative velocity. 
        /// The final resulting channel volumes depend on the listener and emitter relative positions and the value of <see cref="IPlayableSound.Volume"/>. 
        /// </para>
        /// </remarks>
        public void Apply3D(AudioEmitter emitter)
        {
            if (engine.State == AudioEngineState.Invalidated)
                return;

            if (!spatialized) return;

            if (emitter == null)
                throw new ArgumentNullException(nameof(emitter));

           emitter.Apply3D(Source);
        }
Exemplo n.º 4
0
 public void Apply3D(AudioListener listener, AudioEmitter emitter)
 {
     DefaultInstance.Apply3D(listener, emitter);
 }
        private void Apply3DImpl(AudioListener listener, AudioEmitter emitter)
        {
            // Since android has no function available to perform sound 3D localization by default, here we try to mimic the behaviour of XAudio2

            // After an analysis of the XAudio2 left/right stereo balance with respect to 3D world position, 
            // it could be found the volume repartition is symmetric to the Up/Down and Front/Back planes.
            // Moreover the left/right repartition seems to follow a third degree polynomial function:
            // Volume_left(a) = 2(c-1)*a^3 - 3(c-1)*a^2 + c*a , where c is a constant close to c = 1.45f and a is the angle normalized bwt [0,1]
            // Volume_right(a) = 1-Volume_left(a)

            // As for signal attenuation wrt distance the model follows a simple inverse square law function as explained in XAudio2 documentation 
            // ( http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.x3daudio.x3daudio_emitter(v=vs.85).aspx )
            // Volume(d) = 1                    , if d <= ScaleDistance where d is the distance to the listener
            // Volume(d) = ScaleDistance / d    , if d >= ScaleDistance where d is the distance to the listener

            // 1. Attenuation due to distance.
            var vecListEmit = emitter.Position - listener.Position;
            var distListEmit = vecListEmit.Length();
            var attenuationFactor = distListEmit <= emitter.DistanceScale ? 1f : emitter.DistanceScale / distListEmit;

            // 2. Left/Right balance.
            var repartRight = 0.5f;
            var worldToList = Matrix.Identity;
            var rightVec = Vector3.Cross(listener.Forward, listener.Up);
            worldToList.Column1 = new Vector4(rightVec, 0);
            worldToList.Column2 = new Vector4(listener.Forward, 0);
            worldToList.Column3 = new Vector4(listener.Up, 0);
            var vecListEmitListBase = Vector3.TransformNormal(vecListEmit, worldToList);
            var vecListEmitListBase2 = (Vector2)vecListEmitListBase;
            if (vecListEmitListBase2.Length() > 0)
            {
                const float c = 1.45f;
                var absAlpha = Math.Abs(Math.Atan2(vecListEmitListBase2.Y, vecListEmitListBase2.X));
                var normAlpha = (float)(absAlpha / (Math.PI / 2));
                if (absAlpha > Math.PI / 2) normAlpha = 2 - normAlpha;
                repartRight = 0.5f * (2 * (c - 1) * normAlpha * normAlpha * normAlpha - 3 * (c - 1) * normAlpha * normAlpha * normAlpha + c * normAlpha);
                if (absAlpha > Math.PI / 2) repartRight = 1 - repartRight;
            }

            // Set the volumes.
            localizationChannelVolumes = new[] { attenuationFactor * (1f - repartRight), attenuationFactor * repartRight };
            UpdateStereoVolumes();

            // 3. Calculation of the Doppler effect
            ComputeDopplerFactor(listener, emitter);
            UpdatePitch();
        }
Exemplo n.º 6
0
 internal void Apply3DImpl(AudioListener listener, AudioEmitter emitter)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 7
0
 public void Apply3D(AudioListener listener, AudioEmitter emitter)
 {
     DefaultInstance.Apply3D(listener, emitter);
 }
Exemplo n.º 8
0
        private void ComputeDopplerFactor(AudioListener listener, AudioEmitter emitter)
        {
            // To evaluate the Doppler effect we calculate the distance to the listener from one wave to the next one and divide it by the sound speed
            // we use 343m/s for the sound speed which correspond to the sound speed in the air.
            // we use 600Hz for the sound frequency which correspond to the middle of the human hearable sounds frequencies.

            const float SoundSpeed = 343f;
            const float SoundFreq = 600f;
            const float SoundPeriod = 1 / SoundFreq;

            // avoid useless calculations.
            if (emitter.DopplerScale <= float.Epsilon || (emitter.Velocity == Vector3.Zero && listener.Velocity == Vector3.Zero))
            {
                dopplerPitchFactor = 1f;
                return;
            }

            var vecListEmit = emitter.Position - listener.Position;
            var distListEmit = vecListEmit.Length();

            var vecListEmitSpeed = emitter.Velocity - listener.Velocity;
            if (Vector3.Dot(vecListEmitSpeed, Vector3.Normalize(vecListEmit)) < -SoundSpeed) // emitter and listener are getting closer more quickly than the speed of the sound.
            {
                dopplerPitchFactor = float.PositiveInfinity; // will be clamped later
                return;
            }

            var timeSinceLastWaveArrived = 0f; // time elapsed since the previous wave arrived to the listener.
            var lastWaveDistToListener = 0f; // the distance that the last wave still have to travel to arrive to the listener.
            const float DistLastWave = SoundPeriod * SoundSpeed; // distance traveled by the previous wave.
            if (DistLastWave > distListEmit)
                timeSinceLastWaveArrived = (DistLastWave - distListEmit) / SoundSpeed;
            else
                lastWaveDistToListener = distListEmit - DistLastWave;
            var nextVecListEmit = vecListEmit + SoundPeriod * vecListEmitSpeed;
            var nextWaveDistToListener = nextVecListEmit.Length();
            var timeBetweenTwoWaves = timeSinceLastWaveArrived + (nextWaveDistToListener - lastWaveDistToListener) / SoundSpeed;
            var apparentFrequency = 1 / timeBetweenTwoWaves;
            dopplerPitchFactor = (float) Math.Pow(apparentFrequency / SoundFreq, emitter.DopplerScale);
        }
Exemplo n.º 9
0
        public void Apply3D(AudioListener listener, AudioEmitter emitter)
        {
            CheckNotDisposed();

            if (listener == null)
                throw new ArgumentNullException("listener");

            if(emitter == null)
                throw new ArgumentNullException("emitter");

            if(soundEffect.WaveFormat.Channels > 1)
                throw new InvalidOperationException("Apply3D cannot be used on multi-channels sounds.");

            // reset Pan its default values.
            if (Pan != 0)
                Pan = 0;

            if (EngineState != AudioEngineState.Invalidated)
                Apply3DImpl(listener, emitter);
        }
Exemplo n.º 10
0
 internal void Apply3DImpl(AudioListener listener, AudioEmitter emitter)
 {
     throw new NotImplementedException();
 }