C#实现通过winmm.dll控制声音播放的方法

下面是“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技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • c#调用arcgis地图rest服务示例详解(arcgis地图输出)

    在介绍 “C#调用ArcGIS地图REST服务示例详解(ArcGIS地图输出)”这个话题之前,简单介绍一下ArcGIS。 ArcGIS是一款专业的地理信息系统软件,全称“Environmental Systems Research Institute (ESRI) ArcGIS”。ArcGIS提供了从数据收集到最终生产的一整套地理信息系统软件。ArcGIS中…

    C# 2023年5月31日
    00
  • VS2010中lib与dll文件的生成与使用方法

    VS2010中lib与dll文件的生成与使用方法,包括以下几个步骤: 步骤 1:新建项目 在Visual Studio 2010中,点击菜单“文件” → “新建项目”,在“新建项目”窗口中选择“Win32控制台应用程序”,取一个合适的项目名称,例如“DllTest”,点击“确定”。 在“Win32应用程序向导”的第一个对话框中,选择“DLL”,然后点击“下一…

    C# 2023年6月7日
    00
  • C#中的multipart/form-data提交文件和参数

    下面是一份详细讲解C#中使用multipart/form-data格式提交文件和参数的攻略。 什么是multipart/form-data格式 multipart/form-data是一种编码格式,用于将数据和文件上传到服务器。以表单的形式提交数据时,包含了文本类型的参数和文件类型的参数。其中,文本类型的参数通过键值对的方式提交,而文件类型的参数需要以二进制…

    C# 2023年6月1日
    00
  • 字符串阵列String[]转换为整型阵列Int[]的实例

    将字符串数组String[]转换为整型数组int[]是编程中很常见的操作,我们可以使用Java提供的内置函数进行转换。 以下是转换的完整攻略: 1.遍历字符串数组 首先,我们需要遍历字符串数组String[],并且将每个元素转换为整型。 String[] strArray = {"10", "20", "30…

    C# 2023年6月8日
    00
  • C# Directory.GetDirectories – 获取目录下的所有子目录

    Directory.GetDirectories 方法的作用是获取指定目录中的所有子目录的名称。 使用方法: string[] directories = Directory.GetDirectories(path); 其中 path 参数为要获取子目录的目录路径。返回值 directories 为一个字符串数组,包含指定目录中所有的子目录名称。 该方法还有…

    C# 2023年4月19日
    00
  • 微信公众平台开发之自定义菜单.Net代码解析

    微信公众平台开发之自定义菜单.Net代码解析 本文将详细讲解在.Net平台下,如何进行微信公众平台的自定义菜单开发,并附带两个样例说明。 前置要求 一台拥有.NET平台开发环境的计算机 已经完成微信公众号认证并获取了公众号的基本信息(如AppID、AppSecret) 至少掌握基本的微信公众平台接口调用方式 开发思路 获取Access Token 使用Acc…

    C# 2023年5月31日
    00
  • C# Aspose.Words 删除word中的图片操作

    下面是详细讲解“C# Aspose.Words 删除word中的图片操作”的完整攻略: 1. 引用Aspose.Words库 在Visual Studio中,打开项目,右键项目,选择“管理NuGet程序包”,搜索Aspose.Words并安装。 2. 打开Word文档 Document doc = new Document("example.doc…

    C# 2023年5月31日
    00
  • Powershell小技巧之非相同域或信任域也能远程

    Powershell小技巧之非相同域或信任域也能远程 在使用Powershell远程管理计算机时,如果计算机不在相同的域或信任域中,可能会遇到一些问题。本文将介绍如何使用Powershell远程管理非相同域或信任域中的计算机。 步骤1:使用Powershell的New-PSSession命令 首先,我们需要使用Powershell的New-PSSession…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部