讯飞语音合成Wav,以及MediaPlayer的一些坑,SeekBar相关知识点
来源:互联网 发布:网络宣传怎么做 编辑:程序博客网 时间:2024/05/15 05:40
项目中遇到讯飞语音转成WAV,我是这样做的,首先生成.pcm文件,然后再.pcm与.wav互换,最终由MediaPlayer播放,还有进度条之类的小知识点
首先上布局
<?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:layout_width="match_parent" android:layout_height="100dp" android:id="@+id/edit"/><LinearLayout android:layout_marginBottom="15dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/play" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="播放" /> <Button android:id="@+id/pause" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="暂停" /></LinearLayout> <SeekBar android:id="@+id/sb" android:layout_width="fill_parent" android:layout_height="wrap_content" android:max="100" /></LinearLayout>
然后是.pcm与.WAV互换工具类
public class PcmToWavUtil { private int mBufferSize; //缓存的音频大小 private int mSampleRate = 8000;// 8000|16000 private int mChannel = AudioFormat.CHANNEL_IN_STEREO; //立体声 private int mEncoding = AudioFormat.ENCODING_PCM_16BIT; public PcmToWavUtil() { this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, mEncoding); } /** * @param sampleRate sample rate、采样率 * @param channel channel、声道 * @param encoding Audio data format、音频格式 */ public PcmToWavUtil(int sampleRate, int channel, int encoding) { this.mSampleRate = sampleRate; this.mChannel = channel; this.mEncoding = encoding; this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, mEncoding); } /** * pcm文件转wav文件 * * @param inFilename 源文件路径 * @param outFilename 目标文件路径 */ public void pcmToWav(String inFilename, String outFilename) { FileInputStream in; FileOutputStream out; long totalAudioLen; long totalDataLen; long longSampleRate = mSampleRate; int channels = 2; long byteRate = 16 * mSampleRate * channels / 8; byte[] data = new byte[mBufferSize]; try { in = new FileInputStream(inFilename); out = new FileOutputStream(outFilename); totalAudioLen = in.getChannel().size(); totalDataLen = totalAudioLen + 36; writeWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate); while (in.read(data) != -1) { out.write(data); } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 加入wav文件头 */ private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; // RIFF/WAVE header header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); header[8] = 'W'; //WAVE header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; // 'fmt ' chunk header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; // 4 bytes: size of 'fmt ' chunk header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; // format = 1 header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); header[32] = (byte) (2 * 16 / 8); // block align header[33] = 0; header[34] = 16; // bits per sample header[35] = 0; header[36] = 'd'; //data header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); out.write(header, 0, 44); }}
最后看大布局
public class Voice_Activity extends Activity { /** Called when the activity is first created. */ private Voice_BroadcaseUtil voice_broadcaseUtil; private EditText edit; private Context context=this; private ListView list; private Button play,pause,resume; private MediaPlayer mp; private SeekBar sb; private Handler handler=new Handler(); private int Duration; private String content; private PcmToWavUtil pcmToWavUtil = new PcmToWavUtil(); public Voice_Activity voice; private List<Voice_Data> voiceData = new ArrayList<>(); public static String SDPATH ="/sdcard/" ;//获取文件夹 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_voice_test); voice=new Voice_Activity(); initView(); initData(); voice_broadcaseUtil=new Voice_BroadcaseUtil(context); } private void initView() { edit=(EditText)findViewById(R.id.edit); play=(Button)findViewById(R.id.play); pause=(Button)findViewById(R.id.pause); sb=(SeekBar)findViewById(R.id.sb); mp = new MediaPlayer(); //找到相应View //后面的参数必须是URI形式的,所以要把相应路径转换成URI play.setOnClickListener(playlis); pause.setOnClickListener(pauselis); sb.setOnSeekBarChangeListener(sbLis); adapter=new GridAdapter(context,ar); list.setAdapter(adapter); testRandom1(); } public static void delFile(String fileName){ File file = new File(SDPATH + fileName); if(file.isFile()){ file.delete(); } file.exists(); } private OnClickListener playlis=new OnClickListener(){ @Override public void onClick(View v) { System.out.println(edit.getText().toString().length()); delFile("speak_result.pcm");//这两行一定要否则,一直都会读上一个文件的内容,导致刷新不及时,点的不是读的 delFile("speak_result.wav"); voice_broadcaseUtil.toVoiceStartSave(edit.getText().toString()); new Handler().postDelayed(new Runnable() { @Override public void run() { final String path = "/sdcard/speak_result.pcm" ; final String outpath = path.replace(".pcm", ".wav"); pcmToWavUtil.pcmToWav(path, outpath);//转换 Toast.makeText(context, "正在拉取资源。请稍后...", Toast.LENGTH_SHORT).show(); } },edit.getText().toString().length()*100); new Handler().postDelayed(new Runnable() { @Override public void run() { try { mp.reset();//这句很关键,没有这句会报状态异常错误,而且很难排查 mp.setDataSource(context, Uri.parse("/sdcard/speak_result.wav")); mp.prepare();//这句也很重要,没有这句无法正常播放 System.out.println("执行了啊"); } catch (IOException e) { e.printStackTrace(); } Duration=mp.getDuration();//时间 sb.setMax(Duration);//进度条最大时间 handler.post(start); Toast.makeText(context, "请稍后...", Toast.LENGTH_LONG).show(); } },edit.getText().toString().length()*100); //调用handler播放 } }; Runnable start=new Runnable(){ @Override public void run() { mp.start(); handler.post(updatesb); //用一个handler更新SeekBar } }; Runnable updatesb =new Runnable(){ @Override public void run() { sb.setProgress(mp.getCurrentPosition()); // sb.setProgress(); handler.postDelayed(updatesb, 100);//每100毫秒修改一次进度条 } }; private OnClickListener pauselis=new OnClickListener(){ @Override public void onClick(View v) { if(mp.isPlaying()){ mp.pause();//暂停播放 pause.setText("继续"); }else{ mp.start();//继续播放 pause.setText("暂停"); } } }; private OnSeekBarChangeListener sbLis=new OnSeekBarChangeListener(){ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub mp.seekTo(sb.getProgress()); //SeekBar确定位置后,跳到指定位置 } }; public void refresh() { onCreate(null); } private void showTip(String string){ Toast.makeText(context, string, Toast.LENGTH_SHORT).show(); }}
快进和快退
case R.id.next_up: System.out.println("快退"); mp.seekTo(mp.getCurrentPosition() - 5000); break; case R.id.next_down: mp.seekTo(mp.getCurrentPosition() + 5000);
上几张图
阅读全文
0 0
- 讯飞语音合成Wav,以及MediaPlayer的一些坑,SeekBar相关知识点
- 科大讯飞语音合成,pcm转wav
- 讯飞语音合成_2_功能测试以及demo解读
- Android 讯飞语音合成
- 讯飞语音合成方案
- 讯飞语音合成问题
- 科大讯飞语音合成的引入
- 科大讯飞语音合成的引入
- 讯飞语音合成实例1
- 讯飞语音合成实例2
- 讯飞语音合成小试
- 讯飞语音合成 简单使用
- 讯飞语音语音合成辅助类
- 讯飞语音合成_1_环境搭建
- 讯飞语音合成_3_java web实现
- 讯飞语音合成数字读法问题
- 讯飞语音合成后播放
- 讯飞语音之语音合成
- JUC集合---CopyOnWriteArraySet
- java8-[CompletableFuture]
- 使用storcli点亮服务器上的故障磁盘
- 物联网安全专家齐聚ICA联盟 多项IoT身份认证安全标准出炉
- SLIC超像素分割MATLAB代码执行时的一些细节
- 讯飞语音合成Wav,以及MediaPlayer的一些坑,SeekBar相关知识点
- 揭秘react生态体系
- django显示SQL语句
- JavaSe——6、String、StringBuffer、StringBuilder
- 多线程编程:线程同步
- hibernate的使用()
- qt中关于中文乱码的问题
- 【物联网安全】物联网安全主要的现有安全问题
- Java创建线程的方法和比较