Android讯飞语音集成【在线语音合成2】

前言:

语音合成:
与语音听写相反,语音合成是将一段文字转换为语音,可根据需要合成出不同音色、语速和语调的声音,让机器像人一样开口说话

效果图:
Android讯飞语音集成【在线语音合成2】_第1张图片
2、直接上代码,配置不再重复说明了:

、TTSActivity.java

public class TTSActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "TTSActivity";
    // 语音合成对象
    private SpeechSynthesizer mTts;
    // 默认发音人
    private String voicer = "xiaoyan";
    //云端发音人名称列表(中文)
    private String[] mCloudVoicersEntries;
    //云端发音人名称列表(英文简称)
    private String[] mCloudVoicersValue;
    //音频流名称列表
    private String[] mCloudVoicersName;
    // 缓冲进度
    private int mPercentForBuffering = 0;
    // 播放进度
    private int mPercentForPlaying = 0;
    // 引擎类型
    private String mEngineType = SpeechConstant.TYPE_CLOUD;
    private MemoryFile memFile;
    public volatile long mTotalSize = 0;
    private Vector container = new Vector<>();
    private TextView voice_value1, voice_value2, voice_value3, progress;
    private SeekBar seekBar1, seekBar2, seekBar3;
    private Button ttsBtnPersonType,ttsBtnPersonSelect;
    //起始值50
    private int voiceNumber1 = 50, voiceNumber2 = 50, voiceNumber3 = 50;
    //播报的文字
    private EditText ttsText;
    //音频流类型
    private String voiceName;
    private SpannableStringBuilder builder;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tts);
        //初始化控件
        findViewById(R.id.tts_play).setOnClickListener(this);
        findViewById(R.id.tts_cancel).setOnClickListener(this);
        findViewById(R.id.tts_pause).setOnClickListener(this);
        findViewById(R.id.tts_resume).setOnClickListener(this);
        voice_value1 = this.findViewById(R.id.voice_value1);
        voice_value2 = this.findViewById(R.id.voice_value2);
        voice_value3 = this.findViewById(R.id.voice_value3);
        seekBar1 = this.findViewById(R.id.seek_bar1);
        seekBar2 = this.findViewById(R.id.seek_bar2);
        seekBar3 = this.findViewById(R.id.seek_bar3);
        ttsText = this.findViewById(R.id.tts_text);
        progress = this.findViewById(R.id.progress);
        ttsBtnPersonType = this.findViewById(R.id.tts_btn_person_type);
        ttsBtnPersonSelect = this.findViewById(R.id.tts_btn_person_select);
        ttsBtnPersonType.setOnClickListener(this);
        ttsBtnPersonSelect.setOnClickListener(this);
        //seekbar滑动事件
        initSeekBarListener();

        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);
        mCloudVoicersEntries = getResources().getStringArray(R.array.voicer_cloud_entries);
        mCloudVoicersValue = getResources().getStringArray(R.array.voicer_cloud_values);
        mCloudVoicersName = getResources().getStringArray(R.array.stream_entries);
    }

    private void initSeekBarListener() {
        //语速
        seekBar1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                //进度发生改变时会触发
                voice_value1.setText("语速:" + i);
                voiceNumber1 = i;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //按住SeekBar时会触发
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //放开SeekBar时触发
            }
        });
        //音调
        seekBar2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                voice_value2.setText("音调:" + i);
                voiceNumber2 = i;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
        //音量
        seekBar3.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                voice_value3.setText("音量:" + i);
                voiceNumber3 = i;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }

    @Override
    public void onClick(View view) {
        if (null == mTts) {
            // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
            showToast("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
            return;
        }
        switch (view.getId()) {
            // 开始合成
            // 收到onCompleted 回调时,合成结束、生成合成音频
            // 合成的音频格式:只支持pcm格式
            case R.id.tts_play:
                //恢复背景色为白色
                setTextStyle(0, ttsText.getText().toString().length(), Color.WHITE);
                // 设置参数
                setParam();
                /**
                 * 只保存音频不进行播放接口,调用此接口请注释startSpeaking接口
                 * text:要合成的文本,uri:需要保存的音频全路径,listener:回调接口
                 */
                int code = mTts.startSpeaking(ttsText.getText().toString(), mTtsListener);
                //String path = Environment.getExternalStorageDirectory() + "/tts.pcm";
                //int code = mTts.synthesizeToUri(texts, path, mTtsListener);
                if (code != ErrorCode.SUCCESS) {
                    showToast("语音合成失败,错误码: " + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
                }
                break;
            // 取消合成
            case R.id.tts_cancel:
                //恢复背景色为白色
                setTextStyle(0, ttsText.getText().toString().length(), Color.WHITE);
                mTts.stopSpeaking();
                break;
            // 暂停播放
            case R.id.tts_pause:
                mTts.pauseSpeaking();
                break;
            // 继续播放
            case R.id.tts_resume:
                mTts.resumeSpeaking();
                break;
            // 选择发音人
            case R.id.tts_btn_person_select:
                showPresonSelectDialog();
                break;
            // 选择音频流类型
            case R.id.tts_btn_person_type:
                showVoiceSelectDialog();
                break;
        }
    }


    private int selectedNum = 0;
    private int selectedVoiceNum = 0;

    /**
     * 发音人选择。
     */
    private void showPresonSelectDialog() {
        new AlertDialog.Builder(this).setTitle("在线合成发音人选项")
                // 单选框有几项,各是什么名字
                .setSingleChoiceItems(mCloudVoicersEntries, selectedNum,
                        new DialogInterface.OnClickListener() { // 点击单选框后的处理
                            public void onClick(DialogInterface dialog, int which) { // 点击了哪一项
                                voicer = mCloudVoicersValue[which];
                                //凯瑟琳、亨利(阿森纳)、玛丽切换文本至英文
                                if ("catherine".equals(voicer) || "henry".equals(voicer) || "vimary".equals(voicer)) {
                                    ttsText.setText(R.string.text_tts_source_en);
                                } else {
                                    //其他中文
                                    ttsText.setText(R.string.text_tts_source);
                                }
                                ttsBtnPersonSelect.setText("发音人:"+mCloudVoicersEntries[which]);
                                selectedNum = which;
                                dialog.dismiss();
                            }
                        }).show();
    }

    /**
     * 音频流类型选择
     */
    private void showVoiceSelectDialog() {
        new AlertDialog.Builder(this).setTitle("在线合成发音人选项")
                // 单选框有几项,各是什么名字
                .setSingleChoiceItems(mCloudVoicersName, selectedVoiceNum,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                voiceName = mCloudVoicersName[which];
                                ttsBtnPersonType.setText("音频流类型:" + voiceName);
                                dialog.dismiss();
                            }
                        }).show();
    }

    /**
     * 初始化监听。
     */
    private InitListener mTtsInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            Log.e(TAG, "InitListener init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showToast("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
            } else {
                // 初始化成功,之后可以调用startSpeaking方法
                // 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,
                // 正确的做法是将onCreate中的startSpeaking调用移至这里
            }
        }
    };

    /**
     * 合成回调监听。
     */
    private SynthesizerListener mTtsListener = new SynthesizerListener() {
        @Override
        public void onSpeakBegin() {
            showToast("开始播放");
        }

        @Override
        public void onSpeakPaused() {
            showToast("暂停播放");
        }

        @Override
        public void onSpeakResumed() {
            showToast("继续播放");
        }

        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos, String info) {
            // 合成进度
            Log.e(TAG, "onBufferProgress percent =" + percent);
            //记录暂停时的进度
            mPercentForBuffering = percent;
            //缓冲与播放进度
            showToast(String.format(getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying));
        }

        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {
            // 播放进度
            Log.e(TAG, "onSpeakProgress percent =" + percent);
            mPercentForPlaying = percent;
            progress.setText("当前进度:" + percent + "%");
            setTextStyle(beginPos, endPos, Color.GREEN);
        }

        @Override
        public void onCompleted(SpeechError error) {
            if (error == null) {
                //showToast("播放完成");
                Log.e(TAG, "onCompleted: 播放完成" + container.size());
                try {
                    for (int i = 0; i < container.size(); i++) {
                        writeToFile(container.get(i));
                    }
                } catch (IOException e) {
                }
                //播放完成后保存至文件夹
                FileUtil.saveFile(memFile, mTotalSize, Environment.getExternalStorageDirectory() + "/helloword-Tts1.pcm");
            } else if (error != null) {
                showToast(error.getPlainDescription(true));
            }
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            //	 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            //	 若使用本地能力,会话id为null
            if (SpeechEvent.EVENT_SESSION_ID == eventType) {
                String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
                Log.e(TAG, "onEventid =" + sid);
            }
            //当设置SpeechConstant.TTS_DATA_NOTIFY为1时,抛出buf数据
            if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
                byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
                Log.e(TAG, "onEvent bufis =" + buf.length);
                container.add(buf);
            }
        }
    };

    /**
     * 设置文字背景色
     */
    private void setTextStyle(int beginPos, int endPos, int color) {
        builder = new SpannableStringBuilder(ttsText.getText());
        ///当前播放的文字背景设置为蓝色
        builder.setSpan(new BackgroundColorSpan(color), beginPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        ttsText.setText(builder);
        Log.e(TAG, "beginPos = " + beginPos + "  endPos = " + endPos);
    }

    /**
     * 参数设置
     */
    private void setParam() {
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);
        // 根据合成引擎设置相应参数
        if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
            mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
            //支持实时音频返回,仅在synthesizeToUri条件下支持
            mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY, "1");
            //	mTts.setParameter(SpeechConstant.TTS_BUFFER_TIME,"1");
            // 设置在线合成发音人
            mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);
            //设置合成语速(String 类型)
            mTts.setParameter(SpeechConstant.SPEED, voiceNumber1 + "");
            //设置合成音调
            mTts.setParameter(SpeechConstant.PITCH, voiceNumber2 + "");
            //设置合成音量
            mTts.setParameter(SpeechConstant.VOLUME, voiceNumber3 + "");
        } else {
            mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
            mTts.setParameter(SpeechConstant.VOICE_NAME, "");
        }
        //设置播放器音频流类型
        mTts.setParameter(SpeechConstant.STREAM_TYPE, voiceName);
        // 设置播放合成音频打断音乐播放,默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "false");

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/helloword-Tts2.wav");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mTts) {
            mTts.stopSpeaking();
            // 退出时释放连接
            mTts.destroy();
        }
    }

    @Override
    protected void onResume() {
        //移动数据统计分析
		/*FlowerCollector.onResume(TtsDemo.this);
		FlowerCollector.onPageStart(TAG);*/
        super.onResume();
    }

    @Override
    protected void onPause() {
        //移动数据统计分析
		/*FlowerCollector.onPageEnd(TAG);
		FlowerCollector.onPause(TtsDemo.this);*/
        super.onPause();
    }

    private void writeToFile(byte[] data) throws IOException {
        if (data == null || data.length == 0)
            return;
        try {
            if (memFile == null) {
                Log.e(TAG, "writeToFile: 写入文件夹");
                String mFilepath = Environment.getExternalStorageDirectory() + "/helloword-Tts1.pcm";
                memFile = new MemoryFile(mFilepath, 1920000);
                memFile.allowPurging(false);
            }
            memFile.writeBytes(data, 0, (int) mTotalSize, data.length);
            mTotalSize += data.length;
        } finally {
        }
    }

    /**
     * 展示吐司
     */
    private void showToast(final String str) {
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
    }

}

、对应布局文件activity_tts.xml:




    

    

    

        

        
    

    

        

        
    

    

        

        
    

    

    

    

        

、app\src\main\res\values\strings.xml添加:

 
        小燕—女青、中英、普通话
        小宇—男青、中英、普通话
        凯瑟琳—女青、英
        亨利—男青、英
        玛丽—女青、英
        小研—女青、中英、普通话
        小琪—女青、中英、普通话
        小峰—男青、中英、普通话
        小梅—女青、中英、粤语
        小莉—女青、中英、台湾普通话
        小蓉—女青、中、四川话
        小芸—女青、中、东北话
        小坤—男青、中、河南话
        小强—男青、中、湖南话
        小莹—女青、中、陕西话
        小新—男童、中、普通话
        楠楠—女童、中、普通话
        老孙—男老、中、普通话
    
    
        xiaoyan
        xiaoyu
        catherine
        henry
        vimary
        vixy
        xiaoqi
        vixf
        xiaomei
        xiaolin
        xiaorong
        xiaoqian
        xiaokun
        xiaoqiang
        vixying
        xiaoxin
        nannan
        vils
    
    
        通话
        系统
        铃声
        音乐
        闹铃
        通知
    

    缓冲进度为%d%%,播放进度为%d%%
    iFLYTEK is a national key software enterprise dedicated to the research of intelligent speech and language technologies, development of software and chip products, provision of speech information services, and integration of E-government systems. The intelligent speech technology of iFLYTEK, the core technology of the company, represents the top level in the world.
    科大讯飞作为中国最大的智能语音技术提供商,在智能语音技术领域有着长期的研究积累,并在中文语音合成、语音识别、口语评测等多项技术上拥有国际领先的成果。科大讯飞是我国唯一以语音技术为产业化方向的“国家863计划成果产业化基地”…

关于离线合成功能貌似要收费:
Android讯飞语音集成【在线语音合成2】_第2张图片

你可能感兴趣的:(安卓开发)