예제 #1
0
        unsafe protected override void OnDispose()
        {
            DirectSoundWorld.criticalSection.Enter();

            if (soundBuffers.Count != freeSoundBuffers.Count)
            {
                Log.Fatal("DirectSound.OnDispose: soundBuffers.Count == freeSoundBuffers.Count");
            }

            for (int n = soundBuffers.Count - 1; n >= 0; n--)
            {
                IDirectSoundBuffer *soundBuffer = (IDirectSoundBuffer *)soundBuffers[n].ToPointer();
                IDirectSoundBuffer.Release(soundBuffer);
            }
            soundBuffers.Clear();
            freeSoundBuffers.Clear();

            if (waveFormat != null)
            {
                NativeUtils.Free((IntPtr)waveFormat);
                waveFormat = null;
            }

            DirectSoundWorld.criticalSection.Leave();

            base.OnDispose();
        }
예제 #2
0
        public unsafe IDirectSoundBuffer *GetBuffer(int needBufferSize)
        {
            if (freeSoundBuffers.Count == 0)
            {
                IDirectSoundBuffer *soundBuffer = CreateBuffer(needBufferSize);
                if (soundBuffer == null)
                {
                    return(null);
                }

                soundBuffers.Add((IntPtr)soundBuffer);
                freeSoundBuffers.Push((IntPtr)soundBuffer);
            }

            if (soundBuffers.Count >= 256)
            {
                Log.Fatal("DirectSound.GetBuffer: soundBuffers.Count >= 256.");
            }

            return((IDirectSoundBuffer *)freeSoundBuffers.Pop().ToPointer());
        }
예제 #3
0
        public unsafe bool RestoreSoundBuffers(out bool restored)
        {
            IDirectSoundBuffer *soundBuffer = (IDirectSoundBuffer *)soundBuffers[0].ToPointer();

            int hr;

            restored = false;

            uint status;

            hr = IDirectSoundBuffer.GetStatus(soundBuffer, out status);
            if (Wrapper.FAILED(hr))
            {
                DirectSoundWorld.Warning("IDirectSoundBuffer.GetStatus", hr);
                return(false);
            }

            if ((status & DSound.DSBSTATUS_BUFFERLOST) != 0)
            {
                int DSERR_BUFFERLOST = DSound.Get_DSERR_BUFFERLOST();

                // Since the app could have just been activated, then
                // DirectSound may not be giving us control yet, so
                // the restoring the buffer may fail.
                // If it does, sleep until DirectSound gives us control.
                do
                {
                    hr = IDirectSoundBuffer.Restore(soundBuffer);
                    if (hr == DSERR_BUFFERLOST)
                    {
                        Thread.Sleep(10);
                    }
                }while((hr = IDirectSoundBuffer.Restore(soundBuffer)) == DSERR_BUFFERLOST);

                restored = true;
            }

            return(true);
        }
예제 #4
0
        unsafe public bool FillSoundBuffersWithData()
        {
            IDirectSoundBuffer *soundBuffer = (IDirectSoundBuffer *)soundBuffers[0].ToPointer();

            int hr;

            void *lockedBuffer     = null;
            uint  lockedBufferSize = 0;

            hr = IDirectSoundBuffer.Lock(soundBuffer, 0, (uint)soundSamples.Length,
                                         &lockedBuffer, &lockedBufferSize, (void **)null, (uint *)null, 0);

            if (Wrapper.FAILED(hr))
            {
                DirectSoundWorld.Warning("IDirectSoundBuffer.Lock", hr);
                return(false);
            }

            if ((int)lockedBufferSize < soundSamples.Length)
            {
                Log.Fatal("DirectSampleSound.FillSoundBuffersWithData: " +
                          "lockedBufferSize >= soundSamples->Length");
            }

            Marshal.Copy(soundSamples, 0, (IntPtr)lockedBuffer, soundSamples.Length);

            if (soundSamples.Length < (int)lockedBufferSize)
            {
                // fill with silence remaining bytes
                NativeUtils.FillMemory((IntPtr)((byte *)lockedBuffer + soundSamples.Length),
                                       (int)lockedBufferSize - soundSamples.Length,
                                       (byte)(waveFormat->wBitsPerSample == 8 ? 128 : 0));
            }

            IDirectSoundBuffer.Unlock(soundBuffer, lockedBuffer, lockedBufferSize, (void *)null, 0);

            return(true);
        }
        unsafe protected override void PreDetachVirtualChannel()
        {
            DirectSoundWorld.criticalSection.Enter();

            DirectFileStreamSound currentFileStreamSound = currentSound as DirectFileStreamSound;

            if (currentFileStreamSound != null)
            {
                DirectSoundWorld.Instance.fileStreamRealChannels.Remove(this);
            }

            if (currentSound3DBuffer != null)
            {
                IDirectSound3DBuffer8.Release(currentSound3DBuffer);
                currentSound3DBuffer = null;
            }

            if (currentSoundBuffer != null)
            {
                IDirectSoundBuffer.Stop(currentSoundBuffer);
                currentSound.FreeBuffer(currentSoundBuffer);
                currentSoundBuffer = null;
            }

            if (streamBuffer != null)
            {
                NativeUtils.Free((IntPtr)streamBuffer);
                streamBuffer = null;
            }
            needStopAfterBufferRead = false;
            streamBufferLength      = 0;

            needStopVirtualChannel = false;

            currentSound = null;

            DirectSoundWorld.criticalSection.Leave();
        }
예제 #6
0
 public unsafe void FreeBuffer(IDirectSoundBuffer *soundBuffer)
 {
     freeSoundBuffers.Push((IntPtr)soundBuffer);
 }
        unsafe void UpdateVolume2()
        {
            float value = CurrentVirtualChannel.GetTotalVolume() * CurrentVirtualChannel.GetRolloffFactor();

            int volume;

            if (value > 0.001f)
            {
                volume = (int)(20.0f * 100.0f * Math.Log10(value));
            }
            else
            {
                volume = DSound.DSBVOLUME_MIN;
            }

            if (volume < DSound.DSBVOLUME_MIN)
            {
                volume = DSound.DSBVOLUME_MIN;
            }
            if (volume > DSound.DSBVOLUME_MAX)
            {
                volume = DSound.DSBVOLUME_MAX;
            }

            //update volume for dublicate buffers (IDirectSoundBuffer8.SetVolume problem)
            //it need have volume not equal to original buffer.
            bool isOriginalBuffer = false;
            IDirectSoundBuffer *originalBuffer = (IDirectSoundBuffer *)
                                                 currentSound.soundBuffers[0].ToPointer();

            isOriginalBuffer = originalBuffer == currentSoundBuffer;

            if (!isOriginalBuffer)
            {
                int originalBufferVolume = 0;
                IDirectSoundBuffer.GetVolume(originalBuffer, out originalBufferVolume);

                if (volume == originalBufferVolume)
                {
                    if (volume == DSound.DSBVOLUME_MAX)
                    {
                        volume = DSound.DSBVOLUME_MAX - 1;
                    }
                    else
                    {
                        volume++;
                    }
                }
            }

            //change volume
            int hr = IDirectSoundBuffer.SetVolume(currentSoundBuffer, volume);

            if (Wrapper.FAILED(hr))
            {
                DirectSoundWorld.Warning("IDirectSoundBuffer.SetVolume", hr);
            }

            //update volume of dublicate buffers
            if (isOriginalBuffer)
            {
                List <DirectSoundRealChannel> realChannels = DirectSoundWorld.Instance.realChannels;
                for (int nRealChannel = 0; nRealChannel < realChannels.Count; nRealChannel++)
                {
                    DirectSoundRealChannel realChannel = realChannels[nRealChannel];
                    if (realChannel != this && realChannel.currentSound == currentSound)
                    {
                        realChannel.UpdateVolume();
                    }
                }
            }
        }
        unsafe protected override void PostAttachVirtualChannel()
        {
            DirectSoundWorld.criticalSection.Enter();

            int hr;

            currentSound = (DirectSound)CurrentVirtualChannel.CurrentSound;

            bool mode3d = (int)(currentSound.Mode & SoundMode.Mode3D) != 0;
            bool loop   = (int)(currentSound.Mode & SoundMode.Loop) != 0;

            //DirectSampleSound
            DirectSampleSound currentSampleSound = currentSound as DirectSampleSound;

            if (currentSampleSound != null)
            {
                int lastBufferCount = currentSound.soundBuffers.Count;

                currentSoundBuffer = currentSound.GetBuffer(currentSampleSound.soundSamples.Length);
                if (currentSoundBuffer == null)
                {
                    PreDetachVirtualChannel();
                    DirectSoundWorld.criticalSection.Leave();
                    return;
                }

                bool needFillData = false;

                if (lastBufferCount == 0)
                {
                    needFillData = true;
                }

                bool restored = false;
                if (!currentSound.RestoreSoundBuffers(out restored))
                {
                    PreDetachVirtualChannel();
                    DirectSoundWorld.criticalSection.Leave();
                    return;
                }
                if (restored)
                {
                    needFillData = true;
                }

                if (needFillData)
                {
                    if (!currentSampleSound.FillSoundBuffersWithData())
                    {
                        PreDetachVirtualChannel();
                        DirectSoundWorld.criticalSection.Leave();
                        return;
                    }
                }
            }

            //DirectFileStreamSound, DirectDataStreamSound
            DirectFileStreamSound currentFileStreamSound = currentSound as DirectFileStreamSound;
            DirectDataStreamSound currentDataStreamSound = currentSound as DirectDataStreamSound;

            if (currentFileStreamSound != null || currentDataStreamSound != null)
            {
                int needBufferSize;

                if (currentFileStreamSound != null)
                {
                    int numSamples = (int)currentFileStreamSound.vorbisFile.pcm_total(-1);
                    int channels;
                    int rate;
                    currentFileStreamSound.vorbisFile.get_info(-1, out channels, out rate);
                    int sizeInBytes = numSamples * channels * 2;

                    needBufferSize = sizeInBytes / 2;

                    if (needBufferSize > 65536 * 2)
                    {
                        needBufferSize = 65536 * 2;
                    }
                }
                else
                {
                    needBufferSize = currentDataStreamSound.creationBufferSize;
                }

                currentSoundBuffer = currentSound.GetBuffer(needBufferSize);
                if (currentSoundBuffer == null)
                {
                    PreDetachVirtualChannel();
                    DirectSoundWorld.criticalSection.Leave();
                    return;
                }

                streamBuffer = (byte *)NativeUtils.Alloc(NativeMemoryAllocationType.SoundAndVideo,
                                                         currentSound.bufferSize);
                streamBufferLength = 0;

                bool restored = false;
                if (!currentSound.RestoreSoundBuffers(out restored))
                {
                    PreDetachVirtualChannel();
                    DirectSoundWorld.criticalSection.Leave();
                    return;
                }
                if (restored)
                {
                    //buffer will be cleared in the BeginStreamPlay()
                }
            }

            //currentSound3DBuffer
            if (mode3d)
            {
                void */*IDirectSound3DBuffer8*/ sound3DBuffer;

                GUID guid = DSound.IID_IDirectSound3DBuffer8;
                hr = IDirectSoundBuffer.QueryInterface(currentSoundBuffer, ref guid, &sound3DBuffer);
                if (Wrapper.FAILED(hr))
                {
                    PreDetachVirtualChannel();
                    DirectSoundWorld.Warning("IDirectSoundBuffer.QueryInterface", hr);
                    DirectSoundWorld.criticalSection.Leave();
                    return;
                }
                currentSound3DBuffer = (IDirectSound3DBuffer8 *)sound3DBuffer;
            }

            //update parameters
            if (mode3d)
            {
                UpdatePosition2();
                UpdateVelocity2();
            }
            else
            {
                UpdatePan2();
            }
            UpdatePitch2();
            UpdateVolume2();

            UpdateTime2();

            if (currentFileStreamSound != null || currentDataStreamSound != null)
            {
                BeginStreamPlay();
            }

            uint playFlags = 0;

            if (loop || currentFileStreamSound != null || currentDataStreamSound != null)
            {
                playFlags |= DSound.DSBPLAY_LOOPING;
            }

            hr = IDirectSoundBuffer.Play(currentSoundBuffer, 0, 0, playFlags);
            if (Wrapper.FAILED(hr))
            {
                PreDetachVirtualChannel();
                DirectSoundWorld.Warning("IDirectSoundBuffer.Play", hr);
                DirectSoundWorld.criticalSection.Leave();
                return;
            }

            if (currentFileStreamSound != null)
            {
                DirectSoundWorld.Instance.fileStreamRealChannels.Add(this);
            }

            needStopVirtualChannel = false;

            DirectSoundWorld.criticalSection.Leave();
        }
예제 #9
0
		unsafe protected override void PreDetachVirtualChannel()
		{
			DirectSoundWorld.criticalSection.Enter();

			DirectFileStreamSound currentFileStreamSound = currentSound as DirectFileStreamSound;
			if( currentFileStreamSound != null )
				DirectSoundWorld.Instance.fileStreamRealChannels.Remove( this );

			if( currentSound3DBuffer != null )
			{
				IDirectSound3DBuffer8.Release( currentSound3DBuffer );
				currentSound3DBuffer = null;
			}

			if( currentSoundBuffer != null )
			{
				IDirectSoundBuffer.Stop( currentSoundBuffer );
				currentSound.FreeBuffer( currentSoundBuffer );
				currentSoundBuffer = null;
			}

			if( streamBuffer != null )
			{
				NativeUtils.Free( (IntPtr)streamBuffer );
				streamBuffer = null;
			}
			needStopAfterBufferRead = false;
			streamBufferLength = 0;

			needStopVirtualChannel = false;

			currentSound = null;

			DirectSoundWorld.criticalSection.Leave();
		}
예제 #10
0
		unsafe protected override void PostAttachVirtualChannel()
		{
			DirectSoundWorld.criticalSection.Enter();

			int hr;

			currentSound = (DirectSound)CurrentVirtualChannel.CurrentSound;

			bool mode3d = (int)( currentSound.Mode & SoundMode.Mode3D ) != 0;
			bool loop = (int)( currentSound.Mode & SoundMode.Loop ) != 0;

			//DirectSampleSound
			DirectSampleSound currentSampleSound = currentSound as DirectSampleSound;
			if( currentSampleSound != null )
			{
				int lastBufferCount = currentSound.soundBuffers.Count;

				currentSoundBuffer = currentSound.GetBuffer( currentSampleSound.soundSamples.Length );
				if( currentSoundBuffer == null )
				{
					PreDetachVirtualChannel();
					DirectSoundWorld.criticalSection.Leave();
					return;
				}

				bool needFillData = false;

				if( lastBufferCount == 0 )
					needFillData = true;

				bool restored = false;
				if( !currentSound.RestoreSoundBuffers( out restored ) )
				{
					PreDetachVirtualChannel();
					DirectSoundWorld.criticalSection.Leave();
					return;
				}
				if( restored )
					needFillData = true;

				if( needFillData )
				{
					if( !currentSampleSound.FillSoundBuffersWithData() )
					{
						PreDetachVirtualChannel();
						DirectSoundWorld.criticalSection.Leave();
						return;
					}
				}
			}

			//DirectFileStreamSound, DirectDataStreamSound
			DirectFileStreamSound currentFileStreamSound = currentSound as DirectFileStreamSound;
			DirectDataStreamSound currentDataStreamSound = currentSound as DirectDataStreamSound;
			if( currentFileStreamSound != null || currentDataStreamSound != null )
			{
				int needBufferSize;

				if( currentFileStreamSound != null )
				{
					int numSamples = (int)currentFileStreamSound.vorbisFile.pcm_total( -1 );
					int channels;
					int rate;
					currentFileStreamSound.vorbisFile.get_info( -1, out channels, out rate );
					int sizeInBytes = numSamples * channels * 2;

					needBufferSize = sizeInBytes / 2;

					if( needBufferSize > 65536 * 2 )
						needBufferSize = 65536 * 2;
				}
				else
				{
					needBufferSize = currentDataStreamSound.creationBufferSize;
				}

				currentSoundBuffer = currentSound.GetBuffer( needBufferSize );
				if( currentSoundBuffer == null )
				{
					PreDetachVirtualChannel();
					DirectSoundWorld.criticalSection.Leave();
					return;
				}

				streamBuffer = (byte*)NativeUtils.Alloc( NativeMemoryAllocationType.SoundAndVideo,
					currentSound.bufferSize );
				streamBufferLength = 0;

				bool restored = false;
				if( !currentSound.RestoreSoundBuffers( out restored ) )
				{
					PreDetachVirtualChannel();
					DirectSoundWorld.criticalSection.Leave();
					return;
				}
				if( restored )
				{
					//buffer will be cleared in the BeginStreamPlay()
				}
			}

			//currentSound3DBuffer
			if( mode3d )
			{
				void*/*IDirectSound3DBuffer8*/ sound3DBuffer;

				GUID guid = DSound.IID_IDirectSound3DBuffer8;
				hr = IDirectSoundBuffer.QueryInterface( currentSoundBuffer, ref guid, &sound3DBuffer );
				if( Wrapper.FAILED( hr ) )
				{
					PreDetachVirtualChannel();
					DirectSoundWorld.Warning( "IDirectSoundBuffer.QueryInterface", hr );
					DirectSoundWorld.criticalSection.Leave();
					return;
				}
				currentSound3DBuffer = (IDirectSound3DBuffer8*)sound3DBuffer;
			}

			//update parameters
			if( mode3d )
			{
				UpdatePosition2();
				UpdateVelocity2();
			}
			else
				UpdatePan2();
			UpdatePitch2();
			UpdateVolume2();

			UpdateTime2();

			if( currentFileStreamSound != null || currentDataStreamSound != null )
				BeginStreamPlay();

			uint playFlags = 0;

			if( loop || currentFileStreamSound != null || currentDataStreamSound != null )
				playFlags |= DSound.DSBPLAY_LOOPING;

			hr = IDirectSoundBuffer.Play( currentSoundBuffer, 0, 0, playFlags );
			if( Wrapper.FAILED( hr ) )
			{
				PreDetachVirtualChannel();
				DirectSoundWorld.Warning( "IDirectSoundBuffer.Play", hr );
				DirectSoundWorld.criticalSection.Leave();
				return;
			}

			if( currentFileStreamSound != null )
				DirectSoundWorld.Instance.fileStreamRealChannels.Add( this );

			needStopVirtualChannel = false;

			DirectSoundWorld.criticalSection.Leave();
		}