当前位置:文档之家› 研 究 生 课 程 论 文

研 究 生 课 程 论 文

研究生课程论文(2013-2014学年第二学期)基于科大讯飞的语音识别设计与实现提交日期:2014年9月13日研究生签名:学号学院课程编号S0812018 课程名称嵌入式技术学位类别硕士任课教师教师评语:成绩评定:分任课教师签名:年月日基于科大讯飞的语音识别系统摘要:本系统的主要目的是在pcduino上开发基于科大讯飞的语音识别系统,完成输入音频的识别,并转换成相应的文本输出。

关键词:语音识别,科大讯飞一、系统简介本系统的主要目的是在pcduino上开发基于科大讯飞的语音识别系统,完成输入音频的识别,并转换成相应的文本输出。

二、开发板及开发环境开发板为pcDuino交叉编译器为arm-none-linux-gnueabi-gccUbuntu版本11.10三、主要开发流程1、完成U-boot移植2、完成内核移植3、完成文件系统移植4、基于讯飞的开发库完成语音识别的上层应用四、讯飞移动语音平台简介讯飞移动语音平台简介是基于讯飞公司已有的ISP和IMS产品,开发出的一款符合移动互联网用户使用的语音应用开发平台,提供语音合成、语音听写、语音识别、声纹识别等服务,为语音应用开发爱好者提供方便易用的开发接口,使得用户能够基于该开发接口进行多种语音应用的开发。

下图为讯飞移动语音平台的典型网络拓扑结构:从图中可以看到,完整的讯飞移动语音平台架构在Internet上,分为服务器端、移动客户端和Internet客户端三个部分。

服务器端为讯飞移动语音平台的核心部分,提供HTTP应用、用户管理、语音服务等服务,位于局域网内,对外统一接入Internet,为用户提供唯一的访问点。

其中:HTTP服务器负责将客户端发送的服务请求发送至业务服务器,然后由业务服务器按照具体的服务类型进行处理,调用ISP语音应用平台获取具体的语音服务,而后把处理结果返回给HTTP服务器,再回复客户端。

互联网用户直接通过讯飞移动语音平台服务器提供的Internet访问点使用语音服务,在集成了讯飞移动语音平台提供的开发接口后即可在网络畅通的情况下载应用程序中调用语音服务。

移动用户使用智能手机通过移动运营商提供的2G(GPRS/EDGE/CDMA)或3G网络接入Internet,然后连接到讯飞移动语音平台服务器获得服务。

五、主要开发思路整个系统开发的过程首先是移植u-boot。

U-boot是引导系统的一段程序,相当于windows 系统下的BIOS。

在开发板上正常移植u-boot后就可以为以后的内核移植做准备了。

下一步是移植内核,内核就是linux的内核。

在u-boot的正确引导之下就可以正常运行内核,也就是整个系统就可以正常运行。

但是此时还有一个问题,就是我们还没有移植文件系统,所以我们的内核就会卡在那里进不去。

然后我们就在移植文件系统,当完成这一步的时候我们就可以对整个系统进行正常操作了。

在搭建起Linux系统平台后,就可以进行语音识别功能的开发了,在这个功能的开发中,我们主要是使用讯飞提供的API将采集到的语音上传到云端,然后将云端的语音识别结果返回到客户端,从而实现语音识别功能。

六、内核移植分析在U-boot移植成功并成功开始引导功能的时候,就开始引导内核的启动了,所以说U-boot移植的下一步就是内核的移植和分析了。

下面对start_kernel()函数及其相关函数进行分析。

1、 lock_kernel()/* Getting the big kernel lock.* This cannot happen asynchronously, * so we only need to worry about other * CPU's. */ extern __inline__ void lock_kernel(void) {if (!++current->lock_depth) spin_lock(&kernel_flag); }kernel_flag是一个内核大自旋锁,所有进程都通过这个大锁来实现向内核态的迁移。

只有获得这个大自旋锁的处理器可以进入内核,如中断处理程序等。

在任何一对lock_kernel /unlock_kernel函数里至多可以有一个程序占用CPU。

进程的lock_depth成员初始化为-1,在kerenl/fork.c文件中设置。

在它小于0时(恒为 -1),进程不拥有内核锁;当大于或等于0时,进程得到内核锁。

2、setup_arch()setup_arch()函数做体系相关的初始化工作,函数的定义在arch/armnommu/kernel/setup.c 文件中,主要涉及下列主要函数及代码。

(1)setup_processor() 该函数主要通过for (list = &__proc_info_begin; list < &__proc_info_end list++)if ((processor_id & list->cpu_mask) == list->cpu_val) break;这样一个循环来在段中寻找匹配的processor_id,processor_id在head_armv.S文件中设置。

(2)setup_architecture(machine_arch_type)该函数获得体系结构的信息,返回mach-xxx/arch.c 文件中定义的machine结构体的指针,包含以下内容:MACHINE_START (xxx, “xxx”)MAINTAINER ("xxx")BOOT_MEM (xxx, xxx, xxx)FIXUP (xxx)MAPIO (xxx)INITIRQ (xxx)MACHINE_END(3)内存设置代码if (meminfo.nr_banks == 0) {meminfo.nr_banks = 1;meminfo.bank[0].start = PHYS_OFFSET;meminfo.bank[0].size = MEM_SIZE; }meminfo结构表明内存情况,是对物理内存结构meminfo的默认初始化。

nr_banks指定内存块的数量,bank指定每块内存的范围,PHYS _OFFSET指定某块内存块的开始地址,MEM_SIZE指定某块内存块长度。

PHYS _OFFSET和MEM_SIZE都定义在include/asm-armnommu/arch-XXX/memory.h文件中,其中PHYS _OFFSET是内存的开始地址,MEM_SIZE就是内存的结束地址。

这个结构在接下来内存的初始化代码中起重要作用。

(4)内核内存空间管理init_mm.start_code = (unsigned long) &_text; 内核代码段开始 init_mm.end_code = (unsigned long) &_etext; 内核代码段结束 init_mm.end_data = (unsigned long) &_edata; 内核数据段开始 init_mm.brk = (unsigned long) &_end; 内核数据段结束每一个任务都有一个mm_struct结构管理其内存空间,init_mm 是内核的mm_struct。

其中设置成员变量* mmap指向自己,意味着内核只有一个内存管理结构,设置 pgd=swapper_pg_dir,swapper_pg_dir是内核的页目录,ARM体系结构的内核页目录大小定义为16k。

init_mm定义了整个内核的内存空间,内核线程属于内核代码,同样使用内核空间,其访问内存空间的权限与内核一样。

(5)内核内存空间管理init_mm.start_code = (unsigned long) &_text; 内核代码段开始 init_mm.end_code = (unsigned long) &_etext; 内核代码段结束 init_mm.end_data = (unsigned long) &_edata; 内核数据段开始 init_mm.brk = (unsigned long) &_end; 内核数据段结束每一个任务都有一个mm_struct结构管理其内存空间,init_mm 是内核的mm_struct。

其中设置成员变量* mmap指向自己,意味着内核只有一个内存管理结构,设置 pgd=swapper_pg_dir,swapper_pg_dir是内核的页目录,ARM体系结构的内核页目录大小定义为16k。

init_mm定义了整个内核的内存空间,内核线程属于内核代码,同样使用内核空间,其访问内存空间的权限与内核一样。

七、具体的步骤与实现:在上文的移植中,我们总共修改了这样几个文件。

Makefile 添加对arm的支持arch/arm/mach-s3c2440/mach-smdk2440.c 修改平台时钟arch/arm/tools/mach-types 修改机器码arch/arm/plat-s3c24xx/commond-smdk.c 移植nandflash驱动当然我们还忘了一个最重要的,.config也就是这一步cp arch/arm/configs/s3c2410_defconfig .config 复制一下对于S3C2410/2440的通用配置我们在配置内核的时候,要执行make menuconfig这个命令调用的文件便是.config。

它打开了我们移植内核的配置单。

长久以来,我们都在迷惑一些问题那就是为什么我们要修改以上几个文件中的内容,为什么修改别的不行。

这些问题在.config 文件中找到了答案。

正如我以上所说,我们在移植内核的时候先要进行配置,选择配置单,也就是make menuconfig的操作。

我们先进到内核源码中看看。

arch/arm/plat-s3c24xx/commond-smdk.c 移植nandflash驱动先说这一项,进入到arch/arm/plat-s3c2440/目录打开该目录下面的Makefile在最后一行查看到有这样一行代码obj-$(CONFIG_MACH_SMDK)+= common-smdk.o这句话的意思是:如果CONFIG_MACH_SMDK=y的话,就编译common-smdk.c接着我们来看.config中是如何做的打开.config 文件(gedit .config)在192行我们找到了如下代码CONFIG_MACH_SMDK=y这样我们就明白了为什么修改nandflash驱动的时候修改arch/arm/plat-s3c24xx/commond-smdk.c就可以了。

相关主题