一. 简单介绍
在上一篇里
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篇 ”