系统采用串行口与外界交互,任何具有标准串口的设备均可与本系统相连。欲发音汉字的国标码(GB码)由串口送入MCU,MCU将其映射为Flash存储器地址表中对应项的地址,然后根据此地址取得对应项中的命令字,由MCU根据该命令字读取该汉字发音对应的语音数据,连续读出语音数据并以游程码解码算法解码后,按照语音采样时的固定速率通过D/A转换和功率放大播放。本文中语音采样速率为11025B/s。为满足应用需求,本文首先构建易于快速解码的语音库,根据特定Flash存储器的存储格式,以快速多查找表寻址及命令字预先存储的方式组织并存储在Flash存储器中,以满足语音播放的实时要求。同样,MCU的代码也要优先考虑速度而牺牲诸如模块化、可读性方面的要求。,出于实用性考虑,系统中需加入足够的输入缓冲区支持,以满足输入多个流字或整句的要求。
2 原始语音数据的采集和处理
本系统共采集了1335种发音,内含1306个流字发音,26个英文字母发音及3个停顿音,语音采集卡AD转换整编11025B/s,分辨率8位,样本值域0~255,静默值为80H。原始语音以WAV文件的格式保存在PC机中。
本文根据上述静默值及边缘值的分布特点,提出了一种改进的游程编码用于语音数据的压缩,具体做法是:用00H代表游程压缩起始码,其后是被编码字符,再下一个字节是被编码字符的重复码,如:80 80 80 80 80可以表示为00 80 05。显然,游程长度小于等于3时没有编码的必要,因而不会出现值为00H、01H和02H的重复码。如上所述,在原始语音文件中,00H、01H这些边缘值是基本上不出现的。因为大量出现这些边缘值即意味着语音采集系统的动态范围设置错误。尽管如此,为确保原始语音文件中没有“多余”边缘值,需要将语音文件略做处理,将可能存在的00H和01H都改为02H,显然这样的处理并不会影响语音的实际播放效果。处理后的00H、01H即可作为特殊控制字符使用。编码前,1335种原始语音样本的大小为14978622字节,压缩后为7767112字节,压缩比超过50%。该语音库已经可以装入容量为8M字节的Flash存储器中。
3 语音库的存储结构
本文以8Mbit×8位NAND型Flash存储器K9F6408U0B为例,描述本系统语音库的存储结构。
语音库的基本内容分为两部分:前端是地址查找表,其后是压缩后的语音数据。地址表中,每4个字节代表一个地址项。GB2312汉字编码字符集中每个汉字在地址表中都有一个对应项,其内容指向该汉字对应读音的语音数据起始地址。GB码字符集中共有94个区,每区94个字符,总计8836个汉字、英文字母和其它符号,其中实际使用了7445个,余下的作为预留区。本系统亦保留了这些预留区,以利于将来的扩充。这样,地址表的大小为94×94×4=35344字节。语音数据区共存储1335年发音,采用流程编码压缩存放,并在每段语音数据结尾添加01H作为结束控制符。
对不同的Flash存储器,语音库需做一些针对性的处理。对于K9F6408U0B而言,要对其C区进行专门的处理。该芯片中,每个页面(Page)都有A、B、C三个区,其中A、B区各256字节,而C区仅有16字节。本设计中没有用到C区,因而在制作写入Flash的二进制政府间库文件时必须注意对C区进行空白码(FFH)填充。考虑C区填充后,地址表对应的二进制语音库文件大小的计算方法改为:512×69+16=35344,表示当35344字节只占据A区和B区时共需69个页面,多出16字节。这意味着有69个C区需要填充,即写入Flash的地址表的实际大小应该是35344+69×16=36448。相应地,语音数据区需要进行同样的处理。
4 码字转换及高效MCU代码的实现
本文中的码字转换有两类。一类GB码到语音库起始字节数的转换,用于MCU收到串口输入的GB码后,确定相应读音在地线表中对应项的起始地址。该类码字转换主要依据GB2312标准及语音库地址表的结构进行。本文中,该码制转换的算法为:((GB码高字节-161)×94+(GB)码低字节-161))×4。另一类是将上述地址转换为Flash读取数据的命令字。这类转换与语音库存储结构及所用Flash存储器的读写操作及时序相关。由于在语音库生成时已由PC机将语音数据的起始地址转换为操作命令字并存储到了地址表对应项中,即大部分的计算及时序控制操作在使用PC制作Flash的二进制映像文件时已经完成,因而避免了系统运行中的大量计算,从而保证了语音播放的实时性。计算命令字的方法与具体的Flash存储器型号相关且较为繁琐。限于篇幅,本文不再给出具体的算法。有兴趣的读者可以参阅K9F6408U0B的数据表。
本文中的MCU型号为AT89S52,使用22.1484MHz的晶振。根据AT89S52数据表,每播放一个汉字,所需指令周期数为(1/11025)/(12/22.1184)=167.2。因此设置一个计时器中断,中断值为256-167=89,在每两个中断之间完成如下工作:
(1) 从缓冲区中取得GB码并将之转换为地址表对应项地址;
(2) 从地址表对应项中取得对应语音数据区存储地址;
(3) 取得对应语音数据区数据;
(4) 完成游程解码并播放。
此外,由于完成有可能在语音播放过程收以输入字符,因而串口亦应工作于中断方式,串口波特率为9600bps,其优先级高于定时器中断。本系统中,此缓冲区能满足使用都 量多输入60个汉字。以上操作均在约168个指令周期中完成,大约相当84条双周期指令。因而在代码编写中,必须把代码效率放在位,灵活地运用编程技巧来完成。
本文给出了一种嵌入式TTS汉语语音系统的实现方案。由于采用了易于解码的改进游程算法、多重查找表及Flash存储器操作命令这了的预先存储技术,使得该方案可以在罗低要求的硬件平台上实现,以AT89S52 MCU为的嵌入式TTS系统不同于基于PC的TTS语音系统,该系统体积小、功耗低、成本低廉、适用范围很广。经测试其语音清晰、连贯,可发音字节涵盖GB码所有汉字、26个英文字节,可输入多达60个汉字的整句,足以满足大部分应用场合的需要。如以MCU或ARM处理器为平台,还可以增加更多的算法,以进一步改进系统性能。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。