Android TTS学习——保存对你的喜欢
一.?简单介绍
在上一篇里
http://blog.csdn.net/ichliebephone/archive/2010/08/13/5810370.aspx
我们介绍了TTS提供的接口?OnUtteranceCompletedListener?的使用,这个接口的作用是监听语音片段的朗读,并在语音片段朗读结束后调用其定义的回调函数,在回调函数里可以进行需要的操作。
在这一篇里我们介绍一下TTS提供的另一个有用的功能,把合成的语音以音频文件的形式保存在系统里,然后就可以直接用播放音频文件的方式来播放。
这个功能调用的函数为:
public?int??synthesizeToFile?(?String??text,??HashMap?<?String?,??String?>?params,?String??filename)
第一个参数为要进行语音合成的文本;第二个参数我们在上一个Demo中有所介绍,是一个键值对形式的HashMap类型变量,可以设置语音片段的ID等;第三个参数为保存到系统中的文件名。
当你想和朋友分享一份精彩的文本合成语音后的效果时,你可以使用这个功能把它保存为音频文件发送给朋友,这样即使朋友的手机不具备TTS功能,也可以用播放音频的方式分享到;当你要对同一段较长的文本多次进行语音合成时,你可以把这段文本的语音保存为音频文件,然后使用时播放,这样会更省资源,运行速度更快,因为使用TTS是比较费资源的一个过程。因此我们会在某些场合用到这个功能。
下面我们就用这个功能完成一个Demo例子,当你害羞当面向她表白你对她的喜欢时,让Android帮你语音合成你想说的话,然后你就可以向她发送保存了对她喜欢的这个音频文件。
二.?实例开发
?
我们希望做的效果如下:
?
图1?实现效果图
?
第一个文本框里可以输入需要语音合成的文本,第二个文本框里输入要保存成的音频文件的文件名,点击第一个Speak?按钮你可以预听一下TTS?语音合成的效果,点击第二个Record?按钮,就会以音频文件的形式保存,然后就可以点击第三个Play?按钮播放保存的这个音频文件。
创建一个Android?工程,工程名为AndroidTTSDemoFourth?,其中SDK?版本需选择1.6?及以上。
其中Main.xml?文件很简单,如下所示:
?
- <?xml?version="1.0"?encoding="utf-8"?>??
- <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????android:orientation="vertical"??
- ????android:layout_width="fill_parent"??
- ????android:layout_height="fill_parent"??
- ????>??
- ????<EditText?android:id="@+id/inputText"???
- ????????????????android:hint="Input?the?text?here!"???
- ????????????????android:layout_width="fill_parent"???
- ????????????????android:layout_height="wrap_content">??
- ????????????????</EditText>??
- ????<Button?android:text="Speak"???
- ????????????????android:id="@+id/speakBtn"???
- ????????????????android:layout_width="wrap_content"???
- ????????????????android:layout_height="wrap_content"??
- ????????????????android:layout_gravity="center_horizontal"??
- ????????????????android:enabled="false"??
- ????????????????></Button>??
- ????<TextView?android:id="@+id/filenameLabel"??
- ????????????????android:text="Save?as:"??
- ????????????????android:layout_width="fill_parent"???
- ????????????????android:layout_height="wrap_content"??????????????????
- ????????????????></TextView>?????
- ????<EditText?android:id="@+id/filenameText"??
- ????????????????android:hint="Input?the?saving?file?name?here!"??
- ????????????????android:layout_width="fill_parent"???
- ????????????????android:layout_height="wrap_content">??????????????????
- ????????????????></EditText>??
- ????<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????????????????????android:orientation="horizontal"??
- ????????????????????android:layout_width="fill_parent"??
- ????????????????????android:layout_height="fill_parent"??
- ????????????????????android:gravity="center_horizontal"??
- ????????????????????>??
- ????????<Button?android:id="@+id/recordBtn"??
- ????????????????????android:text="Record"??
- ????????????????????android:layout_width="wrap_content"???
- ????????????????????android:layout_height="wrap_content"??
- ????????????????????></Button>??
- ????????<Button?android:id="@+id/playBtn"??
- ????????????????????android:text="Play"??
- ????????????????????android:layout_width="wrap_content"???
- ????????????????????android:layout_height="wrap_content"??
- ????????????????????android:enabled="false"??
- ????????????????????></Button>??
- ????</LinearLayout>?????????????????????????????
- </LinearLayout>??
?
?
Java?文件的编写:
有了前面这些Demo?的实例开发,这个Demo?实现起来就比较简单了,程序的代码如下所示:
?
- public?class?AndroidTTSDemoFourth?extends?Activity?implements?OnInitListener{??
- ????//实现初始接口??
- ????/**?Called?when?the?activity?is?first?created.?*/??
- ????//定义变量??
- ????private?EditText?inputText?=?null;??
- ????private?Button?speakBtn?=?null;??
- ????private?EditText?filenameText?=?null;??
- ????private?Button?recordBtn?=?null;??
- ????private?Button?playBtn?=?null;??
- ????private?TextToSpeech?mTts;??
- ????private?static?final?String?TAG?=?"TTS?Demo";??
- ????private?static?final?String?loveConfession?=?"jia?jia,?I?love?you.?";??
- ????private?String?loveFileName?=?null;??
- ????private?File?loveFile?=?null;??
- ????private?MediaPlayer?player?=?null;??
- ??????
- ????@Override??
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????????super.onCreate(savedInstanceState);??
- ????????setContentView(R.layout.main);??
- ????????//创建TextToSpeech实例,初始化完成后会调用OnInitListener(第二个参数)的回调函数??
- ????????mTts?=?new?TextToSpeech(this,??
- ????????????????this??//?TextToSpeech.OnInitListener??
- ????????????????);??
- ????????//设置控件??
- ????????inputText?=?(EditText)findViewById(R.id.inputText);??
- ????????speakBtn?=?(Button)findViewById(R.id.speakBtn);??
- ????????filenameText?=?(EditText)findViewById(R.id.filenameText);??
- ????????recordBtn?=?(Button)findViewById(R.id.recordBtn);??
- ????????playBtn?=?(Button)findViewById(R.id.playBtn);??
- ????????????????
- ????????inputText.setText(loveConfession);????
- ????????filenameText.setText("/sdcard/love.wav");??
- ????????speakBtn.setOnClickListener(new?OnClickListener()?{???????
- ????????????public?void?onClick(View?v)?{??
- ????????????????//?TODO?Auto-generated?method?stub??
- ????????????????//朗读输入框里的内容??
- ????????????????mTts.speak(inputText.getText().toString(),?TextToSpeech.QUEUE_ADD,?null);??
- ????????????}??
- ????????});??
- ????????recordBtn.setOnClickListener(new?OnClickListener()?{??????????????
- ????????????@Override??
- ????????????public?void?onClick(View?v)?{??
- ????????????????//?TODO?Auto-generated?method?stub??
- ????????????????//把TTS语音合成的结果保存为音频文件??
- ????????????????loveFileName?=?filenameText.getText().toString();??
- ????????????????loveFile?=?new?File(loveFileName);??
- ????????????????if(loveFile.exists())??
- ????????????????{??
- ????????????????????loveFile.delete();??
- ????????????????}??
- ????????????????//把语音合成的结果保存到文件中??
- ????????????????if(TextToSpeech.SUCCESS?==?mTts.synthesizeToFile(inputText.getText().toString(),?null,?loveFileName))??
- ????????????????{??
- ????????????????????Toast.makeText(getBaseContext(),?"sound?file?created!",?Toast.LENGTH_SHORT).show();??
- ????????????????????playBtn.setEnabled(true);??
- ????????????????}??
- ????????????????else??
- ????????????????{??
- ????????????????????Toast.makeText(getBaseContext(),?"failed?to?create?sound?file!",?Toast.LENGTH_SHORT).show();??
- ????????????????}??
- ????????????}??
- ????????});??
- ????????playBtn.setOnClickListener(new?OnClickListener()?{????????????
- ????????????@Override??
- ????????????public?void?onClick(View?v)?{??
- ????????????????//?TODO?Auto-generated?method?stub??
- ????????????????//播放保存着的音频文件??
- ????????????????try??
- ????????????????{??
- ????????????????????player?=?new?MediaPlayer();??
- ????????????????????player.setDataSource(loveFileName);??
- ????????????????????player.prepare();??
- ????????????????????player.start();??
- ????????????????}??
- ????????????????catch?(Exception?e)?{??
- ????????????????????//?TODO:?handle?exception??
- ????????????????????Toast.makeText(getBaseContext(),?"failed?to?play?sound?file!",?Toast.LENGTH_SHORT).show();??
- ????????????????????e.printStackTrace();??
- ????????????????}??
- ????????????}??
- ????????});??
- ????}??
- ??????
- ????public?void?onInit(int?status)?{??
- ????????//?TODO?Auto-generated?method?stub??
- ????????//TTS?Engine初始化完成??
- ????????if(status?==?TextToSpeech.SUCCESS)??
- ????????{??
- ????????????int?result?=?mTts.setLanguage(Locale.US);??
- ????????????//设置发音语言??
- ????????????if(result?==?TextToSpeech.LANG_MISSING_DATA?||?result?==?TextToSpeech.LANG_NOT_SUPPORTED)??
- ????????????//判断语言是否可用??
- ????????????{??
- ????????????????Log.v(TAG,?"Language?is?not?available");??
- ????????????????speakBtn.setEnabled(false);??
- ????????????}??
- ????????????else??
- ????????????{??
- ????????????????speakBtn.setEnabled(true);??
- ????????????}??
- ????????}??
- ????}??
- ??????
- ????@Override??
- ????protected?void?onDestroy()?{??
- ????????//?TODO?Auto-generated?method?stub??
- ????????//释放TTS的资源??
- ????????if(mTts?!=?null)??
- ????????{??
- ????????????mTts.stop();??
- ????????????mTts.shutdown();??
- ????????}?????
- ????????super.onDestroy();??
- ????}??
- }??
?
?
和TTS?相关的新的部分为recordBtn?的onClick?事件的处理,先根据指定的文件名创建一个File?变量,来判断文件是否已经存在,如果已存在就先删除。然后调用函数
mTts?.synthesizeToFile(?inputText?.getText().toString(),?null?,?loveFileName?)
把文本框中的内容语音合成后保存到文件中。
另一个playBtn?的onClick?事件的处理,主要就是创建一个MediaPlayer?实例,播放上一步保存的音频文件。
?
至此,这个Demo?就完成了,但是在运行前,需创建一个带SD?卡的AVD?,因为要往SD?卡上保存文件,如下所示:
图2?必须创建带SD?卡的AVD
?
同时还需在AndroidManifest.xml?文件中添加写外部存储设备的权限:
<?uses-permission?android:name?=?"android.permission.WRITE_EXTERNAL_STORAGE"?></uses-permission?>
接着就可以运行这个Demo?了,运行程序后在Eclipse?中切换到DDMS?视图,接着选择查看File Explorer?,我们看到在没有点击程序的Record?按钮进行语音合成到文件保存时,sdcard?目录下没有额外的文件,如下图所示:
?
图3?原始的SD?卡目录
?
?
然后我们在程序中点击Record?按钮,让TTS?把语音合成到文件,合成成功的话会弹出“sound file created!?”的提示,并且Play?按钮变成可用。点击Play?按钮就会播放刚刚保存的音频文件,和点击第一个的Speak?按钮朗读的内容是一样的。这时,我们再来查看下SD?卡的目录,会发现多了一个文件:love.wav?,正是我们设定保存的文件名,如下图所示:
?
图4?语音合成到文件后的SD?卡目录
?
?
并且,我们还可以使用adb pull?命令把这个文件从SD?卡上提取出来,在CMD?窗口中运行adb pull ./sdcard/love.wav?就可以把SD?卡上的这个音频文件保存的当前目录下,如下图所示:
?
图5?提取SD?卡上保存的音频文件
最后,也可以在电脑上播放记录了你对她的喜欢的这个音频文件了,或者也可以把这个文件发送给你喜欢的她。
?
注:文章参加“?首届Google暑期大学生博客分享大赛——2010 Andriod篇”