当前位置: 移动技术网 > IT编程>移动开发>Android > Android实现伴奏录音合成MP3

Android实现伴奏录音合成MP3

2019年07月30日  | 移动技术网IT编程  | 我要评论

刁一妾,网游之盟约天下,粉色房间

本文实例为大家分享了android实现伴奏录音合成mp3的具体代码,供大家参考,具体内容如下

基本实现思路如下:

1.利用android自带的录音类(audiorecord)实现录音.

 /**
  * 播放伴奏
  */
 private mediaplayer player;
 /**
  * 返回按钮
  */
 private imageview btnback;
 /**
  * 切换歌曲
  */
 private button btnswitchsong;
 /**
  * 伴唱时长
  */
 private textview tv_recod_time;
 /**
  * 歌词view
  */
 private lyricview lv_lyric;
 /**
  * 开始录制
  */
 private button btnplay;
 /**
  * 标题
  */
 private textview ivtitle;
 private boolean canplay = true;
 private boolean ispause = false;
 
 /***
  * 背景音乐模式
  */
 private backgroudmusicmode mode = backgroudmusicmode.accompany;
 /**
  * 歌曲id
  */
 private string songid;
 /**
  * 歌曲名称
  */
 private string songname;
 /**
  * 歌手名字
  */
 private string singername;
 /**
  * 伴奏文件
  */
 private file file;
 /**
  * 是否正在录制
  */
 private boolean isstart = false;
 /**
  * 录音状态
  */
 private boolean starting = false;
 /**
  * 伴奏时间
  */
 private int bztimetmp = 0;
 /**
  * 伴奏时间
  */
 private string bztime = "";
 
 /**
  * 录制时间
  */
 private int recordtimelength=0;
 /**
  * 更新伴奏时间
  */
 private recordtask rt = null;
 
 /**
  * 录制频率,单位hz.这里的值注意了,写的不好,可能实例化audiorecord对象的时候,会出错。我开始写成11025就不行。这取决于硬件设备
  * 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
  */
 private int samplerateinhz = 44100;
 /**
  * 设置音频的录制的声道channel_in_stereo为双声道,channel_configuration_mono为单声道
  */
 private int channelconfig = audioformat.channel_configuration_mono;
 
 /**
  * 音频数据格式:pcm 16位每个样本。保证设备支持。pcm 8位每个样本。不一定能得到设备支持。
  */
 private int audioformat = audioformat.encoding_pcm_16bit;
 
 /**
  * 调整播放音量
  */
 private audiomanager audiomanager;
 
 /**
  * 最大音量
  */
 private int maxvolume = 0;
 
 /**
  * 当前音量
  */
 private int currentvolume = 0;
 
 /**
  * audiorecord 写入缓冲区大小
  */
 protected int m_in_buf_size;
 /**
  * 录制音频对象
  */
 private audiorecord mrecorder;
 /**
  * 录入的字节数组
  */
 private byte[] m_in_bytes;
 /**
  * 存放录入字节数组的大小
  */
 private linkedlist<byte[]> m_in_q;
 /**
  * audiotrack 播放缓冲大小
  */
 private int m_out_buf_size;
 /**
  * 播放音频对象
  */
 private audiotrack maudiotrack;
 /**
  * 播放的字节数组
  */
 private byte[] m_out_bytes;
 /**
  * 录制音频线程
  */
 private thread record;
 /**
  * 播放音频线程
  */
 private thread play;
 /**
  * 让线程停止的标志
  */
 private boolean flag = true;
 /**
  * 是否启动回声
  */
 private boolean room_flag = true;
 
 /***上面有个播放歌词的组件
  /***
  * 初始化
  */
 private void init() {
  
  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 = new coverdao(getapplicationcontext());
  bundle bundle = 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 = new audiorecord(mediarecorder.audiosource.mic, samplerateinhz, channelconfig, audioformat,
     m_in_buf_size);
   // 实例化一个字节数组,长度为最小缓冲区的长度
   m_in_bytes = new byte[m_in_buf_size];
   // 实例化一个链表,用来存放字节组数
   m_in_q = new linkedlist<byte[]>();
 
   // audiotrack 得到播放最小缓冲区的大小
   m_out_buf_size = audiotrack.getminbuffersize(samplerateinhz, channelconfig, audioformat);
   // 实例化播放音频对象
   maudiotrack = new audiotrack(audiomanager.stream_music, samplerateinhz, channelconfig, audioformat,
     m_out_buf_size, audiotrack.mode_stream);
   // 实例化一个长度为播放最小缓冲大小的字节数组
   m_out_bytes = new byte[m_out_buf_size];
   record = new thread(new recordsound());
   
//   if(ycapplication.isheadsetplug()){
    
//   }else{
//    m_out_trk = new audiotrack(audiomanager.stream_music, samplerateinhz, channelconfig, audioformat,
//      m_out_buf_size, audiotrack.mode_stream);
//   }
   
 
  }
 }
 
  /**
  *
  * 类描述:录音线程 
  *
  * @version 1.0
  */
 class recordsound implements runnable {
  @override
  public void run() {
   // 初始化输出流
   dataoutputstream dos = null;
   try {
    file audiofile = new file(songutil.getrecordsingpcmpath(songid));
    // 初始化输出流
    dos = new dataoutputstream(new bufferedoutputstream(new fileoutputstream(audiofile)));
    byte[] bytes_pkg;
    if (mrecorder.getstate() == audiorecord.state_uninitialized) {
     // 实例化播放音频对象
     mrecorder = new audiorecord(mediarecorder.audiosource.mic, samplerateinhz, channelconfig,
       audioformat, m_in_buf_size);
    }
 
    // 开始录音
    mrecorder.startrecording();
    while (flag) {
     int size = 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 = new thread(new playrecord());
       // 启动播放线程
       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 (exception e) {
    // todo: handle exception
    e.printstacktrace();
   } finally {
    try {
     // 关闭录音
     if (mrecorder != null) {
      try {
       if (mrecorder.getstate() == audiorecord.state_initialized) {
        // 关闭录音
        mrecorder.stop();
        mrecorder.release();
       }
      } catch (exception e2) {
       // todo: handle exception
      }
     }
     if (dos != null) {
      dos.close();
     }
    } catch (exception e2) {
     // todo: handle exception
     e2.printstacktrace();
    }
   }
 
  }
 }

2.录音完成后,调用开源工具(mad)实现pcm合成输出到mp3文件.

主要调用的合成方法:

/***
 * 方法描述:本地方法调用jni合并mp3pcm与sourcepcm
 * @param sourcepcm
 * @param mp3pcm
 * @param mixpcm
 * @return
 */
 public static native int mix2pcmtopcm(string sourcepcm, string mp3pcm, string mixpcm);
 
 string recordpcmpath = songutil.getrecordsingpcmpath(songid); //录音生成的pcm文件
      string accompanypcmpath = songutil.getaccompanysongpcmpath(songid); //伴奏解码生成的pcm文件
      string mixpcmpath = songutil.getmixsingpcmpath(songid); //合成后的pcm文件
      string mixmp3path = songutil.getmixsingmp3path(songid); //合成后的mp3文件
      // 混音
      int code = songencodeutil.mix2pcmtopcm(recordpcmpath, accompanypcmpath, mixpcmpath);
      if (code == 0) {
       // 转换混合后音频格式 to mp3
       int i = simplelame.convert(mixpcmpath, mixmp3path, m_in_buf_size);
       log.i(singsingleactivity.this.getclass().getname(), "转换" + i + "混音完成");
       savemp3file(mixmp3path);
      }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网