/// <summary> /// Determines whether or not the device supports a given format. /// </summary> /// <param name="waveFormat">The format to check.</param> /// <returns>true, if the format is supported; false, otherwise.</returns> public bool SupportsFormat(WaveFormat waveFormat) { NativeMethods.WAVEFORMATEX wfx = new NativeMethods.WAVEFORMATEX(); wfx.nAvgBytesPerSec = waveFormat.AverageBytesPerSecond; wfx.wBitsPerSample = waveFormat.BitsPerSample; wfx.nBlockAlign = waveFormat.BlockAlign; wfx.nChannels = waveFormat.Channels; wfx.wFormatTag = (short)(int)waveFormat.FormatTag; wfx.nSamplesPerSec = waveFormat.SamplesPerSecond; wfx.cbSize = 0; IntPtr dummy = new IntPtr(0); NativeMethods.MMSYSERROR ret = NativeMethods.waveOutOpen( ref dummy, (uint)this.deviceId, ref wfx, null, (IntPtr)0, NativeMethods.WAVEOPENFLAGS.WAVE_FORMAT_QUERY); if (ret == NativeMethods.MMSYSERROR.MMSYSERR_NOERROR) { return(true); } else if (ret == NativeMethods.MMSYSERROR.WAVERR_BADFORMAT) { return(false); } else { NativeMethods.Throw(ret, NativeMethods.ErrorSource.WaveOut); return(false); } }
/// <summary> /// Opens the device for writing with the specified format. /// </summary> /// <param name="waveFormat">The format of the device to open.</param> public void Open(WaveFormat waveFormat) { lock (this.startStopLock) { if (this.handle != null) { throw new InvalidOperationException("The device is already open."); } NativeMethods.WAVEFORMATEX wfx = new NativeMethods.WAVEFORMATEX { nAvgBytesPerSec = waveFormat.AverageBytesPerSecond, wBitsPerSample = waveFormat.BitsPerSample, nBlockAlign = waveFormat.BlockAlign, nChannels = waveFormat.Channels, wFormatTag = (short)(int)waveFormat.FormatTag, nSamplesPerSec = waveFormat.SamplesPerSecond, cbSize = 0 }; this.recordingFormat = waveFormat.Clone(); IntPtr tempHandle = new IntPtr(); NativeMethods.Throw( NativeMethods.waveInOpen( ref tempHandle, (uint)this.deviceId, ref wfx, this.callback, (IntPtr)0, NativeMethods.WAVEOPENFLAGS.CALLBACK_FUNCTION | NativeMethods.WAVEOPENFLAGS.WAVE_FORMAT_DIRECT), NativeMethods.ErrorSource.WaveOut); this.handle = new WaveInSafeHandle(tempHandle); } }
/// <summary> /// Opens the device for writing with the specified format. /// </summary> /// <param name="waveFormat">The format of the device to open.</param> public void Open(WaveFormat waveFormat) { lock (this.startStopLock) { if (this.handle != null) { throw new InvalidOperationException("The device is already open."); } NativeMethods.WAVEFORMATEX wfx = new NativeMethods.WAVEFORMATEX(); wfx.nAvgBytesPerSec = waveFormat.AverageBytesPerSecond; wfx.wBitsPerSample = waveFormat.BitsPerSample; wfx.nBlockAlign = waveFormat.BlockAlign; wfx.nChannels = waveFormat.Channels; wfx.wFormatTag = (short)(int)waveFormat.FormatTag; wfx.nSamplesPerSec = waveFormat.SamplesPerSecond; wfx.cbSize = 0; IntPtr tempHandle = new IntPtr(); NativeMethods.Throw( NativeMethods.waveOutOpen( ref tempHandle, (uint)this.deviceId, ref wfx, this.callback, (IntPtr)0, NativeMethods.WAVEOPENFLAGS.CALLBACK_FUNCTION | NativeMethods.WAVEOPENFLAGS.WAVE_FORMAT_DIRECT), NativeMethods.ErrorSource.WaveOut); this.handle = new WaveOutSafeHandle(tempHandle); lock (this.bufferingLock) { this.buffering = true; Monitor.Pulse(this.bufferingLock); } this.bufferMaintainerThread = new Thread(new ThreadStart(this.MaintainBuffers)); this.bufferMaintainerThread.IsBackground = true; this.bufferMaintainerThread.Name = "WaveOut MaintainBuffers thread. (DeviceID = " + this.deviceId + ")"; this.bufferMaintainerThread.Start(); } }
public static void Play(double[] signal, int samplingRate) { // Dies ist noch sehr unsauber! // TODO: auf Fehler reagieren; Speicherlecks vermeiden // TODO: Iterator statt komplettem Array benutzen short[] buffer = new short[signal.Length]; for (int i = 0; i < signal.Length; i++) { buffer[i] = (short)(short.MaxValue * signal[i]); } GCHandle hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr hWaveOut = IntPtr.Zero; NativeMethods.WAVEFORMATEX format = new NativeMethods.WAVEFORMATEX(); format.wFormatTag = 1; format.nChannels = 1; format.nSamplesPerSec = (uint)samplingRate; format.nAvgBytesPerSec = (uint)(samplingRate * sizeof(short)); format.nBlockAlign = sizeof(short); format.wBitsPerSample = 16; format.cbSize = 0; NativeMethods.waveOutOpen(ref hWaveOut, new IntPtr(-1), ref format, IntPtr.Zero, IntPtr.Zero, 0); NativeMethods.WAVEHDR header = new NativeMethods.WAVEHDR(); header.lpData = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); header.dwBufferLength = (uint)(buffer.Length * sizeof(short)); NativeMethods.waveOutPrepareHeader(hWaveOut, ref header, (uint)Marshal.SizeOf(header)); NativeMethods.waveOutWrite(hWaveOut, ref header, (uint)Marshal.SizeOf(header)); while ((header.dwFlags & 1) == 0) { System.Threading.Thread.Sleep(100); } NativeMethods.waveOutUnprepareHeader(hWaveOut, ref header, (uint)Marshal.SizeOf(header)); NativeMethods.waveOutClose(hWaveOut); hBuffer.Free(); }
private unsafe void ValidateSoundFile(string fileName) { NativeMethods.MMCKINFO ckRIFF = new NativeMethods.MMCKINFO(); NativeMethods.MMCKINFO ck = new NativeMethods.MMCKINFO(); NativeMethods.WAVEFORMATEX waveFormat = null; int dw; IntPtr hMIO = UnsafeNativeMethods.mmioOpen(fileName, IntPtr.Zero, NativeMethods.MMIO_READ | NativeMethods.MMIO_ALLOCBUF); if (hMIO == IntPtr.Zero) { throw new FileNotFoundException(SR.GetString(SR.SoundAPIFileDoesNotExist), this.soundLocation); } try { ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (UnsafeNativeMethods.mmioDescend(hMIO, ckRIFF, null, NativeMethods.MMIO_FINDRIFF) != 0) { throw new InvalidOperationException(SR.GetString(SR.SoundAPIInvalidWaveFile, this.soundLocation)); } while (UnsafeNativeMethods.mmioDescend(hMIO, ck, ckRIFF, 0) == 0) { if (ck.dwDataOffset + ck.cksize > ckRIFF.dwDataOffset + ckRIFF.cksize) { throw new InvalidOperationException(SR.GetString(SR.SoundAPIInvalidWaveHeader)); } if (ck.ckID == mmioFOURCC('f', 'm', 't', ' ')) { if (waveFormat == null) { dw = ck.cksize; if (dw < Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX))) { dw = Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX)); } waveFormat = new NativeMethods.WAVEFORMATEX(); byte[] data = new byte[dw]; if (UnsafeNativeMethods.mmioRead(hMIO, data, dw) != dw) throw new InvalidOperationException(SR.GetString(SR.SoundAPIReadError, this.soundLocation)); fixed(byte *pdata = data) { Marshal.PtrToStructure((IntPtr)pdata, waveFormat); } } else { // // multiple formats? // } } UnsafeNativeMethods.mmioAscend(hMIO, ck, 0); } if (waveFormat == null) { throw new InvalidOperationException(SR.GetString(SR.SoundAPIInvalidWaveHeader)); } if (waveFormat.wFormatTag != NativeMethods.WAVE_FORMAT_PCM && waveFormat.wFormatTag != NativeMethods.WAVE_FORMAT_ADPCM && waveFormat.wFormatTag != NativeMethods.WAVE_FORMAT_IEEE_FLOAT) { throw new InvalidOperationException(SR.GetString(SR.SoundAPIFormatNotSupported)); } } finally { if (hMIO != IntPtr.Zero) { UnsafeNativeMethods.mmioClose(hMIO, 0); } } }
private unsafe void ValidateSoundFile(string fileName) { NativeMethods.MMCKINFO lpck = new NativeMethods.MMCKINFO(); NativeMethods.MMCKINFO mmckinfo2 = new NativeMethods.MMCKINFO(); NativeMethods.WAVEFORMATEX structure = null; IntPtr hMIO = UnsafeNativeMethods.mmioOpen(fileName, IntPtr.Zero, 0x10000); if (hMIO == IntPtr.Zero) { throw new FileNotFoundException(SR.GetString("SoundAPIFileDoesNotExist"), this.soundLocation); } try { lpck.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (UnsafeNativeMethods.mmioDescend(hMIO, lpck, null, 0x20) == 0) { goto Label_0179; } throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveFile", new object[] { this.soundLocation })); Label_008B: if ((mmckinfo2.dwDataOffset + mmckinfo2.cksize) > (lpck.dwDataOffset + lpck.cksize)) { throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader")); } if ((mmckinfo2.ckID == mmioFOURCC('f', 'm', 't', ' ')) && (structure == null)) { int cksize = mmckinfo2.cksize; if (cksize < Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX))) { cksize = Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX)); } structure = new NativeMethods.WAVEFORMATEX(); byte[] wf = new byte[cksize]; if (UnsafeNativeMethods.mmioRead(hMIO, wf, cksize) != cksize) { throw new InvalidOperationException(SR.GetString("SoundAPIReadError", new object[] { this.soundLocation })); } try { fixed(byte *numRef = wf) { Marshal.PtrToStructure((IntPtr)numRef, structure); } } finally { numRef = null; } } UnsafeNativeMethods.mmioAscend(hMIO, mmckinfo2, 0); Label_0179: if (UnsafeNativeMethods.mmioDescend(hMIO, mmckinfo2, lpck, 0) == 0) { goto Label_008B; } if (structure == null) { throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader")); } if (((structure.wFormatTag != 1) && (structure.wFormatTag != 2)) && (structure.wFormatTag != 3)) { throw new InvalidOperationException(SR.GetString("SoundAPIFormatNotSupported")); } } finally { if (hMIO != IntPtr.Zero) { UnsafeNativeMethods.mmioClose(hMIO, 0); } } }
private unsafe void ValidateSoundFile(string fileName) { NativeMethods.MMCKINFO ckRIFF = new NativeMethods.MMCKINFO(); NativeMethods.MMCKINFO ck = new NativeMethods.MMCKINFO(); NativeMethods.WAVEFORMATEX waveFormat = null; int dw; IntPtr hMIO = UnsafeNativeMethods.mmioOpen(fileName, IntPtr.Zero, NativeMethods.MMIO_READ | NativeMethods.MMIO_ALLOCBUF); if (hMIO == IntPtr.Zero) throw new FileNotFoundException(SR.GetString(SR.SoundAPIFileDoesNotExist), this.soundLocation); try { ckRIFF.fccType = mmioFOURCC('W', 'A','V','E'); if (UnsafeNativeMethods.mmioDescend(hMIO, ckRIFF, null, NativeMethods.MMIO_FINDRIFF) != 0) throw new InvalidOperationException(SR.GetString(SR.SoundAPIInvalidWaveFile, this.soundLocation)); while (UnsafeNativeMethods.mmioDescend(hMIO, ck, ckRIFF, 0) == 0) { if (ck.dwDataOffset + ck.cksize > ckRIFF.dwDataOffset + ckRIFF.cksize) throw new InvalidOperationException(SR.GetString(SR.SoundAPIInvalidWaveHeader)); if (ck.ckID == mmioFOURCC('f','m','t',' ')) { if (waveFormat == null) { dw = ck.cksize; if (dw < Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX))) dw = Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX)); waveFormat = new NativeMethods.WAVEFORMATEX(); byte[] data = new byte[dw]; if (UnsafeNativeMethods.mmioRead(hMIO, data, dw) != dw) throw new InvalidOperationException(SR.GetString(SR.SoundAPIReadError, this.soundLocation)); fixed(byte* pdata = data) { Marshal.PtrToStructure((IntPtr) pdata, waveFormat); } } else { // // multiple formats? // } } UnsafeNativeMethods.mmioAscend(hMIO, ck, 0); } if (waveFormat == null) throw new InvalidOperationException(SR.GetString(SR.SoundAPIInvalidWaveHeader)); if (waveFormat.wFormatTag != NativeMethods.WAVE_FORMAT_PCM && waveFormat.wFormatTag != NativeMethods.WAVE_FORMAT_ADPCM && waveFormat.wFormatTag != NativeMethods.WAVE_FORMAT_IEEE_FLOAT) throw new InvalidOperationException(SR.GetString(SR.SoundAPIFormatNotSupported)); } finally { if (hMIO != IntPtr.Zero) UnsafeNativeMethods.mmioClose(hMIO, 0); } }
private unsafe void ValidateSoundFile(string fileName) { NativeMethods.MMCKINFO lpck = new NativeMethods.MMCKINFO(); NativeMethods.MMCKINFO mmckinfo2 = new NativeMethods.MMCKINFO(); NativeMethods.WAVEFORMATEX structure = null; IntPtr hMIO = UnsafeNativeMethods.mmioOpen(fileName, IntPtr.Zero, 0x10000); if (hMIO == IntPtr.Zero) { throw new FileNotFoundException(SR.GetString("SoundAPIFileDoesNotExist"), this.soundLocation); } try { lpck.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (UnsafeNativeMethods.mmioDescend(hMIO, lpck, null, 0x20) == 0) { goto Label_0179; } throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveFile", new object[] { this.soundLocation })); Label_008B: if ((mmckinfo2.dwDataOffset + mmckinfo2.cksize) > (lpck.dwDataOffset + lpck.cksize)) { throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader")); } if ((mmckinfo2.ckID == mmioFOURCC('f', 'm', 't', ' ')) && (structure == null)) { int cksize = mmckinfo2.cksize; if (cksize < Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX))) { cksize = Marshal.SizeOf(typeof(NativeMethods.WAVEFORMATEX)); } structure = new NativeMethods.WAVEFORMATEX(); byte[] wf = new byte[cksize]; if (UnsafeNativeMethods.mmioRead(hMIO, wf, cksize) != cksize) { throw new InvalidOperationException(SR.GetString("SoundAPIReadError", new object[] { this.soundLocation })); } try { fixed (byte* numRef = wf) { Marshal.PtrToStructure((IntPtr) numRef, structure); } } finally { numRef = null; } } UnsafeNativeMethods.mmioAscend(hMIO, mmckinfo2, 0); Label_0179: if (UnsafeNativeMethods.mmioDescend(hMIO, mmckinfo2, lpck, 0) == 0) { goto Label_008B; } if (structure == null) { throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader")); } if (((structure.wFormatTag != 1) && (structure.wFormatTag != 2)) && (structure.wFormatTag != 3)) { throw new InvalidOperationException(SR.GetString("SoundAPIFormatNotSupported")); } } finally { if (hMIO != IntPtr.Zero) { UnsafeNativeMethods.mmioClose(hMIO, 0); } } }