2.3 关键方法与技术
(1)程序初始化
鉴于数据结构相对简单,本文使用文本文件存放学生名单,每行一条,以硬回车分隔。对于重名、重音或读音相近的姓名,可加前缀或后缀以示区别,对于GBK字符集中的汉字使用同音字代替,如图2所示。
程序初始化时,将学生名单读入变量并分割单个姓名存入数组。算法描述如下:
输入:学生名单存放路径。
输出:学生总名单数组,学生总人数。
Step1:判断输入的名单存放路径是否存在。
Step2:如名单路径存在,将文件内容读至内存变量,并以换行符为分割符将此变量分割至学生总名单数组,取数组成员数从而得到学生总人数;如不存在,提示用户建立此文件再继续。
(2)由学生花名册随机选取指定数目的非重复记录
用户可设置每次随机选取几个学生姓名用以点名,程序据此由学生总名单数组选取指定数目的记录,算法描述如下:
输入:学生总名单数组,学生总人数。
输出:将指定数目的非重复姓名存放于点名名单数组。
Step1:取大于等于1、小于等于学生总人数的随机数,据此取回学生总名单数组中相应成员,加入点名名单数组。
Step2:重复Step1,判断取回的姓名是否与点名名单数组中已有成员重复。如重复,重新执行Step1;否则将取到的姓名加入点名名单数组。
Step3:重复Step1和Step2,直至取出名单人数等于用户设置的需要点名的人数。
(3)朗读指定文本
本文调用微软TTS语音引擎 [4]朗读文本,算法描述如下:
<script type="text/javascript">
var VoiceObj = new ActiveXObject("Sapi. SpVoice");
function Speak() {
var text = '生物系汪武';
VoiceObj.volume=100; // 音量1-100
VoiceObj.rate=0; // 速率-10-10
VoiceObj.Speak(text);
}
Speak();
</script>
(4)自动记录考勤
枚举点名名单数组中各成员,逐一显示并朗读,实现点名。在设置时限内,如教师上课用台式电脑外接麦克风探测到音频输入(即学生答“到”声音),自动记录出勤;反之自动记录缺勤。算法描述如下:
输入:点名名单数组。
输出:点名并记录考勤。
Step1:从输入的点名名单数组取出一条记录,朗读之。记下此时时刻。
Step2:进入循环,检测现在时刻减去Step1中所记录时刻的差值有否超过用户设置的时限。如果超过了但教师上课用台式电脑外接麦克风没有探测到音频输入,表明被点到名的学生缺勤,自动记录之;反之自动记录出勤。
Step3:重复Step1和Step2,直至点名名单数组中所有成员被朗读、记录出勤情况。
此步骤中,程序对麦克风信噪比(SIGNAL-NOISE RATIO,简称SNR)要求稍高。实践中发现80dB SPL可达到理想效果。
捕获麦克风音量大小算法描述如下。
public static double getVolume(byte[] buffer)
{
try
{
double sV = 0.0;
double aV = 0.0;
double volume = 0.0;
int length = buffer.Length;
for (int i = 0; i < length; i += 2)
{
int v1 = buffer[i] & 0xFF;
int v2 = buffer[i + 1] & 0xFF;
int temp = v1 + (v2 << 8);
if (temp >= 0x8000)
{
temp = 0xffff - temp;
}
sV += Math.Abs(temp);
}
aV = sV / length / 2;
volume = Math.Log((1 + aV), 10) * 10;
return volume;
}
catch (Exception ex)
{
return 0;
}
}