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(); }
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()); }
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); }
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(); }
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(); }
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(); }