一種計算CD標識的算法
2019-09-06 23:33:45
供稿:網友
北 京 市167 信 箱(100036) 王 亞 軍
---- 本 文 介 紹 了 關 于 音 樂CD 的 紅 皮 書 格 式。 文 章 從 如 何 根 據 數 據 格 式, 調 用Windows MCI 接 口 函 數, 利 用 一 定 算 法 計 算CD 之ID 號, 用 來 唯 一 標 識CD 等 方 面 闡 述 和 說 明, 具 有 一 定 的 應 用 價 值。
一、 紅 皮 書 格 式
----在 光 盤 格 式 家 族 中, 大 家 較 熟 悉 的 有 紅 皮 書、 黃 皮 書、 白 皮 書 以 及 桔 皮 書 等 多 種 標 準。 這 些 格 式 有 個 共 同 的 特 點, 就 是 光 盤 最 小 分 配 單 位 是 長 度 為2352 個 字 節 的 扇 區; 當 然, 并 不 是 所 有 的2352 個 字 節 都 可 為 用 戶 所 用, 這 要 看 具 體 是 哪 個 標 準。 例 如, 黃 皮 書 格 式 中2352 個 字 節 要 扣 除 一 些 檢 錯 和 糾 錯 的 開 銷, 只 有2048 個 字 節 是 真 正 存 放 用 戶 數 據 的。
----紅 皮 書 格 式 是1980 年PHILIP 和SONY 聯 合 頒 布 的, 又 稱CD -DA 格 式, 是 為 控 制 音 頻CD 建 立 的 標 準。 它 是 國 際 標 準ISO10149。 紅 皮 書 標 準 規 范 了 光 盤 尺 寸、 塑 料 的 光 參 數、 錄 放 環 境、 信 號 測 量、 保 真 度 以 及 音 樂 波 形 數 字 文 件 結 構。 紅 皮 書 音 頻 的 數 字 化 方 式 用44.1kHz 的 采 樣 頻 率、16 級 量 化 電 平 而 且 是 雙 通 道 記 錄 和 線 形 格 式。 現 已 成 為 音 樂 工 業 中 的 事 實 標 準。 主 要 有 以 下 內 容:
最 多99 首 歌 曲(track, 即 音 軌);
每 扇 區2352 字 節 均 用 來 存 放 聲 音 數 據;
聲 音 數 據 為 采 樣 率44.1K、16 比 特 量 化 的PCM 信 號;
立 體 聲;
無 目 錄 和 文 件 結 構, 連 續 存 放PCM 信 號;
播 放 時 按 每 秒75 扇 區 的 速 度;
每 張 光 盤 最 多74 分 鐘。
----音 頻 數 據 不 像 其 他 計 算 機 數 據( 如 程 序 文 件) 那 樣 對 錯 誤 具 有 極 大 的 敏 感 性( 一 般 對 誤 碼 具 敏 感 性 的 數 據 不 能 容 忍1 比 特 的 錯 誤), 因 此 每 扇 區 的2352 個 字 節 無 需 額 外 的 檢 錯 糾 錯 的 開 銷, 均 可 用 來 存 放 音 頻 數 據。 這 樣, 每 個 扇 區 能 存 放 的 音 樂 時 間 為2352/(16/8 ×2 ×44100)=1/75 秒, 因 此 播 放 速 度 為75 扇 區 / 秒。 扇 區 地 址 與 播 放 時 間 具 有 一 一 對 應 的 關 系; 在CD -DA 格 式 中, 用 時 間MSF 格 式 表 示, 標 記 為 00:00:00 格 式:
----M: 分 鐘 數, 以 一 個 字 節 表 示;
----S: 秒 數, 范 圍0 ~59, 以 一 個 字 節 表 示;
----F: 扇 區 數, 范 圍0 ~74, 以 一 個 字 節 表 示, 代 表 有 多 少 個1/75 秒。
----在ISO 9660 標 準 下, 單 張 的 CD -ROM 被 定 義 為 一 個" 卷", 前150 個 扇 區 用 于 保 存 各 個 音 軌 的 起 始 時 間 以 及 光 盤 本 身 的 卷 標、 版 權 等 信 息。 所 以, 從MSF 到 絕 對 扇 區 地 址 的 轉 換 關 系 為:
---- Address = M * 60 * 75 + S * 75 + F + 150 ;
----本 人 在 開 發 一 個 個 人CD 收 藏 數 據 庫 時 發 現, 各 個CD 出 版 公 司 都 有 自 己 的CD 編 號 規 范, 無 法 統 一, 如: DG 437 667 -2。 因 此, 有 必 要 采 用 一 種 算 法 唯 一 標 識 單 張CD。 基 于 以 上 分 析, 采 用 如 下 算 法, 事 實 證 明 是 可 行 的。
二、 算 法 說 明( 程 序 框 架)
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) {
/tret = ret + (n % 10);
/tn = n / 10;
}
return (ret);
}
unsigned long cddb_discid(int tot_trks)
{
int i, t = 0, n = 0;
i = 0;
while (i
三、 使 用
----假 設 你 的 編 譯 器 支 持32 位 整 數, cddb_discid 函 數 計 算discid, 基 于CD 的 內 容 表, 按 照MSF 格 式, 故 意 忽 略 了 扇 區 數, 函 數 接 收tot_trks 參 數(CD 的 音 軌 總 數), 返 回discid 這 個 整 數。 假 設cdtoc[] 是 一 個 結 構 數 組, 每 個 結 構 包 含 分 鐘 數、 秒 數 和 扇 區 數 三 個 域, 它 們 實 際 上 是 每 個 音 軌 的 分 鐘 數、 秒 數 和 扇 區 數 的 偏 移 量。 這 些 信 息 從CD 的 內 容 表 中 讀 出, 數 組 中 實 際 上 有tot_trks + 1 個 元 素, 最 后 一 個 是 個 虛 擬 音 軌, 即 最 外 一 個 音 軌 末 端 的 偏 移 量, 或 稱 為 頂 頭 音 軌( 也 稱 音 軌0xAA), 函 數 循 環 檢 測 內 容 表 中 的 每 個 音 軌, 計 算 每 個 音 軌 的(M * 60) + S( 按 秒 計 算 偏 移 量), 并 把 結 果 給cddb_sum() 函 數, 該 函 數 把 數 據 中 的 每 個 數 字 累 加, 每 個 音 軌 的 結 果 保 存 在 變 量n 中。
----循 環 結 束 時
用 頂 頭 音 軌 的 偏 移 量(M *60 +S) 減 去 第 一 個 音 軌 的 偏 移 量 (M *60 +S), 按 秒 計 算disk 的 長 度。
用n 對0xff 取 余, 將 結 果 左 移24 位。
把t 左 移8 位。
----把2、3 所 得 結 果 連 同tot_trks 進 行 或 運 算, 結 果 便 是diskid。
----為 了 建 庫 方 便,diskid 用16 進 制 代 表, 如 果 少 于8 位 字 符 串, 前 面 補0,( 如3a8f07 變 為003a8f07), 為 方 便 起 見, 其 中 的 字 母 用 小 寫。
----使 用MS -Windows MCI 接 口 的 用 戶 應 注 意:
----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 不 正 確。 這 樣, 當 你 計 算 頂 頭 位 置 的 時 候, 在 最 后 一 個 音 軌 的 長 度 上 加 上 一 楨。
----對 于Windows 客 戶 來 說, 按 照MSF 格 式 計 算 頂 頭 的 最 簡 便 的 方 法 是:
(offset_minutes * 60 * 75) +(offset_seconds * 75) +offset_frames + (length_minutes * 60 * 75) +(length_seconds * 75) + length_frames +1=X
X 是 按 楨 計 算 的 頂 頭 偏 移 量, 若 按 秒 計 算, 只 需 簡 單 地 用75 除, 消 掉 余 數 即 可。