讯飞语音合成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);

上几张图
这里写图片描述

原创粉丝点击