internal static AcmFormatInfo FromFormatTagDetails(ACMFORMATTAGDETAILS details, IntPtr hDriver, int driverId) { if (driverId == 0) { AcmNativeMethods.acmDriverID(hDriver, out driverId, 0); } AcmFormatInfo info = new AcmFormatInfo(); info.DriverId = driverId; //info.Format = new WaveFormat2( info.FormatName = details.szFormatTag; info.FormatTag = (FormatTag)details.dwFormatTag; for (int i = 0; i < details.cStandardFormats; i++) { ACMFORMATDETAILS fd = new ACMFORMATDETAILS(); fd.cbStruct = Marshal.SizeOf(fd); fd.cbwfx = details.cbFormatSize; WaveFormat2 fmt = new WaveFormat2(new byte[fd.cbwfx]); fmt.FormatTag = (FormatTag)details.dwFormatTag; fmt.Size = (short)(fd.cbwfx == 16 ? 0 : fd.cbwfx - 18); fmt.Extra = new byte[fmt.Size]; fd.pwfx = Marshal.AllocHGlobal(fd.cbwfx); Marshal.Copy(fmt.GetBytes(), 0, fd.pwfx, fd.cbwfx); fd.dwFormatIndex = i; fd.dwFormatTag = (int)info.FormatTag; /*MMResult mmr = */ int mmr = AcmNativeMethods.acmFormatDetails(hDriver, ref fd, AcmFormatDetailsFlags.INDEX); byte[] fmtData = new byte[fd.cbwfx]; Marshal.Copy(fd.pwfx, fmtData, 0, fd.cbwfx); info.Format = new WaveFormat2(fmtData); Marshal.FreeHGlobal(fd.pwfx); } return(info); }
/// <summary> /// Set the volume for the default waveOut device (device ID = 0) /// </summary> /// <param name="Volume"></param> public void SetVolume(int Volume) { WaveFormat2 format = new WaveFormat2(); IntPtr hWaveOut = IntPtr.Zero; NativeMethods.waveOutOpen(out hWaveOut, 0, format.GetBytes(), IntPtr.Zero, 0, 0); NativeMethods.waveOutSetVolume(hWaveOut, Volume); NativeMethods.waveOutClose(hWaveOut); }
/// <summary> /// Get the current volume setting for the default waveOut device (device ID = 0) /// </summary> /// <returns></returns> public int GetVolume() { WaveFormat2 format = new WaveFormat2(); IntPtr hWaveOut = IntPtr.Zero; int volume = 0; NativeMethods.waveOutOpen(out hWaveOut, 0, format.GetBytes(), IntPtr.Zero, 0, 0); NativeMethods.waveOutGetVolume(hWaveOut, ref volume); NativeMethods.waveOutClose(hWaveOut); return(volume); }
protected override void LoadHeader() { base.LoadHeader(); byte[] fmtIn = _fmt.GetBytes(); if (_fmt2 == null) { _fmt2 = WaveFormat2.GetPCMWaveFormat(_fmt.SamplesPerSec, _fmt.Channels, _fmt.BitsPerSample != 0 ? _fmt.BitsPerSample : (short)16); } byte[] fmtOut = _fmt2.GetBytes(); MMResult mmr; _fmt2 = new WaveFormat2(fmtOut); mmr = AcmNativeMethods.acmStreamOpen(out hStreamComp, IntPtr.Zero, fmtIn, fmtOut, IntPtr.Zero, 0, 0, AcmStreamOpenFlags.CALLBACK_NULL); hdr1 = new ACMSTREAMHEADER(); hdr1.cbStruct = Marshal.SizeOf(hdr1); hdr2 = new ACMSTREAMHEADER(); hdr2.cbStruct = Marshal.SizeOf(hdr2); int cbIn = (_fmt.AvgBytesPerSec * DefaultBufferSizeInSeconds / _fmt.BlockAlign + 1) * _fmt.BlockAlign; inBuffer1 = new byte[cbIn]; inBuffer2 = new byte[cbIn]; int cbOut = _fmt2.BlockAlign * _fmt2.AvgBytesPerSec * DefaultBufferSizeInSeconds; mmr = AcmNativeMethods.acmStreamSize(hStreamComp, cbIn, out cbOut, AcmStreamSizeFlags.SOURCE); outBuffer1 = new byte[cbOut]; outBuffer2 = new byte[cbOut]; hinBuffer1 = GCHandle.Alloc(inBuffer1, GCHandleType.Pinned); houtBuffer1 = GCHandle.Alloc(outBuffer1, GCHandleType.Pinned); hinBuffer2 = GCHandle.Alloc(inBuffer2, GCHandleType.Pinned); houtBuffer2 = GCHandle.Alloc(outBuffer2, GCHandleType.Pinned); hdr1.pbSrc = hinBuffer1.AddrOfPinnedObject(); hdr1.pbDst = houtBuffer1.AddrOfPinnedObject(); hdr1.cbSrcLength = cbIn; hdr1.cbDstLength = cbOut; hdr2.pbSrc = hinBuffer2.AddrOfPinnedObject(); hdr2.pbDst = houtBuffer2.AddrOfPinnedObject(); hdr2.cbSrcLength = cbIn; hdr2.cbDstLength = cbOut; ptrBuffer1 = ptrBuffer1 = 0; bufferRead = new SlidingBuffer(cbOut); firstBlock = true; bufferRead.BufferStarving = (BufferStarvingHandler) delegate(SlidingBuffer obj, int spaceAvailable) { if (hdr1.cbDstLengthUsed == ptrBuffer1) { int cb = ReadInternal(inBuffer1, 0, inBuffer1.Length); if (cb == 0) { return(0); } ptrBuffer1 = 0; AcmStreamConvertFlags flags; if (firstBlock) { flags = AcmStreamConvertFlags.START; firstBlock = false; } else if (cb == inBuffer1.Length) { flags = AcmStreamConvertFlags.BLOCKALIGN; } else { flags = AcmStreamConvertFlags.END; } hdr1.cbSrcLength = cb; MMResult res = AcmNativeMethods.acmStreamConvert(hStreamComp, ref hdr1, flags); return(cb); } int written = obj.Append(outBuffer1, ptrBuffer1, hdr1.cbDstLengthUsed - ptrBuffer1); ptrBuffer1 += written; return(written); }; mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr1, 0); mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr2, 0); }
protected override bool InitializeForWriting(Stream underlyingStream, WaveFormat2 wfIn, WaveFormat2 wfOut, bool fAppend) { base.InitializeForWriting(underlyingStream, wfIn, wfOut, fAppend); MMResult mmr; int driverId = 0; foreach (AcmDriverInfo drvInfo in ACMSupport.SupportedDrivers) { foreach (AcmFormatInfo fmtInfo in drvInfo.Formats) { if (fmtInfo.Format == wfOut) { driverId = fmtInfo.DriverId; break; } } } foreach (AcmDriverInfo drvInfo in ACMSupport.SupportedDrivers) { foreach (AcmFormatInfo fmtInfo in drvInfo.Formats) { if (fmtInfo.DriverId == driverId && fmtInfo.Format.FormatTag == wfIn.FormatTag) { wfIn.CopyFrom(fmtInfo.Format); break; } } } byte[] fmtIn = wfIn.GetBytes(); byte[] fmtOut = wfOut.GetBytes(); IntPtr hDrv = IntPtr.Zero; if (driverId != 0) { AcmNativeMethods.acmDriverOpen(out hDrv, driverId, 0); } mmr = AcmNativeMethods.acmStreamOpen(out hStreamComp, hDrv, fmtIn, fmtOut, IntPtr.Zero, 0, 0, AcmStreamOpenFlags.CALLBACK_NULL | AcmStreamOpenFlags.NONREALTIME); hdr1 = new ACMSTREAMHEADER(); hdr1.cbStruct = Marshal.SizeOf(hdr1); hdr2 = new ACMSTREAMHEADER(); hdr2.cbStruct = Marshal.SizeOf(hdr2); int cbIn = (wfIn.AvgBytesPerSec * DefaultBufferSizeInSeconds / wfIn.BlockAlign + 1) * wfIn.BlockAlign; inBuffer1 = new byte[cbIn]; inBuffer2 = new byte[cbIn]; int cbOut = wfOut.BlockAlign * wfOut.AvgBytesPerSec * DefaultBufferSizeInSeconds; mmr = AcmNativeMethods.acmStreamSize(hStreamComp, cbIn, out cbOut, AcmStreamSizeFlags.DESTINATION); outBuffer1 = new byte[cbOut]; outBuffer2 = new byte[cbOut]; hinBuffer1 = GCHandle.Alloc(inBuffer1, GCHandleType.Pinned); houtBuffer1 = GCHandle.Alloc(outBuffer1, GCHandleType.Pinned); hinBuffer2 = GCHandle.Alloc(inBuffer2, GCHandleType.Pinned); houtBuffer2 = GCHandle.Alloc(outBuffer2, GCHandleType.Pinned); hdr1.pbSrc = hinBuffer1.AddrOfPinnedObject(); hdr1.pbDst = houtBuffer1.AddrOfPinnedObject(); hdr1.cbSrcLength = cbIn; hdr1.cbDstLength = cbOut; hdr2.pbSrc = hinBuffer2.AddrOfPinnedObject(); hdr2.pbDst = houtBuffer2.AddrOfPinnedObject(); hdr2.cbSrcLength = cbIn; hdr2.cbDstLength = cbOut; ptrBuffer1 = ptrBuffer1 = 0; firstBlock = true; mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr1, 0); mmr = AcmNativeMethods.acmStreamPrepareHeader(hStreamComp, ref hdr2, 0); return(true); }
/// <summary> /// Record sound data for specified number of seconds using given wave format /// The stream will be a properly formatted RIFF file /// </summary> /// <param name="st">Stream into which recorded samples are written</param> /// <param name="Seconds">Seconds of data to record</param> /// <param name="format">Sound format to record in.</param> public RiffStream RecordFor(Stream st, short Seconds, WaveFormat2 format) { // only allow 1 recording session at a time if (recording) { throw new InvalidOperationException("Already recording"); } m_hWaveIn = IntPtr.Zero; // set our global flag recording = true; if (m_qBuffers == null) { m_qBuffers = new Queue <WaveHeader>(MaxBuffers); } if (m_HandleMap == null) { m_HandleMap = new System.Collections.Hashtable(MaxBuffers); } m_recformat = new WaveFormat2(); #if !NDOC // create the callback message window m_recmw = new SoundMessageWindow(); m_recmw.WaveDoneMessage += new WaveDoneHandler(m_recmw_WaveDoneMessage); m_recmw.WaveCloseMessage += new WaveCloseHandler(mw_WaveCloseMessage); m_recmw.WaveOpenMessage += new WaveOpenHandler(mw_WaveOpenMessage); #endif bool append = st.Length >= 42; if (format.FormatTag == FormatTag.PCM) { m_recformat = format; if (append) { m_streamRecord = RiffStream.Append(st); } else { m_streamRecord = RiffStream.OpenWrite(st, m_recformat); } } else { m_recformat = WaveFormat2.GetPCMWaveFormat(SoundFormats.Mono8bit11kHz); if (append) { m_streamRecord = ACMStream.Append(st, m_recformat); } else { m_streamRecord = ACMStream.OpenWrite(st, m_recformat, format); } } #if !NDOC // check for support of selected format CheckWaveError(NativeMethods.waveInOpen(out m_hWaveIn, WAVE_MAPPER, m_recformat.GetBytes(), IntPtr.Zero, 0, WAVE_FORMAT_QUERY)); // open wave device CheckWaveError(NativeMethods.waveInOpen(out m_hWaveIn, (uint)m_deviceID, m_recformat.GetBytes(), m_recmw.Hwnd, 0, CALLBACK_WINDOW)); m_recBufferSize = (int)(Math.Min((int)Seconds, BufferLen) * m_recformat.AvgBytesPerSec); for (int i = 0; i < 2; i++) { WaveHeader hdr = GetNewRecordBuffer(m_recBufferSize); // send the buffer to the device CheckWaveError(NativeMethods.waveInAddBuffer(m_hWaveIn, hdr.Pointer, hdr.HeaderLength)); } // begin recording CheckWaveError(NativeMethods.waveInStart(m_hWaveIn)); recordingFinished = false; m_recTimer = new Timer(new TimerCallback(RecTimerCallback), this, Seconds * 1000, Timeout.Infinite); #endif return(m_streamRecord); }
/// <summary> /// Plays waveform contained in the given stream. Stream is exepcted to contain full riff header /// </summary> /// <param name="playStream">Stream with the waveform</param> public void Play(Stream playStream) { Monitor.Enter(m_syncRoot); try { if (m_playing) { return; } if (playStream == null) { throw new Exception("No valid WAV file has been opened"); } #if !NDOC if (m_qBuffers == null) { m_qBuffers = new Queue <WaveHeader>(MaxBuffers); } if (m_HandleMap == null) { m_HandleMap = new System.Collections.Hashtable(MaxBuffers); } // create a window to catch waveOutxxx messages SoundMessageWindow mw = new SoundMessageWindow(); // wire in events mw.WaveOpenMessage += new WaveOpenHandler(mw_WaveOpenMessage); mw.WaveCloseMessage += new WaveCloseHandler(mw_WaveCloseMessage); mw.WaveDoneMessage += new WaveDoneHandler(mw_WaveDoneMessage); // add it to the global array m_mwArray.Add(mw); int i = m_mwArray.Count - 1; if (playStream is ACMStream) { m_streamArray.Add(playStream as ACMStream); } else if (playStream is RiffStream) { m_streamArray.Add(playStream as RiffStream); } else { m_streamArray.Add(ACMStream.OpenRead(playStream)); } m_format = (m_streamArray[m_streamArray.Count - 1] as RiffStream).Format; // open the waveOut device and register the callback CheckWaveError(NativeMethods.waveOutOpen(out m_hWaveOut, m_deviceID, m_format.GetBytes(), m_mwArray[i].Hwnd, 0, CALLBACK_WINDOW)); // see if we need to adjust playback rate if ((PlaybackRate < 0.9f) || (PlaybackRate > 1.1f)) { SetPlaybackRate(PlaybackRate); } RefillPlayBuffers(); while (m_qBuffers.Count > 0) { Monitor.Enter(m_qBuffers); WaveHeader hdr = m_qBuffers.Dequeue(); Monitor.Exit(m_qBuffers); // play the file ThreadPool.QueueUserWorkItem(BufferWriteThreadProc, hdr); m_playing = true; if (m_qBuffers.Count <= 1) { RefillPlayBuffers(); } } #endif } finally { Monitor.Exit(m_syncRoot); } }