把喜欢的图烧进CD里——光驱绘图研究

观前提示

本文包含大量公式推导, 请慎重阅读. 部分内容借助AI查找, 注意辨别真伪.

前置知识

光盘存储的基本原理

首先介绍一下光盘的结构, 光盘表面有一条很长的阿基米德螺旋线轨道(从数据面看是顺时针展开的),轨道上有两种区域: 凹坑(pit), 以及没有凹坑的平坦区域(land). 很显然, 激光照射在pit和land上接收到的反射光强是不同的, 这就是光盘存储最基础的物理原理.

在这个基础上, 0和1, 是如何表示的呢? 实际上光盘是通过反射强弱变化来表示0和1的, 也就是(pit->land)/(land->pit)表示1, (pit->pit)/(land->land)表示0.

光驱绘图的原理

既然pit和land反射率存在差异, 那它们就可以被当成黑白点来使用, 就像激光打印机, 在特定位置撒下碳粉(pit), 就可以产生可见的画面.

以前的LightScribe和LabelFlash技术也是这个原理, 但是需要专用刻录机和光盘.

如果手里只有普通光驱和盘片应该怎么办呢, 我们可以假设同一台光驱在同型号光盘上刻录相同数据产生的物理布局是一致的, 于是就可以构造特定数据来让数据面被刻录上特定画面了.

接下来的大部分内容都是为了解决如何把特定数据映射到正确的物理位置上.

CD盘片上数据的逻辑与物理布局

CD盘片从内到外分成很多区域, 其中最重要有三个区域(均为半径):

  • Lead-in(23–25mm): 导入区, 存储最终TOC/目录信息
  • Program(25–58mm): 用户数据区域, 这部分才是构造数据烧录的位置, 也就是我们的绘图区域
  • Lead-out: 跟在数据区之后, 最外到59mm

对CD而言, 可寻址的基本单位是sector/block, 每个sector有2352B. 音乐CD中这2352字节全是音频数据, 而数据CD中则包含了校验纠错等其它内容, 实际可用通常为2048或2336B(所以绘图构造音乐CD数据比较简单).

寻址常用MSF或者LBA, MSF(MM:SS:FF, 也就是分钟:秒:帧)是根据时间寻址的(因为CD最初是存音乐的), 其中1秒=75 sectors/frames. LBA则是从0开始的sector编号.

落到物理盘面上, sector流按24B为单位连续切分成F1 frame流, 然后连续的F1 frame流内进行CIRC编码(包含交织和纠错等操作)得到32B的F2 frame, 再加上subcode得到33B的F3 frame, 最后结果EFM编码并加上merging bits之后得到588个channel bits(也就是实际写入的0和1).

物理位置的计算

一些约定

根据前置知识可知, 一个sector经过一系列处理后在盘面上并不是连续线段, 但是我们暂时先不考虑这个问题, 因为后续处理是参照规范实现的固定流程(否则不同厂商的产品就互不兼容了).

为了方便起见, 后续计算以LBA寻址的”虚拟sector”(也就是假设没有交织等操作, F1 frame在原位编码成F2 frame)为对象展开计算.

物理建模

由于开源仓库CDImage - A tool for burning visible pictures on a compact disc surface所用物理模型标定存在一些困难, 因此我重新建模了一个更容易标定的模型.

因为轨道是阿基米德螺旋线(不考虑轨道摆动), 因此如果已知轨距和起点半径, 就有, 其中

很简洁的公式, 但是测量困难, 如果我们已知总角度和终点半径, 我们可以用把对的需求消解掉.

然而一样测量困难, 于是我们考虑引入一些标准里的已知量, 这个时候MSF跳出来了, 于是终点的时间可以确定, 又因为光盘是恒定线速度(音乐CD), 于是总弧长变成了已知量.

反求之后就好说了.

近似求解

考虑到半径(25mm+)远大于轨距(微米级), 所以有. 于是:

代换之后就可以得到轨距的近似:

对于特定型号的光盘, 总sector数是已知的, 因此很容易求得第个sector的极坐标:

此处仍然满足近似的前提条件, 因此弧长, 又因为线速度恒定, 有, 于是:

平面坐标也很容易得到:

公式整理

已知:

  • : 线速度
  • : 总sector数
  • : 当前sector编号
  • : 轨道总长(可用推导得到, 为了简洁, 此处当已知量)

标定:

  • : 轨道起点处半径
  • : 轨道终点处半径

可以用以下公式得到第个sector的坐标: