public override Sound SoundCreate(VirtualFileStream stream, bool closeStreamAfterReading,
                                          SoundType soundType, SoundMode mode)
        {
            criticalSection.Enter();

            DirectSound sound;
            bool        initialized;

            if ((int)(mode & SoundMode.Stream) == 0)
            {
                sound = new DirectSampleSound(stream, soundType, null, mode, out initialized);
                if (closeStreamAfterReading)
                {
                    stream.Close();
                }
            }
            else
            {
                sound = new DirectFileStreamSound(stream, closeStreamAfterReading, soundType, null,
                                                  mode, out initialized);
            }

            if (!initialized)
            {
                sound.Dispose();
                sound = null;
            }

            criticalSection.Leave();

            return(sound);
        }
        //file stream
        unsafe int ReadDataFromFileStream(IntPtr buffer, int needRead)
        {
            DirectFileStreamSound currentFileStreamSound = (DirectFileStreamSound)currentSound;

            while (streamBufferLength < needRead)
            {
                int readBytes = currentFileStreamSound.vorbisFile.read(
                    (IntPtr)(streamBuffer + streamBufferLength),
                    currentSound.bufferSize - streamBufferLength, 0, 2, 1, IntPtr.Zero);

                //convert to mono for 3D
                if (readBytes > 0 && currentFileStreamSound.needConvertToMono)
                {
                    byte *pointer = (byte *)streamBuffer + streamBufferLength;

                    readBytes /= 2;

                    for (int n = 0; n < readBytes; n += 2)
                    {
                        *(pointer + n + 0) = *(pointer + n * 2 + 0);
                        *(pointer + n + 1) = *(pointer + n * 2 + 1);
                    }
                }

                if (readBytes > 0)
                {
                    streamBufferLength += readBytes;
                }
                else
                {
                    break;
                }
            }

            if (streamBufferLength == 0)
            {
                return(0);
            }

            int totalReaded = Math.Min(streamBufferLength, needRead);

            NativeUtils.CopyMemory(buffer, (IntPtr)streamBuffer, totalReaded);

            streamBufferLength -= totalReaded;
            if (streamBufferLength > 0)
            {
                NativeUtils.MoveMemory((IntPtr)streamBuffer, (IntPtr)(streamBuffer + totalReaded),
                                       streamBufferLength);
            }

            return(totalReaded);
        }
        public override Sound SoundCreate(string name, SoundMode mode)
        {
            criticalSection.Enter();

            DirectSound sound;

            sound = (DirectSound)base.SoundCreate(name, mode);
            if (sound != null)
            {
                criticalSection.Leave();
                return(sound);
            }

            VirtualFileStream stream = CreateFileStream(name);

            if (stream == null)
            {
                criticalSection.Leave();
                DirectSoundWorld.Warning(string.Format("Creating sound \"{0}\" failed.", name));
                return(null);
            }

            bool initialized;

            if ((int)(mode & SoundMode.Stream) == 0)
            {
                sound = new DirectSampleSound(stream, SoundType.Unknown, name,
                                              mode, out initialized);
                stream.Close();
            }
            else
            {
                sound = new DirectFileStreamSound(stream, true, SoundType.Unknown,
                                                  name, mode, out initialized);
            }

            if (!initialized)
            {
                sound.Dispose();
                sound = null;
            }

            criticalSection.Leave();

            return(sound);
        }
        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();
        }
        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();
        }
        unsafe void UpdateStreamBuffer(bool firstPart)
        {
            DirectFileStreamSound currentFileStreamSound = currentSound as DirectFileStreamSound;

            void *lockedBuffer     = null;
            uint  lockedBufferSize = 0;

            int hr = IDirectSoundBuffer.Lock(currentSoundBuffer,
                                             (uint)(firstPart ? 0 : currentSound.bufferSize / 2),
                                             (uint)(currentSound.bufferSize / 2), &lockedBuffer, &lockedBufferSize,
                                             (void **)null, (uint *)null, 0);

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

            if ((int)lockedBufferSize < currentSound.bufferSize / 2)
            {
                Log.Fatal("DirectSoundRealChannel.UpdateStreamBuffer: " +
                          "lockedBufferSize >= currentSound->bufferSize / 2.");
            }

            bool repeated = false;

            int readed = 0;

again:

            if (currentFileStreamSound != null)
            {
                readed += ReadDataFromFileStream((IntPtr)((byte *)lockedBuffer + readed),
                                                 currentSound.bufferSize / 2 - readed);
            }
            else
            {
                readed += ReadDataFromDataStream((IntPtr)((byte *)lockedBuffer + readed),
                                                 currentSound.bufferSize / 2 - readed);
            }

            if (readed < currentSound.bufferSize / 2)
            {
                NativeUtils.FillMemory((IntPtr)((byte *)lockedBuffer + readed),
                                       (int)lockedBufferSize - readed,
                                       (byte)(currentSound.waveFormat->wBitsPerSample == 8 ? 128 : 0));

                if ((int)(currentSound.Mode & SoundMode.Loop) != 0)
                {
                    if (currentFileStreamSound != null)
                    {
                        //loop play. we need recreate vorbis file
                        currentFileStreamSound.Rewind();

                        if (!repeated)
                        {
                            repeated = true;
                            goto again;
                        }
                    }
                }
            }

            if (readed == 0)
            {
                //need stop
                if ((int)(currentSound.Mode & SoundMode.Loop) == 0)
                {
                    if (currentFileStreamSound != null)
                    {
                        needStopAfterBufferRead = true;
                    }
                }
            }

            IDirectSoundBuffer.Unlock(currentSoundBuffer, lockedBuffer, lockedBufferSize, null, 0);
        }
Пример #7
0
		public override Sound SoundCreate( VirtualFileStream stream, bool closeStreamAfterReading,
			SoundType soundType, SoundMode mode )
		{
			criticalSection.Enter();

			DirectSound sound;
			bool initialized;

			if( (int)( mode & SoundMode.Stream ) == 0 )
			{
				sound = new DirectSampleSound( stream, soundType, null, mode, out initialized );
				if( closeStreamAfterReading )
					stream.Close();
			}
			else
			{
				sound = new DirectFileStreamSound( stream, closeStreamAfterReading, soundType, null,
					mode, out initialized );
			}

			if( !initialized )
			{
				sound.Dispose();
				sound = null;
			}

			criticalSection.Leave();

			return sound;
		}
Пример #8
0
		public override Sound SoundCreate( string name, SoundMode mode )
		{
			criticalSection.Enter();

			DirectSound sound;

			sound = (DirectSound)base.SoundCreate( name, mode );
			if( sound != null )
			{
				criticalSection.Leave();
				return sound;
			}

			VirtualFileStream stream = CreateFileStream( name );
			if( stream == null )
			{
				criticalSection.Leave();
				DirectSoundWorld.Warning( string.Format( "Creating sound \"{0}\" failed.", name ) );
				return null;
			}

			bool initialized;

			if( (int)( mode & SoundMode.Stream ) == 0 )
			{
				sound = new DirectSampleSound( stream, SoundType.Unknown, name,
					mode, out initialized );
				stream.Close();
			}
			else
			{
				sound = new DirectFileStreamSound( stream, true, SoundType.Unknown,
					name, mode, out initialized );
			}

			if( !initialized )
			{
				sound.Dispose();
				sound = null;
			}

			criticalSection.Leave();

			return sound;
		}