电子说
步骤1:了解格式
磁性编码条带数据遵循通用标准。磁条由3条物理上分开的“磁道”组成。磁道1最靠近卡的底部,磁道3最高。 Square的读取器位于读取轨道2的位置。轨道2是最常用的轨道,但是大多数信用卡也使用轨道1。轨道2包括卡号和有效期。音轨1包括那个加号。根据特定的卡,可能还会有其他数据。这些磁道的宽度规定为0.11英寸,因此要使用Square的读取器读取磁道1,我们只需要重新布置条纹,使磁道1与读取头对齐即可。
每个磁道中的数据均通过磁编码域翻转。长话短说:一系列的域翻转对波形进行编码,该波形被解释为二进制。此编码中的二进制0是任意频率。 1是该频率的两倍。
数据以一组前导零开始,以建立基本频率。在可变数目的零之后,出现开始标记。对于音轨2,开始标记为“;”。每个字符被编码为整数,最低有效位在前。对于磁道2,每个字符包含4个数据位和1个奇偶校验位。为每个字符设置奇偶校验位,以使1的数量为奇数。如果为每个字符的整数值加上48(ASCII编码为“ 0”),则将显示ASCII字符。除了数字“ 0”到“ 9”之外,磁道2还可以编码一些其他字符,包括“;”。 (开始标记),“ =“(字段分隔符)和“?” (末尾)。
步骤2:制作垫片以读取音轨1
磁卡的磁道1比磁道2更靠近卡的边缘.11英寸。由于Square读卡器被设置为读取磁道2,因此如果我们在磁道中粘贴一些东西,读取器将卡提升.11英寸时,读取头将与轨道1对齐,而不是与轨道2对齐。
您可以通过从另一张卡上剪切0.11英寸的条来创建垫片。我还发现廉价垃圾袋的缠结也差不多。
第3步:录制一些音频
就电话而言,Square阅读器只是一个麦克风。因此,要从卡中获取数据,我们需要记录音频。请参阅其他Android文档(例如本教程:http://eurodev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html)以获取详细说明,或使用RhombusLib(请参阅最后的链接) )。以下是一些Java代码,可以开始在Android应用中记录音频:
AudioRecord audioRecord =新的AudioRecord(MediaRecorder.AudioSource.MIC,
频率,channelConfiguration,
audioEncoding,bufferSize);
audioRecord.startRecording();
录音时,我们需要不断从录音机中读取数据并将其放入缓冲区中。
//创建一个DataOutputStream以写入音频数据
ByteArrayOutputStream os = new ByteArrayOutputStream ();
BufferedOutputStream bos =新的BufferedOutputStream(os);
DataOutputStream dos =新的DataOutputStream(bos);
short bufferVal;
short [] buffer = new short [bufferSize];
while(recording){
bufferReadResult = audioRecord.read(buffer,0,bufferSize);
for(int i = 0; i bufferVal = buffer [i];
dos.writeShort(buffer [i]);
}
}
dos.close();
byte [] audioBytes = os.toByteArray();
上面的代码是从RhombusLib中提取并简化的。录制后,您将拥有一个字节数组,代表麦克风中的样本,可以进行分析。
步骤4:解码音频
因此,现在我们的设备上有很多音频。我们如何解码它?我的代码基于Android教程,该教程显示了如何记录数据然后进行回放。就我而言,我确保将音频保存为16位PCM编码。我以44100hz采样。在Android(以及其他地方,我想)上,16位PCM数据意味着每个样本都是一个带符号的16位值。因为我们只关心频率,所以我们只需要关心“零交叉”之间有多少时间。过零是指信号从正向变为负,反之亦然。 0位将由2个交叉点之间的间隔表示,而1将在大约相同的时间段内有一个额外的交叉点。
每个磁道中的卡数据以一些(可变)数0开始,以建立基本频率。我所做的是听取高于某个“安静”阈值的第一个样本,然后计算零交叉之间的样本数。该数字将成为0的基值。由于这些卡是手工刷卡的,因此从扫描开始到结束,实际频率将有所变化。因此,我做了一个简单的方法,确定自上次零交叉以来的样本数量是否更接近基本频率或两倍于基本频率(基本样本数量的一半)。然后,它会相应地调整预期的基本频率。只要两个逻辑位之间的变化很小,此方法就可以很好地工作。而且它们几乎肯定会。
要检测零交叉,我们需要查看每个样本的符号并将其与前一个样本的符号进行比较。如果它们不同(一个正,一个负),则信号在这些样本之间越过0。
基本算法是遍历字节数组,提取样本。计算零交叉之间的样本数,并将其与0或1的预期计数进行比较。好的,经过一番挥舞之后,我们现在有了一个二进制数据序列,我们想回过头来。转换成ASCII。最常见的编码(也是我编写的唯一处理程序)将每个字符编码为一定数量的位,再加上一个奇偶校验位。对于音轨2,字符为4位,奇偶校验为1,组成5位组。从最低有效位到最高读取位,最后一位是奇偶校验位。将奇偶校验位设置为使组中的1的个数为奇数。在我的实现中,我只是忽略了奇偶校验位,但这将有助于确定读取是否正确。在磁道1中,字符的6位加上奇偶校验。
磁道的字符集也有所不同,但是两者都是ASCII子集,具有一些偏移量。对于仅编码一些符号和数字的磁道2,字符集从48开始,这是“ 0”的ASCII码。因此,如果我们得到0,0,0,0,1作为我们的角色,则将其变成0,加48,得到48。类似地,1,0,0,0,0为1。1 + 48 = 49 = ASCII“ 1”。
对于轨道1,字符集以“”(空格)开头,即ASCII32。因此,我们在解码的数字值上加上32,得到ASCII字符。之后,我们有了数据,因此剩下的一切都只是在挂接UI胶水。
责任编辑:wv
全部0条评论
快来发表一下你的评论吧 !