(二)获取CODECs 的 信 息
ACM 的API 函 数 定 义 在 头 文 件msacm.h 中, 除 此 之 外, 对ACM 编 程 还 必 须 包 含 头 文 件mmsystem.h,mmreg.h, 这 两 个 头 文 件 定 义 了 多 媒 体 编 程 中 最 基 本 的 常 量 和 数 据 结 构;
1.ACM版本信息:为 了 避 免 有 些 高 版 本ACM 才 提 供 的 函 数 和 功 能 在 较 低 版 本 的ACM 中 上 不 可 用, 程 序 中 应 调 用acmGetVersion 函 数 查 询 用 户 机 器 中ACM 的 版 本 信 息;
2.查看系统CODECs信息:在 控 制 面 板 中 可 以 查 看 系 统 中CODECs 的 信 息, 而 在 应 用 程 序 中 也 常 常 需 要 知 道 某 种 音 频CODECs 是 否 存 在, 并 获 取 其 编 解 码 参 数 等 信 息, 这 一 点 可 以 通 过 调 用 下 面 两 个 函 数 来 实 现。
MMRESULT mmr = acmMetrics(NULL, ACM_METRIC_COUNT_CODECS, &dwCodecs);
mmr = acmDriverEnum(CodecsEnumProc, 0, 0);
acmMetrics函数可以获取许多ACM对象的有用信息,例如向其中传递ACM_METRIC_COUNT_CODECS可以查询系统中安装的音频CODECs总数;传递ACM_METRIC_MAX_SIZE_FORMAT获取GSM6.10格式Format Chunk的附加数据长度;
acmDriverEnum函数的功能是枚举所有的音频CODECs,在acmDriverEnum() 的参数中指定回调函数CodecsEnumProc()可以进一步查询每个CODEC的信息;
BOOL CALLBACK CodecsEnumProc(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport)
{
DWORD dwSize = 0;
if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
printf("多格式转换\n");
ACMDRIVERDETAILS add;
acmdd.cbStruct = sizeof(acmdd);
MMRESULT mmr = acmDriverDetails(hadid, &acmdd, 0);
if (mmr)
error_msg(mmr);
else
{
printf(" 全称: %s\n", acmdd.szLongName);
printf(" 描述: %s\n", acmdd.szFeatures);
}
HACMDRIVER had = NULL;
mmr = acmDriverOpen(&had, hadid, 0); //打开驱动程序
if (mmr)
error_msg(mmr);
else
{
mmr = acmMetrics(had, ACM_METRIC_ MAX_SIZE_FORMAT, &dwSize);
WAVEFORMATEX* pwf = (WAVEFORMATEX*) malloc(dwSize);
memset(pwf, 0, dwSize);
pwf->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);
pwf->wFormatTag = WAVE_FORMAT_UNKNOWN;
ACMFORMATDETAILS fd;
memset(&fd, 0, sizeof(fd));
fd.cbStruct = sizeof(fd);
fd.pwfx = pwf;
fd.cbwfx = dwSize;
fd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
mmr = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
if (mmr)
error_msg(mmr);
free(pwf);
acmDriverClose(had, 0);
}
return TRUE;
}
CodecsEnumProc()共有三个参 数。 第 一 个 参 数 是 驱 动 程 序 的ID 值; 第 二 个 参 数 是 实 例 数 据, 本 文 例 子 中 未 使 用; 第 三 个 参 数 描 述 该 驱 动 程 序 所 支 持 的 功 能, 它 由 一 组 标 识 进 行 或 运 算 构 成, 例 如, 如 果 设 置 了 标 识ACMDRIVERDETAILS_SUPPORTF_CODEC, 则 说 明 该 驱 动 程 序 可 以 将 一 种 编 码 格 式 的 音 频 信 号 转 换 成 另 一 种 编 码 格 式。 通 过acmDriverDetails() 函 数 可 以 获 得 对 该 驱 动 程 序 进 一 步 的 信 息, 如CODEC 的 名 称、 简 单 描 述 等。 以 上 信 息 实 际 上 是 由ACM 收 集, 并 保 存 在ACM 内 部, 所 以 查 询 以 上 信 息 时 并 未 真 正 将 驱 动 程 序 加 载 至 内 存。 而 要 获 得 每 一 种 驱 动 程 序 支 持 的 音 频 格 式 信 息, 则 必 须 将 驱 动 程 序 加 载 至 内 存, 这 是 通 过acmDriverOpen() 完 成 的, 在 退 出CodecsEnumProc() 前, 还 要 用acmDriverClose() 来 关 闭 已 打 开 的 驱 动 程 序。
在 使 用 音 频 格 式 枚 举 函 数 前, 需 要 先 分 配 一 块 缓 冲 区 存 置 格 式 信 息, 缓 冲 区 的 大 小 可 通 过 调 用acmMetrics() 查 询ACM_METRIC_MAX_SIZE_FORMAT 获 得, 格 式 信 息 中 的 音 频 格 式 标 识 设 为WAVE_FORMAT_UNKNOWN。 在 音 频 格 式 枚 举 中 同 样 使 用 了 回 调 函 数, 此 回 调 函 数 只 是 列 出 了 该 音 频 格 式 的 名 称 和 标 识 值。
BOOL CALLBACK FormatEnumProc (HACMDRIVERID hadid, LPACMFORMATDETAILS pafd, DWORD dwInstance, DWORD fdwSupport) { printf("%4.4lXH, %s\n", pafd- >dwFormatTag, pafd- >szFormat); return TRUE; }
上 面 介 绍 了 浏 览 系 统 中 所 有 音 频CODECs 及 每 种CODEC 所 支 持 的 音 频 格 式 的 方 法, 某 些 典 型 的 应 用 程 序 可 能 需 要 列 出 系 统 中 所 有 可 以 选 用 的CODECs, 并 由 用 户 来 选 择 使 用 哪 一 种CODEC 进 行 压 缩, 此 时 就 需 要 利 用 上 面 的 编 程 方 法 来 获 取CODECs 的 信 息。