重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
可以。
创新互联是少有的成都网站设计、成都网站建设、外贸网站建设、营销型企业网站、微信小程序、手机APP,开发、制作、设计、买链接、推广优化一站式服务网络公司,自2013年起,坚持透明化,价格低,无套路经营理念。让网页惊喜每一位访客多年来深受用户好评
需求:
1.实现可以从麦克风进行录音
2.可以停止录音
3.实现播放录音内容
4.并将所录的mp3文件全部存到F:/语音文件夹,语音的文件名以当前时间命名(java中是换算成秒),其中文件夹程序自己创建,不用担心出错
程序如下:
span style="font-size:18px;"import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class MyRecord extends JFrame implements ActionListener{
//定义录音格式
AudioFormat af = null;
//定义目标数据行,可以从中读取音频数据,该 TargetDataLine 接口提供从目标数据行的缓冲区读取所捕获数据的方法。
TargetDataLine td = null;
//定义源数据行,源数据行是可以写入数据的数据行。它充当其混频器的源。应用程序将音频字节写入源数据行,这样可处理字节缓冲并将它们传递给混频器。
SourceDataLine sd = null;
//定义字节数组输入输出流
ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = null;
//定义音频输入流
AudioInputStream ais = null;
//定义停止录音的标志,来控制录音线程的运行
Boolean stopflag = false;
//定义所需要的组件
JPanel jp1,jp2,jp3;
JLabel jl1=null;
JButton captureBtn,stopBtn,playBtn,saveBtn;
public static void main(String[] args) {
//创造一个实例
MyRecord mr = new MyRecord();
}
//构造函数
public MyRecord()
{
//组件初始化
jp1 = new JPanel();
jp2 = new JPanel();
jp3 = new JPanel();
//定义字体
Font myFont = new Font("华文新魏",Font.BOLD,30);
jl1 = new JLabel("录音机功能的实现");
jl1.setFont(myFont);
jp1.add(jl1);
captureBtn = new JButton("开始录音");
//对开始录音按钮进行注册监听
captureBtn.addActionListener(this);
captureBtn.setActionCommand("captureBtn");
//对停止录音进行注册监听
stopBtn = new JButton("停止录音");
stopBtn.addActionListener(this);
stopBtn.setActionCommand("stopBtn");
//对播放录音进行注册监听
playBtn = new JButton("播放录音");
playBtn.addActionListener(this);
playBtn.setActionCommand("playBtn");
//对保存录音进行注册监听
saveBtn = new JButton("保存录音");
saveBtn.addActionListener(this);
saveBtn.setActionCommand("saveBtn");
this.add(jp1,BorderLayout.NORTH);
this.add(jp2,BorderLayout.CENTER);
this.add(jp3,BorderLayout.SOUTH);
jp3.setLayout(null);
jp3.setLayout(new GridLayout(1, 4,10,10));
jp3.add(captureBtn);
jp3.add(stopBtn);
jp3.add(playBtn);
jp3.add(saveBtn);
//设置按钮的属性
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(false);
saveBtn.setEnabled(false);
//设置窗口的属性
this.setSize(400,300);
this.setTitle("录音机");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("captureBtn"))
{
//点击开始录音按钮后的动作
//停止按钮可以启动
captureBtn.setEnabled(false);
stopBtn.setEnabled(true);
playBtn.setEnabled(false);
saveBtn.setEnabled(false);
//调用录音的方法
capture();
}else if (e.getActionCommand().equals("stopBtn")) {
//点击停止录音按钮的动作
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
saveBtn.setEnabled(true);
//调用停止录音的方法
stop();
}else if(e.getActionCommand().equals("playBtn"))
{
//调用播放录音的方法
play();
}else if(e.getActionCommand().equals("saveBtn"))
{
//调用保存录音的方法
save();
}
}
//开始录音
public void capture()
{
try {
//af为AudioFormat也就是音频格式
af = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class,af);
td = (TargetDataLine)(AudioSystem.getLine(info));
//打开具有指定格式的行,这样可使行获得所有所需的系统资源并变得可操作。
td.open(af);
//允许某一数据行执行数据 I/O
td.start();
//创建播放录音的线程
Record record = new Record();
Thread t1 = new Thread(record);
t1.start();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
return;
}
}
//停止录音
public void stop()
{
stopflag = true;
}
//播放录音
public void play()
{
//将baos中的数据转换为字节数据
byte audioData[] = baos.toByteArray();
//转换为输入流
bais = new ByteArrayInputStream(audioData);
af = getAudioFormat();
ais = new AudioInputStream(bais, af, audioData.length/af.getFrameSize());
try {
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, af);
sd = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sd.open(af);
sd.start();
//创建播放进程
Play py = new Play();
Thread t2 = new Thread(py);
t2.start();
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
//关闭流
if(ais != null)
{
ais.close();
}
if(bais != null)
{
bais.close();
}
if(baos != null)
{
baos.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//保存录音
public void save()
{
//取得录音输入流
af = getAudioFormat();
byte audioData[] = baos.toByteArray();
bais = new ByteArrayInputStream(audioData);
ais = new AudioInputStream(bais,af, audioData.length / af.getFrameSize());
//定义最终保存的文件名
File file = null;
//写入文件
try {
//以当前的时间命名录音的名字
//将录音的文件存放到F盘下语音文件夹下
File filePath = new File("F:/语音文件");
if(!filePath.exists())
{//如果文件不存在,则创建该目录
filePath.mkdir();
}
file = new File(filePath.getPath()+"/"+System.currentTimeMillis()+".mp3");
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭流
try {
if(bais != null)
{
bais.close();
}
if(ais != null)
{
ais.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//设置AudioFormat的参数
public AudioFormat getAudioFormat()
{
//下面注释部分是另外一种音频格式,两者都可以
AudioFormat.Encoding encoding = AudioFormat.Encoding.
PCM_SIGNED ;
float rate = 8000f;
int sampleSize = 16;
String signedString = "signed";
boolean bigEndian = true;
int channels = 1;
return new AudioFormat(encoding, rate, sampleSize, channels,
(sampleSize / 8) * channels, rate, bigEndian);
// //采样率是每秒播放和录制的样本数
// float sampleRate = 16000.0F;
// // 采样率8000,11025,16000,22050,44100
// //sampleSizeInBits表示每个具有此格式的声音样本中的位数
// int sampleSizeInBits = 16;
// // 8,16
// int channels = 1;
// // 单声道为1,立体声为2
// boolean signed = true;
// // true,false
// boolean bigEndian = true;
// // true,false
// return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,bigEndian);
}
//录音类,因为要用到MyRecord类中的变量,所以将其做成内部类
class Record implements Runnable
{
//定义存放录音的字节数组,作为缓冲区
byte bts[] = new byte[10000];
//将字节数组包装到流里,最终存入到baos中
//重写run函数
public void run() {
baos = new ByteArrayOutputStream();
try {
System.out.println("ok3");
stopflag = false;
while(stopflag != true)
{
//当停止录音没按下时,该线程一直执行
//从数据行的输入缓冲区读取音频数据。
//要读取bts.length长度的字节,cnt 是实际读取的字节数
int cnt = td.read(bts, 0, bts.length);
if(cnt 0)
{
baos.write(bts, 0, cnt);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
//关闭打开的字节数组流
if(baos != null)
{
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
td.drain();
td.close();
}
}
}
}
//播放类,同样也做成内部类
class Play implements Runnable
{
//播放baos中的数据即可
public void run() {
byte bts[] = new byte[10000];
try {
int cnt;
//读取数据到缓存数据
while ((cnt = ais.read(bts, 0, bts.length)) != -1)
{
if (cnt 0)
{
//写入缓存数据
//将音频数据写入到混频器
sd.write(bts, 0, cnt);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
sd.drain();
sd.close();
}
}
}
}/span
为应用程序加上语音能力有什么好处呢?粗略地讲,是为了趣味,它适合所有注重趣味的应用,比如游戏。当然,从更严肃的角度来讲,它还涉及到应用的可用性问题。注意,这里我考虑的不仅是可视化界面固有的不足,而且还有这样一些情形:一些时候,让双眼离开当前的工作很不方便,甚至是不合法的。比如,假设有一个带语音功能的浏览器,你就可以在外出散步或开车上班的同时,用听的方式浏览自己喜爱的网站。从目前来看,邮件阅读器或许是语音技术更实际的应用,在JavaMail API的帮助下,这一切已经可能。邮件阅读器可以定期地检查收件箱,然后用语音“You have new mail, would you like me to read it to you?”引起你的注意。按照类似的思路,我们还可以考虑一个带语音功能的提醒器,把它连接到一个日历应用:它会及时地提醒你“Don't forget your meeting with the boss in 10 minutes!”。 也许你已经被这些主意吸引,或者有了自己更好的主意,现在让我们继续。首先我将介绍如何启用本文提供的语音引擎,这样,如果你认为语音引擎的实现细节过于复杂,就可以直接使用它而忽略其实现细节。
一、试用语音引擎 要使用这个语音引擎,你必须在CLASSPATH中加入本文提供的javatalk.jar文件,然后从命令行运行(或者从Java程序调用)com.lotontech.speech.Talker类。如果从命令行运行,则命令为: java com.lotontech.speech.Talker "h|e|l|oo" 如果从Java程序调用,则代码为: com.lotontech.speech.Talker talker=new com.lotontech.speech.Talker(); talker.sayPhoneWord("h|e|l|oo"); 现在,对于在命令行上(或者调用sayPhoneWord()方法时)提供的“h|e|l|oo”字符串,你或许有所不解。下面我就来解释一下。 语音引擎的工作原理是把细小的声音样本连接起来,每一个样本都是人的语言发音(英语)的一个最小单位。这些声音样本称为音素(allophone)。每一个因素对应一个、二个或者三个字母。从前面“hello”的语音表示可以看出,一些字母组合的发音显而易见,还有一些却不是很明显: h -- 读音显而易见 e -- 读音显而易见 l -- 读音显而易见,但注意两个“l”被简缩成了一个“l”。 OO -- 应该读作“hello”中的读音,不应读作“bot”、“too”中的读音。 下面是一个有效音素的清单: a : 如cat b : 如cab c : 如cat d : 如dot e : 如bet f : 如frog g : 如frog h : 如hog i : 如pig j : 如jig k : 如keg l : 如leg m : 如met n : 如begin o : 如not p : 如pot r : 如rot s : 如sat t : 如sat u : 如put v : 如have w : 如wet y : 如yet z : 如zoo aa : 如fake ay : 如hay ee : 如bee ii : 如high oo : 如go bb : b的变化形式,重音不同 dd : d的变化形式,重音不同 ggg : g的变化形式,重音不同 hh : h的变化形式,重音不同 ll : l的变化形式,重音不同 nn : n的变化形式,重音不同 rr : r的变化形式,重音不同 tt : t的变化形式,重音不同 yy : y的变化形式,重音不同 ar : 如car aer : 如care ch : 如which ck : 如check ear : 如beer er : 如later err : 如later (长音) ng : 如feeding or : 如law ou : 如zoo ouu : 如zoo (长音) ow : 如cow oy : 如boy sh : 如shut th : 如thing dth : 如this uh : u 的变化形式 wh : 如where zh : 如Asian 人说话的时候,语音在整个句子之内起落变化。语调变化使得语音更自然、更富有感染力,使得问句和陈述句能够相互区别。请考虑下面两个句子: It is fake -- f|aa|k Is it fake? -- f|AA|k 也许你已经猜想到,提高语调的方法是使用大写字母。 以上就是使用该软件时你需要了解的东西。如果你对其后台实现细节感兴趣,请继续阅读。
二、实现语音引擎 语音引擎的实现只包括一个类,四个方法。它利用了J2SE 1.3包含的Java Sound API。在这里,我不准备全面地介绍这个API,但你可以通过实例学习它的用法。Java Sound API并不是一个特别复杂的API,代码中的注释将告诉你必须了解的知识。 下面是Talker类的基本定义: package com.lotontech.speech; import javax.sound.sampled.*; import java.io.*; import java.util.*; import java.net.*; public class Talker { private SourceDataLine line=null; } 如果从命令行执行Talker,下面的main()方法将作为入口点运行。main()方法获取第一个命令行参数,然后把它传递给sayPhoneWord()方法: /* * 读出在命令行中指定的表示读音的字符串 */ public static void main(String args[]) { Talker player=new Talker(); if (args.length0) player.sayPhoneWord(args[0]); System.exit(0); }
sayPhoneWord()方法既可以通过上面的main()方法调用,也可以在Java程序中直接调用。从表面上看,sayPhoneWord()方法比较复杂,其实并非如此。实际上,它简单地遍历所有单词的语音元素(在输入字符串中语音元素以“|”分隔),通过一个声音输出通道一个元素一个元素地播放出来。为了让声音更自然一些,我把每一个声音样本的结尾和下一个声音样本的开头合并了起来: /* * 读出指定的语音字符串 */ public void sayPhoneWord(String word) { // 为上一个声音构造的模拟byte数组 byte[] previousSound=null; // 把输入字符串分割成单独的音素 StringTokenizer st=new StringTokenizer(word,"|",false); while (st.hasMoreTokens()) { // 为音素构造相应的文件名字 String thisPhoneFile=st.nextToken(); thisPhoneFile="/allophones/"+thisPhoneFile+".au"; // 从声音文件读取数据 byte[] thisSound=getSound(thisPhoneFile); if (previousSound!=null) { // 如果可能的话,把前一个音素和当前音素合并 int mergeCount=0; if (previousSound.length=500 thisSound.length=500) mergeCount=500; for (int i=0; i { previousSound[previousSound.length-mergeCount+i] =(byte)((previousSound[previousSound.length -mergeCount+i]+thisSound[i])/2); } // 播放前一个音素 playSound(previousSound); // 把经过截短的当前音素作为前一个音素 byte[] newSound=new byte[thisSound.length-mergeCount]; for (int ii=0; ii newSound[ii]=thisSound[ii+mergeCount]; previousSound=newSound; } else previousSound=thisSound; } // 播放最后一个音素,清理声音通道 playSound(previousSound); drain(); } 在sayPhoneWord()的后面,你可以看到它调用playSound()输出单个声音样本(即一个音素),然后调用drain()清理声音通道。下面是playSound()的代码: /* * 该方法播放一个声音样本 */ private void playSound(byte[] data) { if (data.length0) line.write(data, 0, data.length); } 下面是drain()的代码: /* * 该方法清理声音通道 */ private void drain() { if (line!=null) line.drain(); try {Thread.sleep(100);} catch (Exception e) {} }
现在回过头来看sayPhoneWord(),这里还有一个方法我们没有分析,即getSound()方法。 getSound()方法从一个au文件以字节数据的形式读入预先录制的声音样本。要了解读取数据、转换音频格式、初始化声音输出行(SouceDataLine)以及构造字节数据的详细过程,请参考下面代码中的注释: /* * 该方法从文件读取一个音素, * 并把它转换成byte数组 */ private byte[] getSound(String fileName) { try { URL url=Talker.class.getResource(fileName); AudioInputStream stream = AudioSystem.getAudioInputStream(url); AudioFormat format = stream.getFormat(); // 把一个ALAW/ULAW声音转换成PCM以便回放 if ((format.getEncoding() == AudioFormat.Encoding.ULAW) || (format.getEncoding() == AudioFormat.Encoding.ALAW)) { AudioFormat tmpFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), format.getSampleSizeInBits() * 2, format.getChannels(), format.getFrameSize() * 2, format.getFrameRate(), true); stream = AudioSystem.getAudioInputStream(tmpFormat, stream); format = tmpFormat; } DataLine.Info info = new DataLine.Info( Clip.class, format, ((int) stream.getFrameLength() * format.getFrameSize())); if (line==null) { // 输出线还没有实例化 // 是否能够找到合适的输出线类型? DataLine.Info outInfo = new DataLine.Info(SourceDataLine.class, format); if (!AudioSystem.isLineSupported(outInfo)) { System.out.println("不支持匹配" + outInfo + "的输出线"); throw new Exception("不支持匹配" + outInfo + "的输出线"); } // 打开输出线 line = (SourceDataLine) AudioSystem.getLine(outInfo); line.open(format, 50000); line.start(); } int frameSizeInBytes = format.getFrameSize(); int bufferLengthInFrames = line.getBufferSize() / 8; int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes; byte[] data=new byte[bufferLengthInBytes]; // 读取字节数据,并计数 int numBytesRead = 0; if ((numBytesRead = stream.read(data)) != -1) { int numBytesRemaining = numBytesRead; } // 把字节数据切割成合适的大小 byte[] newData=new byte[numBytesRead]; for (int i=0; i newData[i]=data[i]; return newData; } catch (Exception e) { return new byte[0]; } } 这就是全部的代码,包括注释在内,一个大约150行代码的语音合成器。
三、文本-语音转换 以语音元素的格式指定待朗读的单词似乎过于复杂,如果要构造一个能够朗读文本(比如Web页面或Email)的应用,我们希望能够直接指定原始的文本。 深入分析这个问题之后,我在本文后面的ZIP文件中提供了一个试验性的文本-语音转换类。运行这个类,它将显示出分析结果。文本-语音转换类可以从命令行执行,如下所示: java com.lotontech.speech.Converter "hello there" 输出结果类如: hello - h|e|l|oo there - dth|aer 如果运行下面这个命令: java com.lotontech.speech.Converter "I like to read JavaWorld" 则输出结果为: i - ii like - l|ii|k to - t|ouu read - r|ee|a|d java - j|a|v|a world - w|err|l|d 这个转换类是如何工作的呢?实际上,我的方法相当简单,转换过程就是以一定的次序应用一组文本替换规则。例如对于单词“ant”、“want”、“wanted”、“unwanted”和“unique”,则我们想要应用的替换规则可能依次为: 用“|y|ou|n|ee|k|”替换“*unique*” 用“|w|o|n|t|”替换“*want*” 用“|a|”替换“*a*” 用“|e|”替换“*e*” 用“|d|”替换“*d*” 用“|n|”替换“*n*” 用“|u|”替换“*u*” 用“|t|”替换“*t*” 对于“unwanted”,输出序列为: unwanted un[|w|o|n|t|]ed (规则2) [|u|][|n|][|w|o|n|t|][|e|][|d|] (规则4、5、6、7) u|n|w|o|n|t|e|d (删除多余的符之后) 你将看到包含字母“wont”的单词和包含字母“ant”的单词以不同的方式发音,还将看到在特例规则的作用下,“unique”作为一个完整单词优先于其他规则,从而“unique”这个单词读作“y|ou...”而不是“u|n...”。
直接接入第三发的SDK就好,试试ZEGO即构科技的语音SDK吧,直接通过四行代码就可以接入,不用自己研发,省时省力。
并且这个的语音通话功能很好,没有卡顿、延迟、回声等情况,音质很细腻。
java WEB播放声音整体思路如下:
服务器判断后,可以返回一个对象给页面,两个字段就好了,一个是提示是否错误,一个是对应是播放那个音频文件(具体要看音频是固定还是动态的)。
如果是固定在页面,则可以传播放标志;
如果是动态,则传音频路径或者其他。
/ /项目名称:Car_Demo
/ /说明:参与实施汽车语音控制
/ /库:CMacro1016.lib
/ / bsrv222SDL.lib
/ / sacmv26e。库
/ /组成文件:main.c中
/ / Flash.asm,hardware.asm,ISR.asm
/ /的hardware.h,s480.h,hardware.inc
/ /硬件连接:IOA0 ----- KEY1
/ / IOA1 ----- KEY2
/ / IOA2 ----- KEY3
/ / IOB8 ---- - 远期
/ / IOB9 -----倒车
/ / IOB10 ----左
/ / IOB11 ----右转
/ /保养纪录:2005年-12-12 V1.0
/ / ===================================== ===================
#包括“s480.h”
#包括“bsrsd.h”
BR /#定义P_IOA_Data(挥发性无符号整数*)0x7000处
#定义P_IOA_Dir(挥发性无符号整数*)0x7002
#定义P_IOA_Attrib(挥发性无符号整数*)0x7003
#定义P_IOB_Data(挥发性无符号整型*)0x7005
#定义P_IOB_Dir(挥发性无符号整数*)0x7007
#定义P_IOB_Attrib(挥发性无符号整数*)0x7008
#定义P_TimerA_Data(挥发性无符号整数*)0x700A
#定义P_TimerA_Ctrl(挥发性无符号整数*)0x700B
#定义P_TimerB_Data(挥发性无符号整数*)0x700C
#定义P_TimerB_Ctrl(挥发性无符号整数*)0x700D
#定义P_Watchdog_Clear(挥发性无符号整型*)0x7012
#定义P_INT_Mask(挥发性无符号整数*)0x702D
#定义P_INT_Clear(挥发性无符号整数*)0x7011
#定义名_ID量0x100
#定义COMMAND_GO_ID 0x101
#定义COMMAND_BACK_ID 0x102
#定义COMMAND_LEFT_ID #定义COMMAND_RIGHT_ID量0x104
#定义S_NAME 0 / /给我一个名字吧
#定义S_ACT1 1 / /前进
#定义S_ACT2 2 / /倒车,请注意
#定义S_ACT3 3 / /左
#定义S_ACT4 4 / /右转
#定义S_RDY 5 / /是啊
#定义S_AGAIN 6 / /请重复
#定义S_NOVOICE 7 / /没有听到任何声音
#定义S_CMDDIFF 8 / /代码字说啊
#定义S_NOISY 8 / /说什么暗语呀
#定义S_START 9 / /准备开始识别
#定义S_GJG 10 / /诱拐绑架
#定义S_DCZY 11 / /倒车,请注意
的extern unsigned int类型BSR_SDModel [100]; / /外部变量BSR_SDModel [100],读者自带
外部无效F_FlashWrite1Word(unsigned int类型地址,无符号整型值);
外部无效F_FlashErase(无符号整数部门);
无符号整型uiTimeset = 3; / /运行时间定时器,调节参数控制运行时间
无符号整型uiTimecont; / /运行时定时
/ / ================================== ===========================
/ /语法:无效延迟();
/ /功能:延时
/ /参数:无
/ /返回值:无
/ / ================ =============================================
无效延迟()
{
无符号整数I;
就(i = 0; I 0X3FFF,我+ +)
{
* P_Watchdog_Clear = 0X0001;
/ / ============================== ===============================
/ /语法:无效PlaySnd(无符号SndIndex,无符号DAC_Channel);
/ /功能:语音播放功能
/ /参数:SndIndex播放语音资源索引号
/ / DAC_Channel播放通道选择
/ /返回值:无
/ / =============================================== ============== 无效PlaySnd(无符号SndIndex,无符号DAC_Channel)
{
BSR_StopRecognizer(); / /停止识别
SACM_S480_Initial(1); / /初始化为自动
SACM_S480_Play玩(SndIndex,DAC_Channel,3); / /开始播放语音
同时(!(SACM_S480_Status()&0X0001)= 0)/ /如果播放完毕?
SACM_S480_ServiceLoop(); / /解码,并填补了队列
* P_Watchdog_Clear = 0X0001; / /清除看门狗
}
SACM_S480_Stop(); / /停止播放
BSR_InitRecognizer(BSR_MIC); / /初始化识别器
}
/ / ============================== ===============================
/ /语法:INT TrainWord(INT的wordID,诠释SndID);
/ /功能:训练命令
/ /参数:
/ / SndID命令语气指数
/ /返回值的wordID指令编码:无
/ / ================================================= ============
整数TrainWord(无符号整数的wordID,无符号整型SndID)
{
int结果;
PlaySnd(SndID,3); / /导游培训,打相应的动作
指令,而(1)
{
结果= BSR_Train(的wordID,BSR_TRAIN_TWICE); / /训练两次,得到训练成绩
如果(结果== 0)打破;
开关(结果)
{
案例-1:/ /未检测到声音
PlaySnd(S_NOVOICE,3);
返回-1;
案例-2:/ /要培养第二
PlaySnd(S_AGAIN,3);
突破;
案例-3:/ /环境嘈杂
PlaySnd(S_NOISY,3);
返回-3;
案例-4:/ /数据库全
回报-4;
情况-5:/ /检测声音不同
PlaySnd(S_CMDDIFF,3);
返回-5;
情况-6:/ /错误号
回报-6;
默认:
突破;
返回0;
/ / =================================== ==========================
/ /语法:无效TrainSD();
/ /功能:训练功能
/ /参数:无
/ /返回值:无
/ / =============== ==============================================
无效TrainSD()
{
同时(TrainWord(名_ID,S_NAME)= 0!); / /培训名称
而(TrainWord(COMMAND_GO_ID,S_ACT1)= 0);! / /训练第1节动作
同时(TrainWord(COMMAND_BACK_ID,S_ACT2)= 0);! / /培训前两个动作
同时(TrainWord(COMMAND_LEFT_ID,S_ACT3)= 0!); / /训练第3节动作
同时(TrainWord(COMMAND_RIGHT_ID,S_ACT4)= 0!); / /培训4的动作
}
/ / ============================= ================================
/ /语法:无效StoreSD();
/ /实现功能:存储语音模型功能
/ /参数:无
/ /返回值:无
/ / ============ ================================================= BR /无效StoreSD() {unsigned int类型ulAddr,我,命令号,g_Ret;
F_FlashWrite1Word(0xef00,加上0xAAAA);
F_FlashErase(0xe000);
F_FlashErase(0xe100);
F_FlashErase(0xe200);
ulAddr = 0xe000 ;/ / ********
为(命令号= 0x100的;命令号0x105;命令号+ +)
{
g_Ret = BSR_ExportSDWord(命令号);
而(g_Ret! = 0)/ /导出模型成功?
g_Ret = BSR_ExportSDWord(命令号);
就(i = 0; I 100; i + +)/ /保存语音模型SD1(0xe000 --- 0xe063)
{
F_FlashWrite1Word(ulAddr,BSR_SDModel [I]) ;
ulAddr + = 1;
/ / ========================= ====================================
/ /语法:无效StoreSD();
/ /功能:承载语音模型函数
/ /参数:无
/ /返回值:无 / / ============= ================================================ 无效LoadSD()
{unsigned int类型* P,K,JK,惩戒,g_Ret;
P =(INT *)0xe000;
为(JK = 0; JK 5; JK + +)
{
为(K = 0,K 100,K +)
{
RET = * P;
BSR_SDModel [K] = RET; / /加载语音模型
P + = 1;
g_Ret = BSR_ImportSDWord();
而(g_Ret! = 0)/ /加载成功的模式?
g_Ret = BSR_ImportSDWord();
/ / ============================== ===============================
/ /语法:无效的GoAhead();
/ /功能:正向功能
/ /参数:无
/ /返回值:无
/ / =============== ==============================================
无效的GoAhead()/ /向前
PlaySnd(S_ACT1,3); / /提示
* P_IOB_Data = 0X0100; / /前进
* P_INT_Mask | = 0X0004; / /以下为中断定时器操作
__ asm的(“INT FIQ,IRQ”);
uiTimecont = 0;
/ / ======================================= ======================
/ /语法:无效的备份();
/ /功能:返回函数
/ /参数:无
/ /返回值:无
/ / =============== ==============================================
无效的备份()/ /向后
PlaySnd(S_DCZY,3); / /提示 * P_IOB_Data = 0x0200; / /向后
* P_INT_Mask | = 0X0004; / /以下为中断定时器操作
__ asm的(“INT FIQ,IRQ”);
uiTimecont = 0;
/ / =================================== ==========================
/ /语法:无效TurnLeft();
/ /功能:打开左侧的功能
/ /参数:无
/ /返回值:无
/ / ============== ===============================================
无效TurnLeft()/ /左转
PlaySnd(S_GJG,3);
* P_IOB_Data = 0x0900; / /右转
延迟(); / /延迟
* P_IOB_Data =成0x0500; / /左转
* P_INT_Mask | = 0X0004; / /以下为中断定时器操作
__ asm的(“INT FIQ,IRQ”);
uiTimecont = 0;
/ / ======================================= ======================
/ /语法:无效TurnRight();
/ /功能:右转子程序
/ /参数:无
/ /返回值:无
/ / ============== ===============================================
无效TurnRight()/ /右转
PlaySnd(S_GJG,3); / /语音提示
* P_IOB_Data =成0x0500; / /左转
延迟(); / /延迟
* P_IOB_Data = 0x0900; / /右转
* P_INT_Mask | = 0X0004; / /以下为中断定时器操作
__ asm的(“INT FIQ,IRQ”);
uiTimecont = 0;
/ / =================================== ==========================
/ /语法:无效停止();
/ /功能:停车功能
/ /参数:无
/ /返回值:无
/ / =============== ==============================================
无效停止()/ /停止
{
* P_IOB_Data值= 0x0000; / /停车
PlaySnd(S_RDY,3); / /语音提示
}
/ / =============================== ==============================
/ /语法:BSR无效(无效);
/ /功能:识别功能
/ /参数:无
/ /返回值:无
/ / =============== ==============================================
BSR无效(无效)
{
int结果; / /识别结果存储
结果= BSR_GetResult(); / /得到识别结果
如果(结果 0)/ /语音触发?
* P_IOB_Data值= 0x0000; / /临时停车
开关(结果)
{
案名_ID:/ /识别命令
停止(名称); / /停机位
突破;
情况COMMAND_GO_ID:/ /找出第一个命令
的GoAhead(); / /执行一个动作:直
突破; 案例COMMAND_BACK_ID:/ /找出第二个命令
备份(); / /执行动作二:倒车
突破;
情况COMMAND_LEFT_ID:/ /找出第三个命令
TurnLeft(); / /执行三个动作:向左转
突破;
情况COMMAND_RIGHT_ID:/ /找出第四个命令
TurnRight(); / /执行动作四:右转
突破;
默认:
突破;
/ / ============================= ================================
/ /语法:IRQ5无效(无效);
/ /功能:中断服务子程序
/ /参数:无
/ /返回值:无
/ / ============== ===============================================
IRQ5无效(无效)的__attribute__((ISR)); / /运动定时控制
IRQ5无效(无效)
{
如果(uiTimecont + + == uiTimeset)
{
* P_IOB_Data值= 0x0000;
* P_INT_Clear = 0X0004;
/ / =================================== ==========================
/ /语法:INT主要(无效);
/ /功能:主要功能
/ /参数:无
/ /返回值:无
/ / ============== ===============================================
国际主要(无效)
{unsigned int类型BS_Flag; / /火车标志
* P_IOA_Dir =为0xFF00; / /初始化IOA,IOA07下拉输入
* P_IOA_Attrib =为0xFF00;
* P_IOA_Data值= 0x0000;
* P_IOB_Dir = 0x0f00; / /初始化IOB,IOB811与输出
* P_IOB_Attrib = 0x0f00;
* P_IOB_Data值= 0x0000;
BSR_DeleteSDGroup(0); / /初始化存储器RAM
BS_Flag = *(unsigned int类型*)0xe000; / /读取内存单元0xe000
如果(BS_Flag == 0xFFFF的)/ /没有受过训练(0xe000内容0xFFFF的)
{
TrainSD(); / /培训
StoreSD(); / /存储的训练结果(语音模式)
其他/ /训练(0xe000内容0x0055)
{
LoadSD(); / /语音识别模型加载
}
PlaySnd(S_START,3); / /开始识别
BSR_InitRecognizer(BSR_MIC)提示; / /初始化识别器
同时(1)
{
BSR();
如果((* P_IOA_Data)&0X0004)/ /如果再培训
{
F_FlashErase(0xe000);
而(1);
/ / ========================= ===================================
/ /文件名:flash.asm
/ /实现功能:SPCE061 32K闪存读卡器
/ /保养纪录:2003-6-9 V1 .0
/ / ================= ===========================================
。 INCLUDE hardware.inc
。 DEFINE C_FLASH_SIZE为0x8000
。 DEFINE C_FLASH_BLOCK_SIZE量0x100
。 DEFINE C_FLASH_MATCH加上0xAAAA
。 DEFINE C_FLASH_PAGE_ERASE 0x5511 / /擦除一个
。 DEFINE C_FLASH_MASS_ERASE 0x5522 / /
。 DEFINE C_FLASH_1WORD_PGM 0x5533 / /写一个字
。 DEFINE C_FLASH_SEQUENT_PGM 0x5544 / /写多个字
。 DEFINE C_FLASH_MAIN_BLOCK为0x5555
。 DEFINE C_FLASH_INFORM_BLOCK 0x5566
。代码
/ / =========================================== ================================================= BR / / /语法:无效F_FlashWrite1Word(INT地址,int值)
/ /描述:写一个字到FLASH
/ /参数:要写入的地址内存中的数据写入值地址数据
/ /返回:无
/ / ================================== ================================================== ===========
。公众_F_FlashWrite1Word
DEFINE P_Flash_Ctrl 0x7555
_F_FlashWrite1Word:.. PROC
推基点至[SP]
BP = SP +1
R1 = C_FLASH_MATCH / / AAAA
[P_Flash_Ctrl] = R1
R1 = C_FLASH_1WORD_PGM / / 5533
[P_Flash_Ctrl] = R1
R1 = [BP +4] / / flash地址
R2 = [BP + 4 ] / /数据
[R1 = R2
流行BP从[SP]
。 ENDP
/ / ======================================= ================================================== ====
/ /语法:F_FlashWrite(INT部门,诠释及次数,int的大小)
/ /说明:顺序写更多的字
/ /参数:扇区是起始地址将数据写入写入和NUM-大小的写入数据数
/ /返回的数据:无
/ / ================== ================================================== =========================
公众_F_FlashWrite
_F_FlashWrite:.. PROC
推基点至[SP]
BP = SP +1
R1 = [BP +4] / / flash基地址
R2 =
/数据/ R3 = [BP +5] / /多字节
R4 = C_FLASH_MATCH / / AAAA
[P_Flash_Ctrl] = R4
L_FlashWriteLoop:
R4 = C_FLASH_SEQUENT_PGM / / 5544
[P_Flash_Ctrl] = R4 R4 = [R2 +]
[R1 + +] = R4
R3 - = 1
JNZ L_FlashWriteLoop
[P_Flash_Ctrl] = R3 / /写从最终
弹出基点[SP]
RETF 。 ENDP
/ / ======================================= ================================================== ===
/ /语法:无效F_FlashErase(部门)
/ /说明:擦除256字节
/ /参数:起始地址扇区擦除页
/ /返回:无
/ / ============================================ ================================================ 公共_F_FlashErase
_F_FlashErase:.. PROC
推基点至[SP]
BP = SP + 1
R1 = C_FLASH_MATCH / / AAAA
[P_Flash_Ctrl] = R1
R1 = C_FLASH_PAGE_ERASE / / 5511
[P_Flash_Ctrl] = R1
R1 = [BP +4] / /擦除一个
[R1] = R1
从[SP]
。 ENDP
。完
/ / ======================================= =====================
/ /文件名:ISR.asm
/ /功能:语音播放/识别中断服务
/ /保养纪录:2003-9-9 V1.0
/ / ============================== ==============================
包括hardware.inc
公共_FIQ;。 ..
外部_BSR_FIQ_Routine
外部F_FIQ_Service_SACM_S480
_FIQ:..
推R1,R5为[SP]; / /注册推来保护
R1 = C_FIQ_TMA;
[P_INT_Clear] = R1;
致电_BSR_FIQ_Routine / /语音识别中断服务
致电F_FIQ_Service_SACM_S480; / /语音播放中断服务
流行R1,R5从[SP];
RETI;