C# 调用Win32 API播放PCM数据

		class winmm
		{
			[StructLayout(LayoutKind.Sequential)]
			public struct WAVEFORMATEX
			{
				/// <summary>
				      /// 波形声音的格式
				      /// </summary>
				public WaveFormat wFormatTag;
				/// <summary>
				      /// 音频文件的通道数量
				      /// </summary>
				public UInt16 nChannels; /* number of channels (i.e. mono, stereo...) */

				/// <summary>
				      /// 采样频率
				      /// </summary>
				public UInt32 nSamplesPerSec; /* sample rate */

				/// <summary>
				      /// 每秒缓冲区
				      /// </summary>
				public UInt32 nAvgBytesPerSec; /* for buffer estimation */
				public UInt16 nBlockAlign;  /* block size of data */
				public UInt16 wBitsPerSample; /* number of bits per sample of mono data */
				public UInt16 cbSize;     /* the count in bytes of the size of */
			}

			[StructLayout(LayoutKind.Sequential)]
			public struct WAVEHDR
			{
				/// <summary>
				      /// 缓冲区指针
				      /// </summary>
				public IntPtr lpData;

				/// <summary>
				      /// 缓冲区长度
				      /// </summary>
				public UInt32 dwBufferLength;
				public UInt32 dwBytesRecorded; /* used for input only */
				public IntPtr dwUser;     /* for client's use */

				/// <summary>
				      /// 设置标志
				      /// </summary>
				public UInt32 dwFlags;

				/// <summary>
				      /// 循环控制
				      /// </summary>
				public UInt32 dwLoops;

				/// <summary>
				      /// 保留字段
				      /// </summary>
				public IntPtr lpNext;

				/// <summary>
				      /// 保留字段
				      /// </summary>
				public IntPtr reserved;
			}
			[Flags]
			public enum WaveOpenFlags
			{
				CALLBACK_NULL = 0,
				CALLBACK_FUNCTION = 0x30000,
				CALLBACK_EVENT = 0x50000,
				CallbackWindow = 0x10000,
				CallbackThread = 0x20000,
				WAVE_FORMAT_DIRECT = 0x0008
			}
			public enum WaveMessage
			{
				WIM_OPEN = 0x3BE,
				WIM_CLOSE = 0x3BF,
				WIM_DATA = 0x3C0,
				WOM_CLOSE = 0x3BC,
				WOM_DONE = 0x3BD,
				WOM_OPEN = 0x3BB
			}
			public enum WaveFormat : ushort
			{
				WAVE_FORMAT_PCM = 0x0001,
			}
			/// <summary>
			    /// 默认设备
			    /// </summary>
			public static IntPtr WAVE_MAPPER { get; } = (IntPtr)(-1);

			public delegate void WaveCallback(IntPtr hwi, uint uMsg, uint dwInstance, uint dwParam1, uint dwParam2);

			[DllImport("winmm.dll")]
			public static extern int waveOutOpen(out IntPtr IntPtr, uint uDeviceID, WAVEFORMATEX lpFormat,
			WaveCallback dwCallback, int dwInstance, int dwFlags);

			[DllImport("winmm.dll")]
			public static extern int waveOutSetVolume(IntPtr hwo, ushort dwVolume);

			[DllImport("winmm.dll")]
			public static extern int waveOutClose(in IntPtr IntPtr);

			[DllImport("winmm.dll")]
			public static extern int waveOutPrepareHeader(IntPtr IntPtr, in WAVEHDR lpWaveOutHdr, int uSize);

			[DllImport("winmm.dll")]
			public static extern int waveOutUnprepareHeader(IntPtr IntPtr, in WAVEHDR lpWaveOutHdr, int uSize);

			[DllImport("winmm.dll")]
			public static extern int waveOutWrite(IntPtr IntPtr, in WAVEHDR lpWaveOutHdr, int uSize);
		}
		/// <summary>
		  /// Pcm播放器
		  /// </summary>
		public unsafe class PcmPlayer
		{
			IntPtr _hwo = IntPtr.Zero;
			private IntPtr free_pwfx = IntPtr.Zero;
			winmm.WAVEFORMATEX _wfx;
			/// <param name="channels">声道数目</param>
			    /// <param name="sampleRate">采样频率</param>
			    /// <param name="sampleSize">采样大小(bits)</param>
			public PcmPlayer(int channels, int sampleRate, int sampleSize)
			{
				_wfx = new winmm.WAVEFORMATEX
				{
					wFormatTag = winmm.WaveFormat.WAVE_FORMAT_PCM,
					nChannels = (ushort)channels,
					nSamplesPerSec = (ushort)sampleRate,
					wBitsPerSample = (ushort)sampleSize
				};

				_wfx.nBlockAlign = (ushort)(_wfx.nChannels * _wfx.wBitsPerSample / 8);
				_wfx.nAvgBytesPerSec = _wfx.nBlockAlign * _wfx.nSamplesPerSec;
				this.free_pwfx = MarshalUtils.CreateStructurePointer(_wfx);
			}

			public void Open(winmm.WaveCallback wavecall )
			{
				winmm.waveOutOpen(out _hwo, 0xFFFFFFFF,
					_wfx, wavecall, 0,
					waveIn.WAVE_FORMAT_DIRECT | waveIn.CALLBACK_FUNCTION);
			}
			winmm.WAVEHDR _wh;
			private bool def = false;
			public void WriteData(byte[] buffer)
			{
				_wh = new winmm.WAVEHDR();
				_wh.lpData = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
				_wh.dwBufferLength = (uint)buffer.Length;
				_wh.dwFlags = 0;
				_wh.dwLoops = 1;

				winmm.waveOutPrepareHeader(_hwo, _wh, sizeof(winmm.WAVEHDR)); //准备一个波形数据块用于播放
				winmm.waveOutWrite(_hwo, _wh, sizeof(winmm.WAVEHDR));     //在音频媒体中播放第二个函数wh指定的数据
			}

			public void Dispose()
			{
				winmm.waveOutUnprepareHeader(_hwo, _wh, sizeof(winmm.WAVEHDR));
				winmm.waveOutClose(_hwo);
				_hwo = IntPtr.Zero;
			}
		}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值