📄 lc_bcb_25.html
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>一 种 计 算CD 标 识 的 算 法</title>
</head>
<body>
<h2 align="center">一 种 计 算CD 标 识 的 算 法</h2>
<h3 align="center">北 京 市167 信 箱(100036) 王 亚 军 </h3>
<hr align="center">
<p><font color="#ffffff">----</font> 本 文 介 绍 了 关 于 音 乐CD 的 红 皮 书
格 式。 文 章 从 如 何 根 据 数 据 格 式, 调 用Windows MCI 接 口 函
数, 利 用 一 定 算 法 计 算CD 之ID 号, 用 来 唯 一 标 识CD 等 方
面 阐 述 和 说 明, 具 有 一 定 的 应 用 价 值。 </p>
<h3>一、 红 皮 书 格 式 </h3>
<p><font color="#ffffff">----</font>在 光 盘 格 式 家 族 中, 大 家 较 熟 悉
的 有 红 皮 书、 黄 皮 书、 白 皮 书 以 及 桔 皮 书 等 多 种 标
准。 这 些 格 式 有 个 共 同 的 特 点, 就 是 光 盘 最 小 分 配 单
位 是 长 度 为2352 个 字 节 的 扇 区; 当 然, 并 不 是 所 有 的2352
个 字 节 都 可 为 用 户 所 用, 这 要 看 具 体 是 哪 个 标 准。 例
如, 黄 皮 书 格 式 中2352 个 字 节 要 扣 除 一 些 检 错 和 纠 错 的
开 销, 只 有2048 个 字 节 是 真 正 存 放 用 户 数 据 的。 </p>
<p><font color="#ffffff">----</font>红 皮 书 格 式 是1980 年PHILIP 和SONY 联 合
颁 布 的, 又 称CD -DA 格 式, 是 为 控 制 音 频CD 建 立 的 标 准。
它 是 国 际 标 准ISO10149。 红 皮 书 标 准 规 范 了 光 盘 尺 寸、 塑
料 的 光 参 数、 录 放 环 境、 信 号 测 量、 保 真 度 以 及 音 乐
波 形 数 字 文 件 结 构。 红 皮 书 音 频 的 数 字 化 方 式 用44.1kHz
的 采 样 频 率、16 级 量 化 电 平 而 且 是 双 通 道 记 录 和 线 形
格 式。 现 已 成 为 音 乐 工 业 中 的 事 实 标 准。 主 要 有 以 下
内 容:
<ul>
<li>最 多99 首 歌 曲(track, 即 音 轨); </li>
<li>每 扇 区2352 字 节 均 用 来 存 放 声 音 数 据; </li>
<li>声 音 数 据 为 采 样 率44.1K、16 比 特 量 化 的PCM 信 号; </li>
<li>立 体 声; </li>
<li>无 目 录 和 文 件 结 构, 连 续 存 放PCM 信 号; </li>
<li>播 放 时 按 每 秒75 扇 区 的 速 度; </li>
<li>每 张 光 盘 最 多74 分 钟。 <p><font color="#ffffff">----</font>音 频 数 据
不 像 其 他 计 算 机 数 据( 如 程 序 文 件) 那 样 对 错 误 具 有
极 大 的 敏 感 性( 一 般 对 误 码 具 敏 感 性 的 数 据 不 能 容 忍1
比 特 的 错 误), 因 此 每 扇 区 的2352 个 字 节 无 需 额 外 的 检
错 纠 错 的 开 销, 均 可 用 来 存 放 音 频 数 据。 这 样, 每 个
扇 区 能 存 放 的 音 乐 时 间 为2352/(16/8 ×2 ×44100)=1/75 秒, 因 此
播 放 速 度 为75 扇 区 / 秒。 扇 区 地 址 与 播 放 时 间 具 有 一 一
对 应 的 关 系; 在CD -DA 格 式 中, 用 时 间MSF 格 式 表 示, 标
记 为 00:00:00 格 式: <br>
<font color="#ffffff">----</font>M: 分 钟 数, 以 一 个 字 节 表 示; <br>
<font color="#ffffff">----</font>S: 秒 数, 范 围0 ~59, 以 一 个 字 节 表
示; <br>
<font color="#ffffff">----</font>F: 扇 区 数, 范 围0 ~74, 以 一 个 字 节
表 示, 代 表 有 多 少 个1/75 秒。 </p>
<p><font color="#ffffff">----</font>在ISO 9660 标 准 下, 单 张 的 CD -ROM 被
定 义 为 一 个" 卷", 前150 个 扇 区 用 于 保 存 各 个 音 轨
的 起 始 时 间 以 及 光 盘 本 身 的 卷 标、 版 权 等 信 息。 所
以, 从MSF 到 绝 对 扇 区 地 址 的 转 换 关 系 为: </p>
<p><font color="#ffffff">----</font> Address = M * 60 * 75 + S * 75 + F + 150
; </p>
<p><font color="#ffffff">----</font>本 人 在 开 发 一 个 个 人CD 收 藏 数 据
库 时 发 现, 各 个CD 出 版 公 司 都 有 自 己 的CD 编 号 规 范, 无
法 统 一, 如: DG 437 667 -2。 因 此, 有 必 要 采 用 一 种 算 法
唯 一 标 识 单 张CD。 基 于 以 上 分 析, 采 用 如 下 算 法, 事 实
证 明 是 可 行 的。 </p>
<h3>二、 算 法 说 明( 程 序 框 架)</h3>
<pre>
struct toc {
int min;
int sec;
int frame;
};// 单 个 音 轨 内 容 表
struct toc cdtoc[100];
// 结 构 数 组, 用 来 存 放 各 个 音 轨 的 内 容
int read_cdtoc_from_drive(void)
{
/ * 将CD 的 内 容 表 读 入cdtoc[] 结 构 数 组 */
return (tot_trks);
}
int cddb_sum(int n)
{
int ret;
/ * 将 传 入 参 数 的 每 位 数 据 累 加 */
ret = 0;
while (n > 0) {
ret = ret + (n % 10);
n = n / 10;
}
return (ret);
}
unsigned long cddb_discid(int tot_trks)
{
int i, t = 0, n = 0;
i = 0;
while (i <tot_trks) { n="n" + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec); i + +; } t="((cdtoc[tot_trks].min" * 60) + cdtoc[tot_trks].sec) -((cdtoc[0].min * 60) + cdtoc[0].sec); return ((n % 0xff) << 24 | t << 8 | tot_trks); } main() { int tot_trks; tot_trks="read_cdtoc_from_drive();" printf("The discid is %08x", cddb_discid(tot_trks)); } </pre>
</pre>
<h3>三、 使 用 </h3>
<p><font color="#ffffff">----</font>假 设 你 的 编 译 器 支 持32 位 整 数,
cddb_discid 函 数 计 算discid, 基 于CD 的 内 容 表, 按 照MSF 格 式,
故 意 忽 略 了 扇 区 数, 函 数 接 收tot_trks 参 数(CD 的 音 轨 总
数), 返 回discid 这 个 整 数。 假 设cdtoc[] 是 一 个 结 构 数 组,
每 个 结 构 包 含 分 钟 数、 秒 数 和 扇 区 数 三 个 域, 它 们 实
际 上 是 每 个 音 轨 的 分 钟 数、 秒 数 和 扇 区 数 的 偏 移 量。
这 些 信 息 从CD 的 内 容 表 中 读 出, 数 组 中 实 际 上 有tot_trks
+ 1 个 元 素, 最 后 一 个 是 个 虚 拟 音 轨, 即 最 外 一 个 音
轨 末 端 的 偏 移 量, 或 称 为 顶 头 音 轨( 也 称 音 轨0xAA),
函 数 循 环 检 测 内 容 表 中 的 每 个 音 轨, 计 算 每 个 音 轨 的(M
* 60) + S( 按 秒 计 算 偏 移 量), 并 把 结 果 给cddb_sum() 函
数, 该 函 数 把 数 据 中 的 每 个 数 字 累 加, 每 个 音 轨 的 结
果 保 存 在 变 量n 中。 </p>
<p><font color="#ffffff">----</font>循 环 结 束 时 <ol>
<li>用 顶 头 音 轨 的 偏 移 量(M *60 +S) 减 去 第 一 个 音 轨 的
偏 移 量 (M *60 +S), 按 秒 计 算disk 的 长 度。 </li>
<li>用n 对0xff 取 余, 将 结 果 左 移24 位。 </li>
<li>把t 左 移8 位。</li>
</ol>
<p><font color="#ffffff">----</font>把2、3 所 得 结 果 连 同tot_trks 进 行 或
运 算, 结 果 便 是diskid。 </p>
<p><font color="#ffffff">----</font>为 了 建 库 方 便,diskid 用16 进 制 代
表, 如 果 少 于8 位 字 符 串, 前 面 补0,( 如3a8f07 变 为003a8f07),
为 方 便 起 见, 其 中 的 字 母 用 小 写。 </p>
<p><font color="#ffffff">----</font>使 用MS -Windows MCI 接 口 的 用 户 应 注
意: </p>
<p><font color="#ffffff">----</font>Windows MCI 接 口 不 提 供 顶 头 音 轨 的MSF
位 置, 因 此, 你 必 须 通 过 计 算 最 后 一 个 音 轨 的 起 始 位
置 加 上 最 后 一 个 音 轨 的 长 度 来 得 到 它。 然 而,MCI 接 口
返 回 最 后 一 个 音 轨 的 长 度 比CD 的Toc 中 所 存 的 长 度 少 一
桢, 大 多 数 情 况 下, 这 不 影 响 产 生 的ID, 因 为, 计 算disk
ID 时, 总 要 截 掉 桢 数。 然 而, 如 果 顶 头 音 轨 的 桢 数 为0,
秒 数 会 减 一, 桢 数 成 为74, 例 如: 一 张CD 最 后 一 个 音 轨
在 偏 移 量48m 32s 12f 处, 该 音 轨 长 度 为2m 50s 63f, 顶 头 偏 移 量51m
23s 0f, Windows MCI 错 误 报 告 长 度 为2m 50s 62f, 这 会 产 生51m 22s 74f
的 顶 头 偏 移 量, 这 样 导 致 长 度 被 截 断 一 秒, 从 而 使 得disk
ID 不 正 确。 这 样, 当 你 计 算 顶 头 位 置 的 时 候, 在 最 后
一 个 音 轨 的 长 度 上 加 上 一 桢。 </p>
<p><font color="#ffffff">----</font>对 于Windows 客 户 来 说, 按 照MSF 格 式
计 算 顶 头 的 最 简 便 的 方 法 是: <br>
(offset_minutes * 60 * 75) +(offset_seconds * 75) +offset_frames +
(length_minutes * 60 * 75) +(length_seconds * 75) + length_frames +1=X <br>
X 是 按 桢 计 算 的 顶 头 偏 移 量, 若 按 秒 计 算, 只 需 简 单
地 用75 除, 消 掉 余 数 即 可。 </p>
</li>
</ul>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -