Android实现伴奏录音合成MP3
本文实例为大家分享了Android实现伴奏录音合成MP3的具体代码,供大家参考,具体内容如下
基本实现思路如下:
1.利用android自带的录音类(AudioRecord)实现录音.
/** *播放伴奏 */ privateMediaPlayerplayer; /** *返回按钮 */ privateImageViewbtnBack; /** *切换歌曲 */ privateButtonbtnSwitchSong; /** *伴唱时长 */ privateTextViewtv_recod_time; /** *歌词VIEW */ privateLyricViewlv_lyric; /** *开始录制 */ privateButtonbtnPlay; /** *标题 */ privateTextViewivTitle; privatebooleancanPlay=true; privatebooleanisPause=false; /*** *背景音乐模式 */ privateBackgroudMusicModemode=BackgroudMusicMode.Accompany; /** *歌曲id */ privateStringsongId; /** *歌曲名称 */ privateStringsongName; /** *歌手名字 */ privateStringsingerName; /** *伴奏文件 */ privateFilefile; /** *是否正在录制 */ privatebooleanisStart=false; /** *录音状态 */ privatebooleanstarting=false; /** *伴奏时间 */ privateintbztimetmp=0; /** *伴奏时间 */ privateStringbztime=""; /** *录制时间 */ privateintrecordTimeLength=0; /** *更新伴奏时间 */ privateRecordTaskrt=null; /** *录制频率,单位hz.这里的值注意了,写的不好,可能实例化AudioRecord对象的时候,会出错。我开始写成11025就不行。这取决于硬件设备 *设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025 */ privateintsampleRateInHz=44100; /** *设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道 */ privateintchannelConfig=AudioFormat.CHANNEL_CONFIGURATION_MONO; /** *音频数据格式:PCM16位每个样本。保证设备支持。PCM8位每个样本。不一定能得到设备支持。 */ privateintaudioFormat=AudioFormat.ENCODING_PCM_16BIT; /** *调整播放音量 */ privateAudioManageraudioManager; /** *最大音量 */ privateintmaxVolume=0; /** *当前音量 */ privateintcurrentVolume=0; /** *AudioRecord写入缓冲区大小 */ protectedintm_in_buf_size; /** *录制音频对象 */ privateAudioRecordmRecorder; /** *录入的字节数组 */ privatebyte[]m_in_bytes; /** *存放录入字节数组的大小 */ privateLinkedListm_in_q; /** *AudioTrack播放缓冲大小 */ privateintm_out_buf_size; /** *播放音频对象 */ privateAudioTrackmAudioTrack; /** *播放的字节数组 */ privatebyte[]m_out_bytes; /** *录制音频线程 */ privateThreadrecord; /** *播放音频线程 */ privateThreadplay; /** *让线程停止的标志 */ privatebooleanflag=true; /** *是否启动回声 */ privatebooleanroom_flag=true; /***上面有个播放歌词的组件 /*** *初始化 */ privatevoidinit(){ audioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE); maxVolume=audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); currentVolume=audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); registerHeadsetPlugReceiver(); ycApplication=(YueChangApplication)getApplication(); coverDao=newCoverDao(getApplicationContext()); Bundlebundle=getIntent().getExtras(); songId=bundle.getString("songId"); songName=bundle.getString("songName"); singerName=bundle.getString("singerName"); if(songId!=null){ //AudioRecord得到录制最小缓冲区的大小 m_in_buf_size=AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig,audioFormat); //实例化播放音频对象 mRecorder=newAudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,channelConfig,audioFormat, m_in_buf_size); //实例化一个字节数组,长度为最小缓冲区的长度 m_in_bytes=newbyte[m_in_buf_size]; //实例化一个链表,用来存放字节组数 m_in_q=newLinkedList (); //AudioTrack得到播放最小缓冲区的大小 m_out_buf_size=AudioTrack.getMinBufferSize(sampleRateInHz,channelConfig,audioFormat); //实例化播放音频对象 mAudioTrack=newAudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,channelConfig,audioFormat, m_out_buf_size,AudioTrack.MODE_STREAM); //实例化一个长度为播放最小缓冲大小的字节数组 m_out_bytes=newbyte[m_out_buf_size]; record=newThread(newrecordSound()); //if(ycApplication.isHeadsetplug()){ //}else{ //m_out_trk=newAudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,channelConfig,audioFormat, //m_out_buf_size,AudioTrack.MODE_STREAM); //} } } /** * *类描述:录音线程 * *@version1.0 */ classrecordSoundimplementsRunnable{ @Override publicvoidrun(){ //初始化输出流 DataOutputStreamdos=null; try{ FileaudioFile=newFile(SongUtil.getRecordSingPCMPath(songId)); //初始化输出流 dos=newDataOutputStream(newBufferedOutputStream(newFileOutputStream(audioFile))); byte[]bytes_pkg; if(mRecorder.getState()==AudioRecord.STATE_UNINITIALIZED){ //实例化播放音频对象 mRecorder=newAudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,channelConfig, audioFormat,m_in_buf_size); } //开始录音 mRecorder.startRecording(); while(flag){ intsize=mRecorder.read(m_in_bytes,0,m_in_buf_size); bytes_pkg=m_in_bytes.clone(); if(m_in_q.size()>=2){ m_in_q.removeFirst(); } m_in_q.add(bytes_pkg); if((ycApplication.isHeadsetplug()&&ycApplication.isOpenInEarphone()) ||(!ycApplication.isHeadsetplug()&&ycApplication.isOpenInSpeaker())){ //Log.d(SingSingleActivity.this.getClass().getName(),"启动录音播放1"); if(play==null||!room_flag){ //Log.d(SingSingleActivity.this.getClass().getName(),"启动录音播放2"); room_flag=true; play=newThread(newplayRecord()); //启动播放线程 play.start(); } }else{ if(room_flag||play!=null){ //Log.d(SingSingleActivity.this.getClass().getName(),"关闭录音播放1"); room_flag=false; if(play!=null){ play.interrupt(); } play=null; } } //写入PCM文件 dos.write(bytes_pkg,0,size); dos.flush(); } }catch(Exceptione){ //TODO:handleexception e.printStackTrace(); }finally{ try{ //关闭录音 if(mRecorder!=null){ try{ if(mRecorder.getState()==AudioRecord.STATE_INITIALIZED){ //关闭录音 mRecorder.stop(); mRecorder.release(); } }catch(Exceptione2){ //TODO:handleexception } } if(dos!=null){ dos.close(); } }catch(Exceptione2){ //TODO:handleexception e2.printStackTrace(); } } } }
2.录音完成后,调用开源工具(Mad)实现PCM合成输出到MP3文件.
主要调用的合成方法:
/*** *方法描述:本地方法调用JNI合并mp3PCM与sourcePCM *@paramsourcePCM *@parammp3PCM *@parammixPCM *@return */ publicstaticnativeintmix2PCMToPCM(StringsourcePCM,Stringmp3PCM,StringmixPCM); StringrecordPCMPath=SongUtil.getRecordSingPCMPath(songId);//录音生成的PCM文件 StringaccompanyPCMPath=SongUtil.getAccompanySongPCMPath(songId);//伴奏解码生成的PCM文件 StringmixPCMPath=SongUtil.getMixSingPCMPath(songId);//合成后的PCM文件 StringmixMP3Path=SongUtil.getMixSingMp3Path(songId);//合成后的MP3文件 //混音 intcode=SongEncodeUtil.mix2PCMToPCM(recordPCMPath,accompanyPCMPath,mixPCMPath); if(code==0){ //转换混合后音频格式TOmp3 inti=SimpleLame.convert(mixPCMPath,mixMP3Path,m_in_buf_size); Log.i(SingSingleActivity.this.getClass().getName(),"转换"+i+"混音完成"); saveMp3File(mixMP3Path); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。