├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ ├── Msc.jar
│ └── Sunflower.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── alvin
│ │ └── speechdemo
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── iattest.wav
│ │ ├── userwords.txt
│ │ └── voice.amr
│ ├── java
│ │ └── com
│ │ │ └── alvin
│ │ │ └── speechdemo
│ │ │ ├── MainActivity.java
│ │ │ └── util
│ │ │ ├── AudioDecode.java
│ │ │ ├── FucUtil.java
│ │ │ └── JsonParser.java
│ ├── jniLibs
│ │ └── armeabi
│ │ │ └── libmsc.so
│ └── res
│ │ ├── anim
│ │ ├── push_fade_in.xml
│ │ └── push_fade_out.xml
│ │ ├── drawable-xhdpi
│ │ └── img_view_loading.png
│ │ ├── layout
│ │ ├── activity_login.xml
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── alvin
│ └── speechdemo
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SpeechDemo
2 | 结合讯飞语音,使用封装好的工具类,把MediaRecord录制好的本地录音amr格式音频转成文字
3 | MediaRecorder的关键设置项代码如下
4 | ```Java
5 | MediaRecorder mRecorder = new MediaRecorder();
6 | mRecorder.setMaxDuration(60500);
7 | mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
8 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
9 | mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
10 | } else {
11 | mRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
12 | }
13 | mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
14 | mRecorder.setOutputFile(mFileName);
15 | mRecorder.prepare();
16 | mRecorder.start();
17 | ```
18 |
19 | 因时间仓促就没有把录音部分放入demo还请见谅,demo中在access中放置了录制好的音频,可以拿出来放到手机sd卡相应目录中,或者自己定义的一个路径使用方法如下,也可以参考[我的博客](http://blog.csdn.net/u010705554/article/details/53189317)
20 | ```Java
21 | /**
22 | * 工具类
23 | * @param audioPath
24 | */
25 | private void audioDecodeFun(String audioPath){
26 | audioDecode = AudioDecode.newInstance();
27 | audioDecode.setFilePath(audioPath);
28 | audioDecode.prepare();
29 | audioDecode.setOnCompleteListener(new AudioDecode.OnCompleteListener() {
30 | @Override
31 | public void completed(final ArrayList pcmData) {
32 | if(pcmData!=null){
33 | //写入音频文件数据,数据格式必须是采样率为8KHz或16KHz(本地识别只支持16K采样率,云端都支持),位长16bit,单声道的wav或者pcm
34 | //必须要先保存到本地,才能被讯飞识别
35 | //为防止数据较长,多次写入,把一次写入的音频,限制到 64K 以下,然后循环的调用wirteAudio,直到把音频写完为止
36 | for (byte[] data : pcmData){
37 | mIat.writeAudio(data, 0, data.length);
38 | }
39 | Log.d("-----------stop",System.currentTimeMillis()+"");
40 | mIat.stopListening();
41 | }else{
42 | mIat.cancel();
43 | Log.d(TAG,"--->读取音频流失败");
44 | }
45 | audioDecode.release();
46 | }
47 | });
48 | audioDecode.startAsync();
49 | }
50 |
51 | ```
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 | defaultConfig {
7 | applicationId "com.alvin.speechdemo"
8 | minSdkVersion 9
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:23.3.0'
28 | testCompile 'junit:junit:4.12'
29 | compile 'com.squareup.picasso:picasso:2.5.2'
30 | compile 'com.github.bumptech.glide:glide:3.7.0'
31 | }
32 |
--------------------------------------------------------------------------------
/app/libs/Msc.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/libs/Msc.jar
--------------------------------------------------------------------------------
/app/libs/Sunflower.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/libs/Sunflower.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\AndroidSDK\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/alvin/speechdemo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.alvin.speechdemo;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.alvin.speechdemo", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
26 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
42 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/assets/iattest.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/assets/iattest.wav
--------------------------------------------------------------------------------
/app/src/main/assets/userwords.txt:
--------------------------------------------------------------------------------
1 | {"userword":[{"name":"我的常用词","words":["测试常用词","测试常用词2","测试常用词3"]}]}
--------------------------------------------------------------------------------
/app/src/main/assets/voice.amr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/assets/voice.amr
--------------------------------------------------------------------------------
/app/src/main/java/com/alvin/speechdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.alvin.speechdemo;
2 |
3 | import android.app.Activity;
4 | import android.os.Environment;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.widget.EditText;
9 | import android.widget.Toast;
10 |
11 | import com.alvin.speechdemo.util.AudioDecode;
12 | import com.alvin.speechdemo.util.FucUtil;
13 | import com.iflytek.cloud.ErrorCode;
14 | import com.iflytek.cloud.LexiconListener;
15 | import com.iflytek.cloud.RecognizerListener;
16 | import com.iflytek.cloud.RecognizerResult;
17 | import com.iflytek.cloud.SpeechConstant;
18 | import com.iflytek.cloud.SpeechError;
19 | import com.iflytek.cloud.SpeechRecognizer;
20 | import com.iflytek.cloud.SpeechUtility;
21 | import com.iflytek.sunflower.FlowerCollector;
22 | import com.alvin.speechdemo.util.JsonParser;
23 |
24 | import org.json.JSONObject;
25 |
26 | import java.io.File;
27 | import java.util.ArrayList;
28 | import java.util.HashMap;
29 | import java.util.LinkedHashMap;
30 |
31 | public class MainActivity extends Activity implements View.OnClickListener{
32 |
33 | private final String TAG = "SpeechDemo:ID";
34 | private EditText et_voice_text;
35 | private Toast mToast;
36 | // 用HashMap存储听写结果
37 | private HashMap mIatResults = new LinkedHashMap<>();
38 | private SpeechRecognizer mIat;
39 | // 引擎类型
40 | private String mEngineType = SpeechConstant.TYPE_CLOUD;
41 | private AudioDecode audioDecode;
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setContentView(R.layout.activity_main);
47 |
48 | init();
49 | initView();
50 | }
51 |
52 | private void init(){
53 | mToast = Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT);
54 | //创建语音配置对象,换成自己的id,另外so文件也要换成自己的,AndroidManifest里面还有个统计分析的id也换成自己的
55 | SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID+"=5227fccc");
56 | //1、创建SpeechRecognizer对象,第二个参数:本地识别时传InitListener
57 | mIat = SpeechRecognizer.createRecognizer(MainActivity.this,null);
58 | setParam();
59 | }
60 |
61 | private void initView(){
62 | et_voice_text = (EditText) findViewById(R.id.et_voice_text);
63 | }
64 |
65 | //听写监听器
66 | private RecognizerListener mRecognizerListener = new RecognizerListener() {
67 |
68 | //volume音量值0~30,data音频数据
69 | @Override
70 | public void onVolumeChanged(int volume, byte[] bytes) {
71 | showTip("当前正在说话,音量大小:" + volume);
72 | Log.d(TAG, "返回音频数据:"+bytes.length);
73 | }
74 | //开始录音
75 | // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
76 | @Override
77 | public void onBeginOfSpeech() {
78 | showTip("开始说话");
79 | }
80 | //结束录音
81 | @Override
82 | public void onEndOfSpeech() {
83 | // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
84 | showTip("结束说话");
85 | }
86 |
87 | /**
88 | * 听写结果回调接口,返回Json格式结果
89 | * 一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加
90 | * isLast等于true时会话结束。
91 | */
92 | @Override
93 | public void onResult(RecognizerResult recognizerResult, boolean b) {
94 | Log.d(TAG, recognizerResult.getResultString());
95 | printResult(recognizerResult);
96 | }
97 |
98 | //会话发生错误回调接口
99 | // Tips:
100 | // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
101 | @Override
102 | public void onError(SpeechError speechError) {
103 | //打印错误码描述
104 | Log.d(TAG, "error:" + speechError.getPlainDescription(true));
105 | showTip(speechError.getPlainDescription(true));
106 | }
107 | //扩展用接口
108 | @Override
109 | public void onEvent(int eventType, int arg1, int arg2, Bundle bundle) {
110 |
111 | }
112 | };
113 |
114 | private void printResult(RecognizerResult recognizerResult) {
115 | String text = JsonParser.parseIatResult(recognizerResult.getResultString());
116 | String sn = null;
117 | //读取Json结果中的sn字段
118 | try {
119 | JSONObject resultJson = new JSONObject(recognizerResult.getResultString());
120 | sn = resultJson.optString("sn");
121 | }catch (Exception e){
122 | e.printStackTrace();
123 | }
124 | mIatResults.put(sn,text);
125 | StringBuilder sb = new StringBuilder();
126 | for (String key:mIatResults.keySet()){
127 | sb.append(mIatResults.get(key));
128 | }
129 | et_voice_text.setText(sb.toString());
130 | et_voice_text.setSelection(et_voice_text.length());
131 | }
132 |
133 | private LexiconListener mLexiconListener = new LexiconListener() {
134 | @Override
135 | public void onLexiconUpdated(String lexiconId, SpeechError speechError) {
136 | if (speechError != null) {
137 | Log.d(TAG,"上传词表:"+speechError.toString());
138 | } else {
139 | Log.d(TAG,"上传词表:成功");
140 | }
141 | }
142 | };
143 |
144 | int ret = 0; // 函数调用返回值
145 | @Override
146 | public void onClick(View v) {
147 | switch (v.getId()){
148 | case R.id.bt_start:
149 | // 开始听写
150 | // 如何判断一次听写结束:OnResult isLast=true 或者 onError
151 | // 移动数据分析,收集开始听写事件
152 | FlowerCollector.onEvent(MainActivity.this,"iat_recognize");
153 | et_voice_text.setText(null);
154 | mIatResults.clear();
155 |
156 | // 不显示听写对话框
157 | ret = mIat.startListening(mRecognizerListener);
158 | if (ret != ErrorCode.SUCCESS) {
159 | showTip("听写失败,错误码:" + ret);
160 | } else {
161 | showTip(getString(R.string.text_begin));
162 | }
163 | break;
164 | case R.id.bt_upload:
165 | uploadUserWords();
166 | break;
167 | case R.id.bt_read_voice:
168 | et_voice_text.setText(null);// 清空显示内容
169 | mIatResults.clear();
170 | setParam();
171 | // 设置音频来源为外部文件
172 | String mFileDirName = Environment.getExternalStorageDirectory().toString()
173 | + File.separator+ "ID"+ File.separator + "download";
174 | String audioPath = mFileDirName + File.separator + "voice.amr";
175 | String mFileName2 = mFileDirName + File.separator + "test_temp.wav";
176 | mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
177 | mIat.setParameter(SpeechConstant.SAMPLE_RATE, "8000");//设置正确的采样率
178 | mIat.setParameter(SpeechConstant.ASR_SOURCE_PATH, mFileName2);
179 | mIat.startListening(mRecognizerListener);
180 | //主要参数: -i 设定输入流 -f 设定输出格式 -ss 开始时间
181 | // 视频参数:
182 | // -b 设定视频流量,默认为200Kbit/s -r 设定帧速率,
183 | // 默认为25 -s 设定画面的宽与高 -aspect 设定画面的比例
184 | // -vn 不处理视频 -vcodec 设定视频编解码器,未设定时则使用与输入流相同的编解码器
185 | // 音频参数:
186 | // -ar 设定采样率 -ac 设定声音的Channel数 -acodec 设定声音编解码器,未设定时则使用与输入流相同的编解码器 -an 不处理音频
187 |
188 | ret = mIat.startListening(mRecognizerListener);
189 |
190 | if (ret != ErrorCode.SUCCESS) {
191 | showTip("识别失败,错误码:" + ret);
192 | } else {
193 | //iatFun();//讯飞demo里面的方法
194 | audioDecodeFun(audioPath);
195 | }
196 |
197 | break;
198 | }
199 | }
200 |
201 | /**
202 | * 讯飞
203 | */
204 | private void iatFun(){
205 | byte[] audioData = FucUtil.readAudioFile(MainActivity.this, "iattest.wav");
206 | if (null != audioData) {
207 | showTip("开始识别");
208 | // 一次(也可以分多次)写入音频文件数据,数据格式必须是采样率为8KHz或16KHz(本地识别只支持16K采样率,云端都支持),位长16bit,单声道的wav或者pcm
209 | // 写入8KHz采样的音频时,必须先调用setParameter(SpeechConstant.SAMPLE_RATE, "8000")设置正确的采样率
210 | // 注:当音频过长,静音部分时长超过VAD_EOS将导致静音后面部分不能识别。
211 | // 音频切分方法:FucUtil.splitBuffer(byte[] buffer,int length,int spsize);
212 | mIat.writeAudio(audioData, 0, audioData.length);
213 | mIat.stopListening();
214 | } else {
215 | mIat.cancel();
216 | showTip("读取音频流失败");
217 | }
218 | }
219 |
220 | /**
221 | * 工具类
222 | * @param audioPath
223 | */
224 | private void audioDecodeFun(String audioPath){
225 | audioDecode = AudioDecode.newInstance();
226 | audioDecode.setFilePath(audioPath);
227 | audioDecode.prepare();
228 | audioDecode.setOnCompleteListener(new AudioDecode.OnCompleteListener() {
229 | @Override
230 | public void completed(final ArrayList pcmData) {
231 | if(pcmData!=null){
232 | //写入音频文件数据,数据格式必须是采样率为8KHz或16KHz(本地识别只支持16K采样率,云端都支持),位长16bit,单声道的wav或者pcm
233 | //必须要先保存到本地,才能被讯飞识别
234 | //为防止数据较长,多次写入,把一次写入的音频,限制到 64K 以下,然后循环的调用wirteAudio,直到把音频写完为止
235 | for (byte[] data : pcmData){
236 | mIat.writeAudio(data, 0, data.length);
237 | }
238 | Log.d("-----------stop",System.currentTimeMillis()+"");
239 | mIat.stopListening();
240 | }else{
241 | mIat.cancel();
242 | Log.d(TAG,"--->读取音频流失败");
243 | }
244 | audioDecode.release();
245 | }
246 | });
247 | audioDecode.startAsync();
248 | }
249 |
250 | //上传用户词表,用于在听写着上传个性化数据,以提高匹配率
251 | private void uploadUserWords(){
252 | String content = FucUtil.readFile(MainActivity.this,"userwords.txt","utf-8");
253 | et_voice_text.setText(content);
254 |
255 | ret = mIat.updateLexicon("userword", content, mLexiconListener);
256 | if (ret != ErrorCode.SUCCESS){
257 | Log.d(TAG,"上传热词失败,错误码:" + ret);
258 | }
259 | }
260 |
261 | private void showTip(final String str) {
262 | mToast.setText(str);
263 | mToast.show();
264 | }
265 |
266 | /**
267 | * 参数设置
268 | */
269 | private void setParam(){
270 | //参数设置
271 | /**
272 | * 应用领域 服务器为不同的应用领域,定制了不同的听写匹配引擎,使用对应的领域能获取更 高的匹配率
273 | * 应用领域用于听写和语音语义服务。当前支持的应用领域有:
274 | * 短信和日常用语:iat (默认)
275 | * 视频:video
276 | * 地图:poi
277 | * 音乐:music
278 | */
279 | mIat.setParameter(SpeechConstant.DOMAIN,"iat");
280 | /**
281 | * 在听写和语音语义理解时,可通过设置此参数,选择要使用的语言区域
282 | * 当前支持:
283 | * 简体中文:zh_cn(默认)
284 | * 美式英文:en_us
285 | */
286 | mIat.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
287 | /**
288 | * 每一种语言区域,一般还有不同的方言,通过此参数,在听写和语音语义理解时, 设置不同的方言参数。
289 | * 当前仅在LANGUAGE为简体中文时,支持方言选择,其他语言区域时, 请把此参数值设为null。
290 | * 普通话:mandarin(默认)
291 | * 粤 语:cantonese
292 | * 四川话:lmz
293 | * 河南话:henanese
294 | */
295 | mIat.setParameter(SpeechConstant.ACCENT,"mandarin");
296 | // 设置听写引擎
297 | mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
298 | //设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
299 | //默认值:短信转写5000,其他4000
300 | mIat.setParameter(SpeechConstant.VAD_BOS,"4000");
301 | // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
302 | mIat.setParameter(SpeechConstant.VAD_EOS,"1000");
303 | // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
304 | mIat.setParameter(SpeechConstant.ASR_PTT,"1");
305 | // 设置音频保存路径,保存音频格式支持pcm、wav
306 | mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
307 | //mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");
308 | //文本,编码
309 | mIat.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");
310 | }
311 |
312 | @Override
313 | protected void onDestroy() {
314 | super.onDestroy();
315 | // 退出时释放连接
316 | mIat.cancel();
317 | //mIat.destroy();
318 | }
319 | @Override
320 | protected void onResume() {
321 | // 开放统计 移动数据统计分析
322 | FlowerCollector.onResume(MainActivity.this);
323 | FlowerCollector.onPageStart(TAG);
324 | super.onResume();
325 | }
326 |
327 | @Override
328 | protected void onPause() {
329 | // 开放统计 移动数据统计分析
330 | FlowerCollector.onPageEnd(TAG);
331 | FlowerCollector.onPause(MainActivity.this);
332 | super.onPause();
333 | }
334 | }
335 |
--------------------------------------------------------------------------------
/app/src/main/java/com/alvin/speechdemo/util/AudioDecode.java:
--------------------------------------------------------------------------------
1 | package com.alvin.speechdemo.util;
2 |
3 |
4 | import android.media.AudioFormat;
5 | import android.media.MediaCodec;
6 | import android.media.MediaExtractor;
7 | import android.media.MediaFormat;
8 | import android.os.Build;
9 | import android.util.Log;
10 |
11 | import java.io.IOException;
12 | import java.nio.ByteBuffer;
13 | import java.util.ArrayList;
14 |
15 | /**
16 | * 本地AMR录音解码成PCM数据流
17 | */
18 | public class AudioDecode {
19 |
20 | private static final String TAG = "AudioDecode";
21 | private String srcPath;//语音本地路径
22 | private MediaCodec mediaDecode;
23 | private MediaExtractor mediaExtractor;
24 | private ByteBuffer[] decodeInputBuffers;
25 | private ByteBuffer[] decodeOutputBuffers;
26 | private MediaCodec.BufferInfo decodeBufferInfo;
27 | private ArrayList chunkPCMDataContainer;//PCM数据块容器
28 | private OnCompleteListener onCompleteListener;
29 | private boolean codeOver = false;//解码结束
30 | private byte[] pcmData;//解码最终存储的完整数据流
31 | private Thread decoderThread;
32 |
33 | public static AudioDecode newInstance() {
34 | return new AudioDecode();
35 | }
36 |
37 | /**
38 | * 设置要读取的文件位置
39 | *
40 | * @param srcPath
41 | */
42 | public void setFilePath(String srcPath) {
43 | this.srcPath = srcPath;
44 | }
45 |
46 | /**
47 | * 准备工作
48 | */
49 | public void prepare() {
50 |
51 | if (srcPath == null) {
52 | throw new IllegalArgumentException("srcPath can't be null");
53 | }
54 | chunkPCMDataContainer = new ArrayList<>();
55 | initMediaDecode();//解码器
56 | }
57 |
58 | /**
59 | * 初始化解码器
60 | */
61 | private void initMediaDecode() {
62 | try {
63 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
64 | mediaExtractor = new MediaExtractor();//此类可分离视频文件的音轨和视频轨道
65 | mediaExtractor.setDataSource(srcPath);//媒体文件的位置
66 | for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {//遍历媒体轨道 此处我们传入的是音频文件,所以也就只有一条轨道
67 | MediaFormat format = mediaExtractor.getTrackFormat(i);;
68 | format.setInteger(MediaFormat.KEY_BIT_RATE, AudioFormat.ENCODING_PCM_16BIT);
69 | String mime = format.getString(MediaFormat.KEY_MIME);
70 | if (mime.startsWith("audio")) {//获取音频轨道
71 | mediaExtractor.selectTrack(i);//选择此音频轨道
72 | mediaDecode = MediaCodec.createDecoderByType(mime);//创建Decode解码器
73 | mediaDecode.configure(format, null, null, 0);
74 | break;
75 | }
76 | }
77 | if (mediaDecode == null) {
78 | Log.e(TAG, "create mediaDecode failed");
79 | return;
80 | }
81 | mediaDecode.start();//启动MediaCodec ,等待传入数据
82 | decodeInputBuffers = mediaDecode.getInputBuffers();//MediaCodec在此ByteBuffer[]中获取输入数据
83 | decodeOutputBuffers = mediaDecode.getOutputBuffers();//MediaCodec将解码后的数据放到此ByteBuffer[]中 我们可以直接在这里面得到PCM数据
84 | decodeBufferInfo = new MediaCodec.BufferInfo();//用于描述解码得到的byte[]数据的相关信息
85 | showLog("buffers:" + decodeInputBuffers.length);
86 | }
87 | } catch (IOException e) {
88 | e.printStackTrace();
89 | }
90 | }
91 |
92 |
93 |
94 | /**
95 | * 开始转码
96 | * 音频数据 解码成PCM,获取到PCM数组
97 | */
98 | public void startAsync() {
99 | decoderThread = new Thread(new DecodeRunnable());
100 | decoderThread.start();
101 | }
102 |
103 | /**
104 | * 将PCM数据存入{@link #chunkPCMDataContainer}
105 | *
106 | * @param pcmChunk PCM数据块
107 | */
108 | private void putPCMData(byte[] pcmChunk) {
109 | synchronized (AudioDecode.class) {//记得加锁
110 | chunkPCMDataContainer.add(pcmChunk);
111 | }
112 | }
113 |
114 | /**
115 | * 在Container中{@link #chunkPCMDataContainer}取出PCM数据
116 | *
117 | * @return PCM数据块
118 | */
119 | private byte[] getPCMData() {
120 | synchronized (AudioDecode.class) {//记得加锁
121 | if (chunkPCMDataContainer.isEmpty()) {
122 | return null;
123 | }
124 |
125 | byte[] pcmChunk = chunkPCMDataContainer.get(0);//每次取出index 0 的数据
126 | chunkPCMDataContainer.remove(pcmChunk);//取出后将此数据remove掉 既能保证PCM数据块的取出顺序 又能及时释放内存
127 | return pcmChunk;
128 | }
129 | }
130 |
131 |
132 | /**
133 | * 解码{@link #srcPath}音频文件 得到PCM数据块
134 | *
135 | * @return 是否解码完所有数据
136 | */
137 | private void srcAudioFormatToPCM() {
138 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
139 | if(decodeInputBuffers!=null){
140 | try {
141 | for (int i = 0; i < decodeInputBuffers.length - 1; i++) {
142 | int inputIndex = 0;//获取可用的inputBuffer -1代表一直等待,0表示不等待 建议-1,避免丢帧
143 | inputIndex = mediaDecode.dequeueInputBuffer(-1);
144 | if (inputIndex < 0) {
145 | codeOver = true;
146 | return;
147 | }
148 | ByteBuffer inputBuffer = decodeInputBuffers[inputIndex];//拿到inputBuffer
149 | inputBuffer.clear();//清空之前传入inputBuffer内的数据
150 | int sampleSize = mediaExtractor.readSampleData(inputBuffer, 0);//MediaExtractor读取数据到inputBuffer中
151 | if (sampleSize < 0) {//小于0 代表所有数据已读取完成
152 | codeOver = true;
153 | } else {
154 | mediaDecode.queueInputBuffer(inputIndex, 0, sampleSize, 0, 0);//通知MediaDecode解码刚刚传入的数据
155 | mediaExtractor.advance();//MediaExtractor移动到下一取样处
156 | }
157 | }
158 |
159 | //获取解码得到的byte[]数据 参数BufferInfo上面已介绍 10000同样为等待时间 同上-1代表一直等待,0代表不等待。此处单位为微秒
160 | //此处建议不要填-1 有些时候并没有数据输出,那么他就会一直卡在这 等待
161 | int outputIndex = mediaDecode.dequeueOutputBuffer(decodeBufferInfo, 10000);
162 |
163 | ByteBuffer outputBuffer;
164 | byte[] chunkPCM;
165 | while (outputIndex >= 0) {//每次解码完成的数据不一定能一次吐出 所以用while循环,保证解码器吐出所有数据
166 | outputBuffer = decodeOutputBuffers[outputIndex];//拿到用于存放PCM数据的Buffer
167 | chunkPCM = new byte[decodeBufferInfo.size];//BufferInfo内定义了此数据块的大小
168 | outputBuffer.get(chunkPCM);//将Buffer内的数据取出到字节数组中
169 | outputBuffer.clear();//数据取出后一定记得清空此Buffer MediaCodec是循环使用这些Buffer的,不清空下次会得到同样的数据
170 | putPCMData(chunkPCM);//自己定义的方法,供编码器所在的线程获取数据,下面会贴出代码
171 | mediaDecode.releaseOutputBuffer(outputIndex, false);//此操作一定要做,不然MediaCodec用完所有的Buffer后 将不能向外输出数据
172 | outputIndex = mediaDecode.dequeueOutputBuffer(decodeBufferInfo, 10000);//再次获取数据,如果没有数据输出则outputIndex=-1 循环结束
173 | }
174 |
175 | if(codeOver){
176 | if (onCompleteListener != null) {
177 | onCompleteListener.completed(chunkPCMDataContainer);
178 | }
179 | }
180 | }catch (Exception e){
181 | e.printStackTrace();
182 | codeOver = true;
183 | if (onCompleteListener != null) {
184 | onCompleteListener.completed(chunkPCMDataContainer);
185 | }
186 | }
187 | }
188 | }
189 | }
190 |
191 | /**
192 | * android 5.0以上
193 | */
194 | private void srcAudioFormatToPCMHigherApi() {
195 | if (Build.VERSION.SDK_INT >= 21){
196 | boolean sawOutputEOS = false;
197 | final long kTimeOutUs = 10000;
198 | long presentationTimeUs = 0;
199 | while (!sawOutputEOS){
200 | try{
201 | int inputIndex = mediaDecode.dequeueInputBuffer(-1);
202 | if (inputIndex >= 0){
203 | ByteBuffer inputBuffer = mediaDecode.getInputBuffer(inputIndex);
204 | if(inputBuffer!=null){
205 | int sampleSize = mediaExtractor.readSampleData(inputBuffer, 0);
206 | if (sampleSize < 0) {// 小于0 代表所有数据已读取完成
207 | sawOutputEOS = true;
208 | codeOver = true;
209 | break;
210 | }else{
211 | presentationTimeUs = mediaExtractor.getSampleTime();
212 | mediaDecode.queueInputBuffer(inputIndex, 0, sampleSize, presentationTimeUs, 0);// 通知MediaDecode解码刚刚传入的数据
213 | mediaExtractor.advance();
214 | }
215 | }
216 | }else{
217 | sawOutputEOS = true;
218 | codeOver = true;
219 | }
220 | int outputIndex = mediaDecode.dequeueOutputBuffer(decodeBufferInfo, kTimeOutUs);
221 | ByteBuffer outputBuffer ;//= mediaDecode.getOutputBuffer(outputIndex);// 拿到用于存放PCM数据的Buffer
222 | while (outputIndex >= 0){
223 | outputBuffer = mediaDecode.getOutputBuffer(outputIndex);
224 | boolean doRender = (decodeBufferInfo.size != 0);
225 | if(doRender && outputBuffer!=null){
226 | outputBuffer.position(decodeBufferInfo.offset);
227 | outputBuffer.limit(decodeBufferInfo.offset + decodeBufferInfo.size);
228 | byte[] chunkPCM = new byte[decodeBufferInfo.size];// BufferInfo内定义了此数据块的大小
229 | outputBuffer.get(chunkPCM);
230 | outputBuffer.clear();// 数据取出后一定记得清空此Buffer MediaCodec是循环使用这些Buffer的,不清空下次会得到同样的数据
231 | putPCMData(chunkPCM);// 自己定义的方法,供编码器所在的线程获取数据,下面会贴出代码
232 | mediaDecode.releaseOutputBuffer(outputIndex, false);// 此操作一定要做,不然MediaCodec用完所有的Buffer后将不能向外输出数据
233 | outputIndex = mediaDecode.dequeueOutputBuffer(decodeBufferInfo, kTimeOutUs);
234 | }
235 | }
236 | }catch (Exception e){
237 | e.printStackTrace();
238 | sawOutputEOS = true;
239 | codeOver = true;
240 | }
241 | }
242 | if(codeOver){
243 | if (onCompleteListener != null) {
244 | onCompleteListener.completed(chunkPCMDataContainer);
245 | }
246 | }
247 | }
248 | }
249 |
250 | /**
251 | * 释放资源
252 | */
253 | public void release() {
254 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
255 |
256 | try{
257 | if(decoderThread!=null && decoderThread.isAlive()){
258 | decoderThread.interrupt();
259 | codeOver = true;
260 | }
261 |
262 | if (mediaDecode != null) {
263 | mediaDecode.stop();
264 | mediaDecode.release();
265 | mediaDecode = null;
266 | }
267 |
268 | if (mediaExtractor != null) {
269 | mediaExtractor.release();
270 | mediaExtractor = null;
271 | }
272 |
273 | if (onCompleteListener != null) {
274 | onCompleteListener = null;
275 | }
276 | }catch (Exception e){
277 | e.printStackTrace();
278 | }
279 |
280 | }
281 | }
282 |
283 | /**
284 | * 解码线程
285 | */
286 | private class DecodeRunnable implements Runnable {
287 |
288 | @Override
289 | public void run() {
290 | while (!codeOver) {
291 | if(Build.VERSION.SDK_INT>=21){
292 | srcAudioFormatToPCMHigherApi();
293 | }else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
294 | srcAudioFormatToPCM();
295 | }
296 | }
297 | }
298 | }
299 |
300 | /**
301 | * 解码完成回调接口
302 | */
303 | public interface OnCompleteListener {
304 | void completed(ArrayList chunkPCMDataContainer);
305 | }
306 |
307 | /**
308 | * 设置转码完成监听器
309 | * @param onCompleteListener 监听器
310 | */
311 | public void setOnCompleteListener(OnCompleteListener onCompleteListener) {
312 | this.onCompleteListener = onCompleteListener;
313 | }
314 |
315 | private void showLog(String msg) {
316 | Log.e("AudioCodec", msg);
317 | }
318 | }
319 |
320 |
321 |
322 |
--------------------------------------------------------------------------------
/app/src/main/java/com/alvin/speechdemo/util/FucUtil.java:
--------------------------------------------------------------------------------
1 | package com.alvin.speechdemo.util;
2 |
3 | import android.content.Context;
4 | import android.media.AudioFormat;
5 | import android.media.AudioManager;
6 | import android.media.AudioRecord;
7 | import android.media.MediaRecorder;
8 |
9 | import java.io.InputStream;
10 |
11 | /**
12 | * 功能性函数扩展类
13 | */
14 | public class FucUtil {
15 |
16 | public static String readFile(Context mContext, String file, String code) {
17 | int len = 0;
18 | byte[] buf = null;
19 | String result = "";
20 | try {
21 | InputStream in = mContext.getClass().getClassLoader().getResourceAsStream("assets/"+file);
22 | len = in.available();
23 | buf = new byte[len];
24 | in.read(buf, 0, len);
25 |
26 | result = new String(buf, code);
27 | } catch (Exception e) {
28 | e.printStackTrace();
29 | }
30 | return result;
31 | }
32 |
33 | /**
34 | * 读取asset目录下音频文件。
35 | *
36 | * @return 二进制文件数据
37 | */
38 | public static byte[] readAudioFile(Context context, String filename) {
39 | try {
40 | InputStream ins = context.getAssets().open(filename);
41 | byte[] data = new byte[ins.available()];
42 |
43 | ins.read(data);
44 | ins.close();
45 |
46 | return data;
47 | } catch (Exception e) {
48 | // TODO Auto-generated catch block
49 | e.printStackTrace();
50 | }
51 |
52 | return null;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/alvin/speechdemo/util/JsonParser.java:
--------------------------------------------------------------------------------
1 | package com.alvin.speechdemo.util;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONObject;
5 | import org.json.JSONTokener;
6 |
7 | /**
8 | * Created by Administrator on 2016/10/18.
9 | */
10 |
11 | public class JsonParser {
12 | public static String parseIatResult(String json){
13 | StringBuilder ret = new StringBuilder();
14 | try{
15 | JSONTokener tokener = new JSONTokener(json);
16 | JSONObject jsonObject = new JSONObject(tokener);
17 | JSONArray words = jsonObject.getJSONArray("ws");
18 | int len = words.length();
19 | for (int i=0;i
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/push_fade_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/img_view_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/res/drawable-xhdpi/img_view_loading.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
21 |
22 |
26 |
27 |
32 |
33 |
41 |
42 |
53 |
54 |
62 |
63 |
71 |
72 |
76 |
77 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
18 |
19 |
27 |
28 |
39 |
50 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #ffbadef5
7 | #fffd7ba6
8 | #ff18b4ed
9 | #ffff1b66
10 | #80ff1b66
11 |
12 | #ffffffff
13 |
14 | #ff000000
15 |
16 | #ff808080
17 |
18 | #00000000
19 |
20 | #ffEF001D
21 |
22 | #ffffffff
23 |
24 | #ffffffff
25 |
26 | #ff18b4ed
27 | #ff87d6f3
28 |
29 |
30 |
31 | #ffE5E8EC
32 | #ff818181
33 | #ff939394
34 |
35 | #ffecedf1
36 | #fff8f8f8
37 | #ffD7D7D7
38 | #ff828282
39 | #ff2183f1
40 | #ffcecece
41 | #ff007aff
42 | #ffb4b4b4
43 | #ff18b4ed
44 |
45 | #ff18b4ed
46 | #ffdcdcdc
47 | #ff0079fe
48 | #ff7c7c7c
49 | #ff0079ff
50 | #00000000
51 | #7f000000
52 | #ff66ccff
53 | #ff000000
54 | #ffb2b2b2
55 | #ff646464
56 | #fff9f9f9
57 | #ffdedfe1
58 | #ff18b4ed
59 | #ff000000
60 | #d9ffffff
61 | #26ffffff
62 | #00ffffff
63 |
64 | #ff9ba09a
65 | #ff74d2f4
66 | #ff039dd5
67 | #ffe6e4e9
68 | #00000000
69 | #15000000
70 | #ff18b4ed
71 | #ff808080
72 | #ff797979
73 | #ff828282
74 | #ff454545
75 | #80000000
76 | #ff4cda64
77 | #ffffb446
78 | #ff6cd8ff
79 | #ffffedec
80 | #ffe6ffea
81 | #ffb7b7b7
82 | #7effffff
83 | #99ffffff
84 | #20ffffff
85 | #ff787878
86 | #ff9f9f9f
87 | #ff27B7ED
88 | #ffd3d3d3
89 | #ffdddddd
90 | #ffCFCFCF
91 | #ff36BAEE
92 | #ff909090
93 | #ff18b4ed
94 | #ff83d3f3
95 | #ffbabcc0
96 | #ffd9d9d9
97 | #ffcdcece
98 | #ff2c5466
99 | #ff53c7f1
100 | #ffd4d4d1
101 | #ffc62c27
102 | @color/WHITE
103 | #fffafafa
104 | #fffbeca3
105 | #fffbfbfb
106 | #ffb22622
107 | #ffd6d6d6
108 | #ff73adcf
109 | #ffe33c1c
110 | #ff924729
111 | @color/GRAY
112 | #fffde648
113 | @color/GRAY
114 | #ffb0b0b0
115 | #ffcd4833
116 | #ff989898
117 | #ffe23b1b
118 | #ffb32523
119 | #fff6af19
120 | #fff0c641
121 | @color/half_black
122 | #ffffb22e
123 | #ffa20403
124 | @color/link_friend
125 | #ffd93801
126 | #ffb2b0b1
127 | #ff787979
128 | #ffa54724
129 | #ffde4531
130 | #fff1d64b
131 | #ff71c9f1
132 | @color/GRAY
133 | @color/myinfo_botttom_divider
134 | #ffbf1c1c
135 | #ffe33b1e
136 | #ffb43330
137 | #ffe8aba9
138 | #ffcc817f
139 | #ffcf1009
140 | #ffce1109
141 | @color/GRAY
142 | #ff6798d9
143 | #ffe7e7e7
144 | #ffefefef
145 | #fff9f9f9
146 | #c0000000
147 | #ff37bef1
148 | #ff255898
149 | #ff3e3e3e
150 | #ff7b7b7b
151 | #fff3f3f5
152 | #ff255898
153 | #ff7a7a7a
154 | #ff902f00
155 | #fff7f7f7
156 | #ffecf6ff
157 | #ff1ab5eb
158 | #fffbecb5
159 | #ffa3b1ba
160 | #ff23b9ee
161 | #ffffc15a
162 | @color/wallet_text26
163 | #c6c8cd
164 | #40ffffff
165 | #90ffffff
166 | #ff1fb200
167 | #fffff0c7
168 | #ffffde00
169 | @color/wallet_text17
170 | #ffe0f6f6
171 | #ffc0c0c0
172 | #ffaeaeae
173 | @color/msg_bottom_bg
174 | #fff2f2f2
175 | #ff19b4ed
176 | #ff69c59c
177 | @color/workicon
178 | #76ffffff
179 | #40ffffff
180 | #ff8899a6
181 | #fffcfcfc
182 | #ffdedfe1
183 | #ff838385
184 | #aaffffff
185 | #ff808080
186 | #353535
187 | #40000000
188 | #fff9f9f9
189 | #ff808080
190 | #ff02cf00
191 | #ff18b4ec
192 | #ffbfbfbf
193 | #fffdfdfd
194 | #ffdddddd
195 | @color/center_bg
196 | #ffbb1811
197 | @color/shake_top
198 | #ff262a2d
199 | #ff505255
200 | #ffd1d1d1
201 | #ff404040
202 | #ffababab
203 | #ffebeeef
204 | #fff3fafd
205 | #ff0cb40f
206 | #ffff3b2f
207 | #ffc7c7cd
208 | #ffff3a30
209 | #ffff9c00
210 |
211 | #aa000000
212 | #ffdddddd
213 | #ff8e8e8e
214 | #ff17b6ed
215 | #ff333333
216 | #ffd4d4d4
217 | #ff18b2ed
218 | #ffff226f
219 | #ff7aa8bd
220 | #ffbcb597
221 | #ff1a1a1a
222 | #ff9bd3fe
223 | #ffe5e4ea
224 | #ff4cda64
225 | #ff8a8a8a
226 | #ffeb5b39
227 | #fff1fbfe
228 | #ffc62b28
229 | #ffffe0b7
230 | #ffca302d
231 | #fff84040
232 | #80f84040
233 | #ffcc4c49
234 | #ffff1b66
235 | #ffff8b0e
236 | #ffceebfa
237 | #ff96d7ee
238 | #ffc3e4fd
239 | #fffc6054
240 | #fffaaca6
241 | #ffebebeb
242 | #fff28c46
243 | #ff5c5c5c
244 | #ffeaeaea
245 | #ff78c446
246 | #fffc6358
247 | #ffff9c00
248 | #ff4b4b4b
249 | #ff18b4ed
250 | #ff4cda64
251 | #ffedf9fe
252 | #ffb7b7b5
253 | #fff5f5f5
254 | #ffededed
255 | #ffdddddd
256 | #ffe6e6e6
257 | #fff6e5a0
258 | #ff18b4ed
259 | #ff857fe9
260 | #ffc64344
261 | #ff8092a8
262 | #ffdedfe1
263 | #ff18b4ed
264 | #fff98a27
265 | #ffff3b30
266 | #ff53d769
267 | #ff3fd086
268 | #fffe7c1c
269 | #ff18b4ed
270 | #ffe66666
271 | #e5ffffff
272 | #8018b4ed
273 | #ff2b2b2b
274 | #ff232323
275 | #ff1e1e1e
276 | #ffe30000
277 | #ff009944
278 | #fffff100
279 | #ff18b4ed
280 | #ff2f3758
281 | #80808080
282 | #ff0060ac
283 | #ffc1c1c1
284 | #ffc7c7c7
285 | #ff80e9ff
286 |
287 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 58049cf2
3 | SpeechDemo
4 | 开始说话
5 | 上传词表
6 | 音频转文字
7 | 请开始说话…
8 | Sign in
9 |
10 |
11 | UserName
12 | Password
13 | Sign in or register
14 | Sign in
15 | clear
16 | This email address is invalid
17 | This password is too short
18 | This password is incorrect
19 | This field is required
20 | "Contacts permissions are needed for providing email
21 | completions."
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/alvin/speechdemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.alvin.speechdemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alvin3225/SpeechDemo/98584925e592f53a9846585fe3afc9fc09df5a7e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------