C语言中mmsystem如何实现音频播放控制?

99ANYc3cd6
预计阅读时长 20 分钟
位置: 首页 C语言 正文

mmsystem 是 Windows 操作系统上一个非常重要的多媒体编程接口,全称是 Windows Multimedia System,它不是 C 语言的标准库,而是微软为 Windows 提供的一个 API(应用程序编程接口),专门用于处理与多媒体相关的任务,比如播放声音、MIDI 音乐、控制媒体设备(如 CD-ROM、MIDI 合成器)等。

c语言mmsystem
(图片来源网络,侵删)

在 C 语言中,你只需要包含对应的头文件并链接对应的库文件,就可以使用这些强大的功能。


核心概念

要使用 mmsystem,你需要了解以下几个核心概念:

a. 头文件和库

  • 头文件: #include <mmsystem.h>
  • 库文件: winmm.lib (在 Visual Studio 中通常自动链接;在 MinGW/GCC 中需要手动添加 -lwinmm)

b. 常用数据类型

  • MMRESULT: 一个用于表示多媒体函数执行结果的 32 位无符号整数,类似于 DWORD,函数成功时通常返回 MMSYSERR_NOERROR (值为 0),失败时返回一个错误码。
  • HWAVEOUT: 波形音频输出设备的句柄,你可以把它想象成一个指向特定声卡输出通道的“指针”或“引用”。
  • HWAVEIN: 波形音频输入设备的句柄(用于录音)。
  • HMIDIOUT: MIDI 输出设备的句柄。
  • HMIDIIN: MIDI 输入设备的句柄。
  • MCIERROR: 媒体控制接口函数的返回值。

c. 核心功能模块

mmsystem 主要包含两大块功能:

  1. Windows Multimedia API (MMAPI): 提供了对底层音频设备(波形音频、MIDI)的直接控制能力,功能强大但相对复杂,需要手动管理内存和设备状态。
  2. Media Control Interface (MCI): 一个更高级、更简单的命令接口,它通过发送文本命令(如 "play c:\\my_music\\song.wav")来控制各种媒体设备,包括 CD 音频、数字视频、MIDI 等,MCI 会帮你处理底层的复杂性。

主要功能详解与代码示例

下面我们通过代码示例来展示 mmsystem 的常见用法。

c语言mmsystem
(图片来源网络,侵删)

示例 1:播放一个 WAV 文件 (使用高级 API PlaySound)

这是最简单、最常用的播放声音的方法。PlaySound 是一个高级函数,适合播放简短的音效。

#include <windows.h>  // PlaySound 函数定义在这里
#include <mmsystem.h> // 虽然 PlaySound 在 windows.h 中,但 mmsystem.h 提供了更多相关定义
#include <stdio.h>
int main() {
    const char* wavFilePath = "C:\\Windows\\Media\\chimes.wav"; // 使用一个系统自带的 WAV 文件作为示例
    printf("正在播放 WAV 文件: %s\n", wavFilePath);
    // PlaySound 函数
    // 第一个参数: WAV 文件路径或一个内存中的声音标识
    // 第二个参数: 保留,设为 NULL
    // 第三个参数: 标志位,SND_FILENAME 表示第一个参数是文件名;SND_ASYNC 表示异步播放(函数立即返回,声音在后台播放)
    if (!PlaySound(wavFilePath, NULL, SND_FILENAME | SND_ASYNC)) {
        printf("播放失败!错误码: %lu\n", GetLastError());
    }
    printf("播放命令已发送,程序将继续执行...\n");
    Sleep(5000); // 暂停 5 秒,让声音有时间播放完
    printf("程序结束,\n");
    return 0;
}

如何编译和运行 (以 MinGW/GCC 为例):

gcc -o playsound_example playsound_example.c -lwinmm
playsound_example.exe

示例 2:播放 MIDI 音乐 (使用 MCI)

MCI 接口非常适合播放像 MIDI 这样需要持续播放的媒体,它通过发送命令字符串来工作。

#include <mmsystem.h>
#include <stdio.h>
#include <windows.h>
int main() {
    const char* midiFilePath = "C:\\Windows\\Media\\flourish.mid"; // 系统自带的 MIDI 文件
    MCIERROR mciError;
    printf("正在打开 MIDI 文件: %s\n", midiFilePath);
    // 1. 打开设备
    // "type mpegvideo" 是一个通用类型,MIDI 文件通常也能被识别
    mciError = mciSendString("open \"" + std::string(midiFilePath) + "\" type mpegvideo alias my_midi", NULL, 0, NULL);
    if (mciError != 0) {
        printf("打开 MIDI 文件失败!错误码: %d\n", mciError);
        return 1;
    }
    printf("MIDI 文件已打开,\n");
    // 2. 播放
    mciError = mciSendString("play my_midi", NULL, 0, NULL);
    if (mciError != 0) {
        printf("播放失败!错误码: %d\n", mciError);
        mciSendString("close my_midi", NULL, 0, NULL); // 清理资源
        return 1;
    }
    printf("正在播放 MIDI 音乐...\n");
    Sleep(10000); // 播放 10 秒
    // 3. 停止
    mciError = mciSendString("stop my_midi", NULL, 0, NULL);
    if (mciError != 0) {
        printf("停止失败!错误码: %d\n", mciError);
    }
    // 4. 关闭设备,释放资源
    mciError = mciSendString("close my_midi", NULL, 0, NULL);
    if (mciError != 0) {
        printf("关闭设备失败!错误码: %d\n", mciError);
    }
    printf("MIDI 播放结束,设备已关闭,\n");
    return 0;
}

MCI 常用命令:

c语言mmsystem
(图片来源网络,侵删)
  • open "filename" alias alias_name: 打开一个文件并给它一个别名。
  • play alias_name [from pos] [to pos]: 播放。
  • pause alias_name: 暂停。
  • resume alias_name: 从暂停处恢复。
  • stop alias_name: 停止。
  • close alias_name: 关闭设备。
  • status alias_name length: 获取媒体总长度。
  • seek alias_name to pos: 跳转到指定位置。

示例 3:播放 CD 音轨 (使用 MCI)

MCI 也能直接控制物理设备,CD-ROM 驱动器。

#include <mmsystem.h>
#include <stdio.h>
#include <windows.h>
int main() {
    MCIERROR mciError;
    // 打开 CD 设备,别名设为 "my_cd"
    mciError = mciSendString("open cdaudio alias my_cd", NULL, 0, NULL);
    if (mciError != 0) {
        printf("打开 CD 设备失败!请确保 CD 驱动器中有 CD,\n错误码: %d\n", mciError);
        return 1;
    }
    // 播放第 2 音轨
    printf("正在播放 CD 的第 2 音轨...\n");
    mciError = mciSendString("play my_cd from 2", NULL, 0, NULL);
    if (mciError != 0) {
        printf("播放失败!错误码: %d\n", mciError);
        mciSendString("close my_cd", NULL, 0, NULL);
        return 1;
    }
    Sleep(15000); // 播放 15 秒
    // 停止并关闭
    mciSendString("stop my_cd", NULL, 0, NULL);
    mciSendString("close my_cd", NULL, 0, NULL);
    printf("CD 播放结束,\n");
    return 0;
}

现代替代方案

虽然 mmsystem 非常经典,但在现代 Windows 开发中,对于更复杂的多媒体需求,开发者通常会使用更现代、功能更强大的 API:

  1. DirectShow: 一个功能极其强大的多媒体框架,用于播放几乎所有类型的音视频流,它非常灵活,但学习曲线陡峭。
  2. Windows Media Foundation (WMF): DirectShow 的现代替代品,是 Windows Vista 及以后版本推荐的多媒体平台,它支持更广泛的媒体格式、硬件加速和流媒体处理,是开发新项目的首选。
  3. BASS Audio Library: 一个非常流行的第三方音频库,以其轻量级、高性能和易用性而闻名,特别适合游戏和需要精细音频控制的应用。
特性 mmsystem (PlaySound/MCI) DirectShow / Windows Media Foundation
易用性 非常高,特别是 PlaySound 和 MCI。 较低,需要理解复杂的图和过滤器概念。
功能 基础,适合简单的音效和媒体播放。 非常强大,支持几乎所有格式、流媒体、硬件加速。
平台 旧版 Windows (如 95/98/XP) 仍然支持,新系统也兼容。 现代Windows平台(Vista+)。
适用场景 简单的工具、音效播放、教学示例。 专业媒体播放器、视频编辑软件、游戏、流媒体应用。

对于初学者或只需要简单播放声音的场景,mmsystem 中的 PlaySound 和 MCI 是绝佳的起点,它简单直接,能快速实现功能,如果你正在开发一个复杂的多媒体应用程序,那么就应该转向 DirectShow 或 Windows Media Foundation。

-- 展开阅读全文 --
头像
dede图片延迟加载如何实现?
« 上一篇 04-22
dede软件发布不了怎么办?
下一篇 » 04-22

相关文章

取消
微信二维码
支付宝二维码

目录[+]