下面是“C#实现通过winmm.dll控制声音播放的方法”的完整攻略:
1.简介
Winmm.dll是Windows操作系统中的一个动态链接库文件,它包含了负责音频的相关函数,通过调用这些函数我们可以实现对音频的控制。本文将介绍C#通过调用winmm.dll实现控制声音播放的方法。
2.winmm.dll 函数介绍
首先,我们需要了解winmm.dll中的一些重要函数:
- waveOutOpen:打开音频输出设备,并且获取音频输出设备句柄。
- waveOutSetVolume:设置音量,0表示静音,65536表示最大音量。
- waveOutWrite:将音频数据写入音频输出设备缓冲区,并开始播放音频。
- waveOutPause:暂停音频播放。
- waveOutRestart:继续音频播放。
- waveOutReset:停止音频播放,并且清空音频输出设备缓冲区。
- waveOutClose:关闭音频输出设备。
3.实现方法
要在C#中调用winmm.dll中的函数,我们需要使用DllImport特性来声明这些函数,在使用前需要引用System.Runtime.InteropServices命名空间。
示例1:播放指定路径下的wav音频文件:
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("winmm.dll")]
static extern int waveOutOpen(out IntPtr hwo, uint uDeviceID, ref WAVEFORMATEX lpFormat, IntPtr dwCallback, IntPtr dwInstance, uint fdwOpen);
[DllImport("winmm.dll")]
static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
[DllImport("winmm.dll")]
static extern int waveOutWrite(IntPtr hwo, ref WAVEHDR pwh, uint cbwh);
[DllImport("winmm.dll")]
static extern int waveOutPause(IntPtr hwo);
[DllImport("winmm.dll")]
static extern int waveOutRestart(IntPtr hwo);
[DllImport("winmm.dll")]
static extern int waveOutReset(IntPtr hwo);
[DllImport("winmm.dll")]
static extern int waveOutClose(IntPtr hwo);
[StructLayout(LayoutKind.Sequential)]
public struct WAVEFORMATEX
{
public ushort wFormatTag;
public ushort nChannels;
public uint nSamplesPerSec;
public uint nAvgBytesPerSec;
public ushort nBlockAlign;
public ushort wBitsPerSample;
public ushort cbSize;
}
[StructLayout(LayoutKind.Sequential)]
public struct WAVEHDR
{
public IntPtr lpData;
public uint dwBufferLength;
public uint dwBytesRecorded;
public IntPtr dwUser;
public uint dwFlags;
public uint dwLoops;
public IntPtr lpNext;
public IntPtr reserved;
}
static void Main(string[] args)
{
string filePath = @"D:\music.wav";
WAVEFORMATEX waveFormatEx = new WAVEFORMATEX
{
wFormatTag = 1,
nChannels = 2,
nSamplesPerSec = 44100,
nAvgBytesPerSec = 176400,
nBlockAlign = 4,
wBitsPerSample = 16,
cbSize = 0
};
IntPtr hWaveOut;
waveOutOpen(out hWaveOut, 0, ref waveFormatEx, IntPtr.Zero, IntPtr.Zero, 0);
IntPtr hFile = Win32Api.CreateFile(filePath, Win32Api.GENERIC_READ, Win32Api.FILE_SHARE_READ, IntPtr.Zero, Win32Api.OPEN_EXISTING, 0, IntPtr.Zero);
uint cbData = Win32Api.GetFileSize(hFile, IntPtr.Zero);
IntPtr pData = Marshal.AllocHGlobal((int)cbData);
Win32Api.ReadFile(hFile, pData, cbData, out uint bytesRead, IntPtr.Zero);
WAVEHDR waveHdr = new WAVEHDR
{
lpData = pData,
dwBufferLength = cbData,
dwFlags = 0
};
waveOutWrite(hWaveOut, ref waveHdr, (uint)Marshal.SizeOf(typeof(WAVEHDR)));
Console.ReadKey();
waveOutPause(hWaveOut);
waveOutReset(hWaveOut);
waveOutClose(hWaveOut);
Win32Api.CloseHandle(hFile);
Marshal.FreeHGlobal(pData);
}
}
static class Win32Api
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32", SetLastError = true)]
public extern static UInt32 GetFileSize(IntPtr hFile, IntPtr lpFileSizeHigh);
public const uint GENERIC_READ = 0x80000000;
public const uint FILE_SHARE_READ = 0x00000001;
public const uint OPEN_EXISTING = 3;
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr hObject);
}
}
示例2:通过麦克风录制音频并播放:
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
[DllImport("winmm.dll")]
static extern int waveInOpen(out IntPtr hwi, uint uDeviceID, ref WAVEFORMATEX lpFormat, IntPtr dwCallback, IntPtr dwInstance, uint fdwOpen);
[DllImport("winmm.dll")]
static extern int waveInClose(IntPtr hwi);
[DllImport("winmm.dll")]
static extern int waveInStart(IntPtr hwi);
[DllImport("winmm.dll")]
static extern int waveInStop(IntPtr hwi);
[DllImport("winmm.dll")]
static extern int waveOutOpen(out IntPtr hwo, uint uDeviceID, ref WAVEFORMATEX lpFormat, IntPtr dwCallback, IntPtr dwInstance, uint fdwOpen);
[DllImport("winmm.dll")]
static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
[DllImport("winmm.dll")]
static extern int waveOutWrite(IntPtr hwo, ref WAVEHDR pwh, uint cbwh);
[DllImport("winmm.dll")]
static extern int waveOutPause(IntPtr hwo);
[DllImport("winmm.dll")]
static extern int waveOutReset(IntPtr hwo);
[DllImport("winmm.dll")]
static extern int waveOutClose(IntPtr hwo);
[StructLayout(LayoutKind.Sequential)]
public struct WAVEFORMATEX
{
public ushort wFormatTag;
public ushort nChannels;
public uint nSamplesPerSec;
public uint nAvgBytesPerSec;
public ushort nBlockAlign;
public ushort wBitsPerSample;
public ushort cbSize;
}
[StructLayout(LayoutKind.Sequential)]
public struct WAVEHDR
{
public IntPtr lpData;
public uint dwBufferLength;
public uint dwBytesRecorded;
public IntPtr dwUser;
public uint dwFlags;
public uint dwLoops;
public IntPtr lpNext;
public IntPtr reserved;
}
static void Main(string[] args)
{
uint deviceID = 0;
WAVEFORMATEX waveFormatEx = new WAVEFORMATEX
{
wFormatTag = 1,
nChannels = 2,
nSamplesPerSec = 44100,
nAvgBytesPerSec = 176400,
nBlockAlign = 4,
wBitsPerSample = 16,
cbSize = 0
};
IntPtr hWaveIn;
waveInOpen(out hWaveIn, deviceID, ref waveFormatEx, IntPtr.Zero, IntPtr.Zero, 0);
WAVEHDR[] waveHdrArray = new WAVEHDR[2];
for (int i = 0; i < 2; i++)
{
waveHdrArray[i] = new WAVEHDR
{
lpData = Marshal.AllocHGlobal(waveFormatEx.nAvgBytesPerSec),
dwBufferLength = waveFormatEx.nAvgBytesPerSec,
dwFlags = 0
};
waveInPrepareHeader(hWaveIn, ref waveHdrArray[i], (uint)Marshal.SizeOf(typeof(WAVEHDR)));
}
for (int i = 0; i < 2; i++)
{
waveInAddBuffer(hWaveIn, ref waveHdrArray[i], (uint)Marshal.SizeOf(typeof(WAVEHDR)));
}
waveOutOpen(out IntPtr hWaveOut, deviceID, ref waveFormatEx, IntPtr.Zero, IntPtr.Zero, 0);
waveOutSetVolume(hWaveOut, 0xFFFF);
waveOutWrite(hWaveOut, ref waveHdrArray[0], (uint)Marshal.SizeOf(typeof(WAVEHDR)));
waveInStart(hWaveIn);
Console.ReadKey();
waveInStop(hWaveIn);
waveOutReset(hWaveOut);
for (int i = 0; i < 2; i++)
{
waveInUnprepareHeader(hWaveIn, ref waveHdrArray[i], (uint)Marshal.SizeOf(typeof(WAVEHDR)));
Marshal.FreeHGlobal(waveHdrArray[i].lpData);
}
waveInClose(hWaveIn);
waveOutClose(hWaveOut);
}
[DllImport("winmm.dll")]
static extern int waveInPrepareHeader(IntPtr hwi, ref WAVEHDR pwh, uint cbwh);
[DllImport("winmm.dll")]
static extern int waveInUnprepareHeader(IntPtr hwi, ref WAVEHDR pwh, uint cbwh);
[DllImport("winmm.dll")]
static extern int waveInAddBuffer(IntPtr hwi, ref WAVEHDR pwh, uint cbwh);
}
static class Win32Api
{
public const uint GENERIC_READ = 0x80000000;
public const uint FILE_SHARE_READ = 0x00000001;
public const uint OPEN_EXISTING = 3;
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32", SetLastError = true)]
public extern static UInt32 GetFileSize(IntPtr hFile, IntPtr lpFileSizeHigh);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr hObject);
}
}
在以上两个示例中,我们先使用waveOutOpen或waveInOpen打开音频输出或输入设备获取句柄,然后设置音量大小、调用waveOutWrite或waveInAddBuffer写入音频数据、调用waveOutPause、waveOutReset、waveOutClose或waveInStop、waveInUnprepareHeader或waveOutUnprepareHeader和Marshal.FreeHGlobal等函数来实现音频的播放或录制并且清理资源。
4.总结
本文介绍了通过调用winmm.dll实现控制声音播放的方法,介绍了winmm.dll中的一些重要函数,同时提供了两个示例来演示播放wav音频、录制并播放麦克风音频的完整过程。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#实现通过winmm.dll控制声音播放的方法 - Python技术站