⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 player.cs

📁 本源码为OpenNETCF源代码
💻 CS
字号:
//==========================================================================================
//
//		OpenNETCF.Multimedia.Audio.Player
//		Copyright (c) 2003, OpenNETCF.org
//
//		This library is free software; you can redistribute it and/or modify it under 
//		the terms of the OpenNETCF.org Shared Source License.
//
//		This library is distributed in the hope that it will be useful, but 
//		WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
//		FITNESS FOR A PARTICULAR PURPOSE. See the OpenNETCF.org Shared Source License 
//		for more details.
//
//		You should have received a copy of the OpenNETCF.org Shared Source License 
//		along with this library; if not, email licensing@opennetcf.org to request a copy.
//
//		If you wish to contact the OpenNETCF Advisory Board to discuss licensing, please 
//		email licensing@opennetcf.org.
//
//		For general enquiries, email enquiries@opennetcf.org or visit our website at:
//		http://www.opennetcf.org
//
//==========================================================================================
using System;
using OpenNETCF.Win32;
using System.IO;
using System.Collections;
using System.Threading;

namespace OpenNETCF.Multimedia.Audio
{
	/// <summary>
	/// Wave Audio player class. Supports PCM waveform playback from the stream
	/// </summary>
	public class Player : Audio
	{
		/// <summary>
		/// Raised when the wave device is opened
		/// </summary>
		public event WaveOpenHandler		WaveOpen;
		/// <summary>
		/// Raised when the wave device is closed
		/// </summary>
		public event WaveCloseHandler		WaveClose;
		/// <summary>
		/// Raised when the wave device has finished playback
		/// </summary>
		public event WaveDoneHandler		DonePlaying;

		private WaveFormatEx		m_format;
		private IntPtr				m_hWaveOut		= IntPtr.Zero;
		private bool				m_playing		= false;
		//private bool				m_paused		= false;

		private ArrayList			m_mwArray;
		private ArrayList			m_streamArray;

		/// <summary>
		/// Constructs Player object on the default wave device
		/// </summary>
		public Player()
		{
			m_mwArray = new ArrayList();
			m_streamArray = new ArrayList();
			m_qBuffers = new Queue(MaxBuffers);
			m_HandleMap = new Hashtable(MaxBuffers);
		}

		/// <summary>
		/// Constructs Player object on the given wave device
		/// </summary>
		/// <param name="AudioDeviceID">Wave device ID</param>
		public Player(int AudioDeviceID) : this()
		{			
			m_deviceID =AudioDeviceID;
		}

		/// <summary>
		/// Number of the output wave devices in the system
		/// </summary>
		public static int NumDevices { get { return Wave.waveOutGetNumDevs(); } }

		/// <summary>
		/// Restart a paused wave file
		/// </summary>
		public void Restart() { Wave.waveOutRestart(m_hWaveOut); }

		/// <summary>
		/// Pause Play
		/// </summary>
		public void Pause() { Wave.waveOutPause(m_hWaveOut); }

		/// <summary>
		/// Stop Play
		/// </summary>
		public void Stop() 
		{ 
			Wave.waveOutReset(m_hWaveOut); 
			m_playing = false;
		}

		/// <summary>
		/// Gets or sets playback volume on the current wave device
		/// </summary>
		public int Volume
		{
			get
			{
				int vol = 0;
				CheckWaveError(Wave.waveOutGetVolume(m_hWaveOut, ref vol));
				return vol;
			}
			set
			{
				CheckWaveError(Wave.waveOutSetVolume(m_hWaveOut, Convert.ToInt32(value)));
			}
		}

		/// <summary>
		/// True, if the player is currently playing. False otherwise
		/// </summary>
		public bool Playing { get{ return m_playing; } }


		/// <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 )
		{
			if(m_playing) return;

			
			MMChunk ck = MMChunk.FromStream(playStream);
			if ( ck != null && ck.FourCC == FourCC.Riff )
			{
				if ( ck[0] is WaveChunk )
				{
					DataChunk dck = ck[0].FindChunk(FourCC.Data) as DataChunk;
					if ( dck != null )
					{
						playStream = dck.BeginRead();
					}
					FmtChunk fck = ck[0].FindChunk(FourCC.Fmt) as FmtChunk;
					if ( fck != null )
					{
						m_format = fck.WaveFormat;
					}
				}
			}
			if ( playStream == null )
			{
				throw new Exception("No valid WAV file has been opened");
			}

#if!NDOC

			if ( m_qBuffers == null )
				m_qBuffers = new Queue(MaxBuffers);
			if ( m_HandleMap == null )
				m_HandleMap = new 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
			int i = m_mwArray.Add(mw);
			m_streamArray.Add(playStream);

			// open the waveOut device and register the callback
			CheckWaveError(Wave.waveOutOpen(out m_hWaveOut, m_deviceID, m_format, ((SoundMessageWindow)m_mwArray[i]).Hwnd, 0, CALLBACK_WINDOW));

			RefillPlayBuffers();

			Monitor.Enter(m_qBuffers.SyncRoot);
			WaveHeader hdr = m_qBuffers.Dequeue() as WaveHeader;
			Monitor.Exit(m_qBuffers.SyncRoot);

			// play the file
			int ret = Wave.waveOutWrite(m_hWaveOut, hdr.Header, hdr.HeaderLength);
			CheckWaveError(ret);

			m_playing = true;
			
#endif
		}

		// Add more buffers to the playback queue - keep it full
		private void RefillPlayBuffers()
		{
			while( m_qBuffers.Count < MaxBuffers )
			{
				int cb = (int)(BufferLen * m_format.SamplesPerSec * m_format.Channels);
				byte[] data = new byte[cb];

				for(int i = 0 ; i < m_streamArray.Count ; i++)
				{
					if( m_streamArray[i] != null )
					{
						cb = ((Stream)m_streamArray[i]).Read(data, 0, cb);
						break;
					}
				}

				if ( cb == 0 )
					break;

				WaveHeader hdr = new WaveHeader(data);
				Monitor.Enter(m_HandleMap.SyncRoot);
				m_HandleMap.Add(hdr.Header.ToInt32(), hdr);
				Monitor.Exit(m_HandleMap.SyncRoot);

				// prepare the header
				CheckWaveError(Wave.waveOutPrepareHeader(m_hWaveOut, hdr.Header, hdr.HeaderLength));
				Monitor.Enter(m_qBuffers.SyncRoot);
				m_qBuffers.Enqueue(hdr);
				Monitor.Exit(m_qBuffers.SyncRoot);
			}
		}

		private void mw_WaveOpenMessage(object sender)
		{
			if(WaveOpen != null)
			{
				WaveOpen(this);
			}
		}

		private void mw_WaveCloseMessage(object sender)
		{
#if !NDOC
			// remove the message window from the gloabal array
			for(int smw = 0 ; smw < m_mwArray.Count ; smw++)
			{
				if(((SoundMessageWindow)m_mwArray[smw]).Hwnd == ((SoundMessageWindow)sender).Hwnd)
				{
					// remove the messages
					((SoundMessageWindow)m_mwArray[smw]).WaveOpenMessage -= new WaveOpenHandler(mw_WaveOpenMessage);
					((SoundMessageWindow)m_mwArray[smw]).WaveCloseMessage -= new WaveCloseHandler(mw_WaveCloseMessage);
					((SoundMessageWindow)m_mwArray[smw]).WaveDoneMessage -= new WaveDoneHandler(mw_WaveDoneMessage);

					((SoundMessageWindow)m_mwArray[smw]).Dispose();
					m_mwArray.RemoveAt(smw);
					((Stream)m_streamArray[smw]).Close();
					m_streamArray.RemoveAt(smw);

					break;
				}
			}
			if(WaveClose != null)
			{
				WaveClose(this);
			}
#endif
			m_playing = false;
		}
		private void mw_WaveDoneMessage(object sender, IntPtr wParam, IntPtr lParam)
		{
			// free the header
			Monitor.Enter(m_HandleMap.SyncRoot);
			WaveHeader hdr = m_HandleMap[lParam.ToInt32()] as WaveHeader;
			m_HandleMap.Remove(lParam.ToInt32());
			Monitor.Exit(m_HandleMap.SyncRoot);
			CheckWaveError(Wave.waveOutUnprepareHeader(m_hWaveOut, lParam, hdr.HeaderLength));
			hdr.Dispose();

			// Check if we got here because of waveOutReset
			if ( !m_playing )
			{
				// Cleanup - free buffers and headers
				Monitor.Enter(m_qBuffers.SyncRoot);
				while( m_qBuffers.Count > 0 )
				{
					hdr = m_qBuffers.Dequeue() as WaveHeader;
					CheckWaveError(Wave.waveOutUnprepareHeader(m_hWaveOut, hdr.Header, hdr.HeaderLength));
					m_HandleMap.Remove(hdr.Header.ToInt32());
					hdr.Dispose();
				}
				Monitor.Exit(m_qBuffers.SyncRoot);
			}

			// Are there any pending buffers?
			if ( m_qBuffers.Count == 0 )
			{
				// No more buffers
				// Close the device
				CheckWaveError(Wave.waveOutClose(m_hWaveOut));
				m_playing = false;
				m_qBuffers = null;

				// Notify clients
				if(DonePlaying != null)
				{
					DonePlaying(this, wParam, lParam);
				}
			}
			else
			{
				//Get next buffer (already prepared)
				Monitor.Enter(m_qBuffers.SyncRoot);
				hdr = (WaveHeader)m_qBuffers.Dequeue();
				Monitor.Exit(m_qBuffers.SyncRoot);

				// play the file
				CheckWaveError(Wave.waveOutWrite(m_hWaveOut, hdr.Header, hdr.HeaderLength));
				
				// Add more buffers
				RefillPlayBuffers();
			}
			
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -