基于VC的ACM音频编程接口压缩Wave音频(二)

(二)获取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("多格式转换 ");

  ACMDRIVERDETAILS add;
  acmdd.cbStruct = sizeof(acmdd);
  MMRESULT mmr = acmDriverDetails(hadid, &acmdd, 0);
  if (mmr)
    error_msg(mmr);
  else
  {
    printf(" 全称: %s ", acmdd.szLongName);
    printf(" 描述: %s ", 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
", pafd- >dwFormatTag, pafd- >szFormat); return TRUE; } 

上 面 介 绍 了 浏 览 系 统 中 所 有 音 频CODECs 及 每 种CODEC 所 支 持 的 音 频 格 式 的 方 法, 某 些 典 型 的 应 用 程 序 可 能 需 要 列 出 系 统 中 所 有 可 以 选 用 的CODECs, 并 由 用 户 来 选 择 使 用 哪 一 种CODEC 进 行 压 缩, 此 时 就 需 要 利 用 上 面 的 编 程 方 法 来 获 取CODECs 的 信 息。

版权申明:本站文章均来自网络,如有侵权,请评论 ,收到后立即删除,谢谢!

原文地址:https://www.cnblogs.com/wanghoney/p/3453874.html