/// <summary> /// Play a wave file. /// </summary> /// <param name="curDevice">Hardware device to use for playback</param> /// <param name="fileName">Name of file to play</param> /// <param name="hwnd">Handle to a message window to use for messaging</param> /// <param name="bufferSize">Size of streaming buffers, a 0 value specifies /// that the buffer should be created big enough to fit the entire file</param> /// <param name="volLeft">Left channel volume level</param> /// <param name="volRight">Right channel volume level</param> /// <returns>MMSYSERR.NOERROR if successful</returns> public Wave.MMSYSERR Play(uint curDevice, String fileName, IntPtr hwnd, int bufferSize, ushort volLeft, ushort volRight) { if (m_playing) { return(Wave.MMSYSERR.NOERROR); } if (!File.Exists(fileName)) { return(Wave.MMSYSERR.ERROR); } FileInfo fi = new FileInfo(fileName); if ((fi.Attributes & FileAttributes.ReadOnly) != 0) { fi.Attributes -= FileAttributes.ReadOnly; } FileStream strm = new FileStream(fileName, FileMode.Open); if (strm == null) { return(Wave.MMSYSERR.ERROR); } m_rdr = new BinaryReader(strm); if (m_rdr == null) { return(Wave.MMSYSERR.ERROR); } m_wfmt = new Wave.WAVEFORMATEX(); m_wfmt.SeekTo(strm); // Read in the WAVEFORMATEX structure and attempt to open the // device for playback. m_wfmt.Read(m_rdr); Wave.MMSYSERR result = waveOutOpen(ref m_hwo, curDevice, m_wfmt, hwnd, 0, Wave.CALLBACK_WINDOW); if (result != Wave.MMSYSERR.NOERROR) { return(result); } m_dataLength = (uint)(m_rdr.BaseStream.Length - Wave.WAVEFORMATEX.WF_OFFSET_DATA); if (bufferSize == 0) { m_bufferSize = (int)m_dataLength; } else { m_bufferSize = bufferSize / 2; } if (m_bufferSize % m_wfmt.nBlockAlign != 0) { m_bufferSize += m_wfmt.nBlockAlign - (m_bufferSize % m_wfmt.nBlockAlign); } // Determine the number of buffer reads required to play the entire // file m_numBlocks = (int)(m_dataLength / m_bufferSize); if ((m_numBlocks * m_bufferSize) < m_dataLength) { m_numBlocks++; } m_whdr[0] = new Wave.WAVEHDR(); m_whdr[1] = new Wave.WAVEHDR(); // Read in the first buffer result = ReadBuffer(0); if (result != Wave.MMSYSERR.NOERROR) { return(result); } // If the entire file fits in the buffer then close the file if (m_numBlocks == 1) { m_rdr.BaseStream.Close(); m_rdr.Close(); m_rdr = null; } SetVolume(volLeft, volRight); // Start playback of the first buffer result = waveOutWrite(m_hwo, m_whdr[0], (uint)Marshal.SizeOf(m_whdr[0])); if (result != Wave.MMSYSERR.NOERROR) { return(result); } m_curBlock = 0; // Create the second buffer. If the audio is being streamed, this will // be the next audio block, otherwise it will be padding Thread loadThread = new Thread(new ThreadStart(LoadBuffer)); loadThread.Start(); m_playing = true; return(Wave.MMSYSERR.NOERROR); }
private static extern Wave.MMSYSERR waveOutWrite(IntPtr hwo, Wave.WAVEHDR pwh, uint cbwh);
private static extern Wave.MMSYSERR waveOutUnprepareHeader(IntPtr hwo, Wave.WAVEHDR pwh, uint cbwh);
/// <summary> /// Play a wave file. /// </summary> /// <param name="curDevice">Hardware device to use for playback</param> /// <param name="fileName">Name of file to play</param> /// <param name="hwnd">Handle to a message window to use for messaging</param> /// <param name="bufferSize">Size of streaming buffers, a 0 value specifies /// that the buffer should be created big enough to fit the entire file</param> /// <param name="volLeft">Left channel volume level</param> /// <param name="volRight">Right channel volume level</param> /// <returns>MMSYSERR.NOERROR if successful</returns> public Wave.MMSYSERR Play(uint curDevice, String fileName, IntPtr hwnd, int bufferSize, ushort volLeft, ushort volRight) { if (m_playing) return Wave.MMSYSERR.NOERROR; if (!File.Exists(fileName)) return Wave.MMSYSERR.ERROR; FileInfo fi = new FileInfo(fileName); if ((fi.Attributes & FileAttributes.ReadOnly) != 0) fi.Attributes -= FileAttributes.ReadOnly; FileStream strm = new FileStream(fileName, FileMode.Open); if (strm == null) return Wave.MMSYSERR.ERROR; m_rdr = new BinaryReader(strm); if (m_rdr == null) return Wave.MMSYSERR.ERROR; m_wfmt = new Wave.WAVEFORMATEX(); m_wfmt.SeekTo(strm); // Read in the WAVEFORMATEX structure and attempt to open the // device for playback. m_wfmt.Read(m_rdr); Wave.MMSYSERR result = waveOutOpen(ref m_hwo, curDevice, m_wfmt, hwnd, 0, Wave.CALLBACK_WINDOW); if (result != Wave.MMSYSERR.NOERROR) return result; m_dataLength = (uint)(m_rdr.BaseStream.Length - Wave.WAVEFORMATEX.WF_OFFSET_DATA); if (bufferSize == 0) m_bufferSize = (int)m_dataLength; else m_bufferSize = bufferSize / 2; if (m_bufferSize % m_wfmt.nBlockAlign != 0) m_bufferSize += m_wfmt.nBlockAlign - (m_bufferSize % m_wfmt.nBlockAlign); // Determine the number of buffer reads required to play the entire // file m_numBlocks = (int)(m_dataLength / m_bufferSize); if ((m_numBlocks * m_bufferSize) < m_dataLength) m_numBlocks++; m_whdr[0] = new Wave.WAVEHDR(); m_whdr[1] = new Wave.WAVEHDR(); // Read in the first buffer result = ReadBuffer(0); if (result != Wave.MMSYSERR.NOERROR) return result; // If the entire file fits in the buffer then close the file if (m_numBlocks == 1) { m_rdr.BaseStream.Close(); m_rdr.Close(); m_rdr = null; } SetVolume(volLeft, volRight); // Start playback of the first buffer result = waveOutWrite(m_hwo, m_whdr[0], (uint)Marshal.SizeOf(m_whdr[0])); if (result != Wave.MMSYSERR.NOERROR) return result; m_curBlock = 0; // Create the second buffer. If the audio is being streamed, this will // be the next audio block, otherwise it will be padding Thread loadThread = new Thread(new ThreadStart(LoadBuffer)); loadThread.Start(); m_playing = true; return Wave.MMSYSERR.NOERROR; }