package com.sinata.xqmuse.utils;
|
|
import android.content.Context;
|
import android.media.AudioManager;
|
import android.media.MediaPlayer;
|
import android.media.MediaRecorder;
|
import android.net.Uri;
|
import android.os.Environment;
|
import android.os.Handler;
|
import android.util.Log;
|
|
import com.google.android.exoplayer2.ExoPlayer;
|
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.PlaybackException;
|
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.source.MediaSource;
|
import com.sinata.xqmuse.utils.exo.ExoMediaPlayer;
|
import com.sinata.xqmuse.utils.exo.ExoMediaPlayerFactory;
|
|
import java.io.File;
|
import java.io.IOException;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
import xyz.doikki.videoplayer.player.AbstractPlayer;
|
|
public class AudioUtils {
|
|
//文件路径
|
private String filePath;
|
//文件夹路径
|
private String FolderPath;
|
|
private MediaRecorder mMediaRecorder;
|
private final String TAG = "fan";
|
public static final int MAX_LENGTH = 1000 * 600;// 最大录音时长十分钟,实际行程设置为5分钟上传一次
|
|
private OnAudioStatusUpdateListener audioStatusUpdateListener;
|
private SimpleExoPlayer mMediaPlayer;
|
|
private float volume = 0.5f; //播放音量
|
|
private String audio = "";//音源
|
|
private boolean isPause = false; //是否暂停,解决循环播放时资源文件prepare异步产生的暂停失败问题
|
|
/**
|
* 文件存储默认sdcard/record
|
*/
|
public AudioUtils() {
|
//默认保存路径为/sdcard/record/下
|
this(Environment.getExternalStorageDirectory() + "/record/");
|
}
|
|
public AudioUtils(String filePath) {
|
|
File path = new File(filePath);
|
if (!path.exists())
|
path.mkdirs();
|
|
this.FolderPath = filePath;
|
}
|
|
private long startTime;
|
private long endTime;
|
|
|
/**
|
* 开始录音 使用amr格式
|
* 录音文件
|
*
|
* @return
|
*/
|
public void startRecord() {
|
// 开始录音
|
/* ①Initial:实例化MediaRecorder对象 */
|
if (mMediaRecorder == null)
|
mMediaRecorder = new MediaRecorder();
|
try {
|
/* ②setAudioSource/setVedioSource */
|
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
|
/* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
|
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
|
/*
|
* ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
|
* ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
|
*/
|
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
|
|
filePath = FolderPath + System.currentTimeMillis() + ".caf";
|
/* ③准备 */
|
mMediaRecorder.setOutputFile(filePath);
|
mMediaRecorder.setMaxDuration(MAX_LENGTH);
|
mMediaRecorder.prepare();
|
/* ④开始 */
|
mMediaRecorder.start();
|
// AudioRecord audioRecord.
|
/* 获取开始时间* */
|
startTime = System.currentTimeMillis();
|
updateMicStatus();
|
Log.e("fan", "startTime" + startTime);
|
} catch (IllegalStateException e) {
|
Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
|
} catch (IOException e) {
|
Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
|
}
|
}
|
|
/**
|
* 停止录音
|
*/
|
public long stopRecord() {
|
if (mMediaRecorder == null)
|
return 0L;
|
endTime = System.currentTimeMillis();
|
|
//有一些网友反应在5.0以上在调用stop的时候会报错,翻阅了一下谷歌文档发现上面确实写的有可能会报错的情况,捕获异常清理一下就行了,感谢大家反馈!
|
try {
|
mMediaRecorder.stop();
|
mMediaRecorder.reset();
|
mMediaRecorder.release();
|
mMediaRecorder = null;
|
|
audioStatusUpdateListener.onStop(filePath);
|
// filePath = ""; //这行代码会引起连续录音文件为空的bug
|
|
} catch (RuntimeException e) {
|
if (mMediaRecorder != null) {
|
mMediaRecorder.reset();
|
mMediaRecorder.release();
|
mMediaRecorder = null;
|
}
|
File file = new File(filePath);
|
if (file.exists())
|
file.delete();
|
|
filePath = "";
|
|
}
|
return endTime - startTime;
|
}
|
|
public String getFilePath() {
|
return filePath;
|
}
|
|
/**
|
* 取消录音
|
*/
|
public void cancelRecord() {
|
|
try {
|
|
mMediaRecorder.stop();
|
mMediaRecorder.reset();
|
mMediaRecorder.release();
|
mMediaRecorder = null;
|
|
} catch (RuntimeException e) {
|
mMediaRecorder.reset();
|
mMediaRecorder.release();
|
mMediaRecorder = null;
|
}
|
File file = new File(filePath);
|
if (file.exists())
|
file.delete();
|
|
filePath = "";
|
|
}
|
|
private final Handler mHandler = new Handler();
|
private Runnable mUpdateMicStatusTimer = new Runnable() {
|
public void run() {
|
updateMicStatus();
|
}
|
};
|
|
|
private int BASE = 1;
|
private int SPACE = 100;// 间隔取样时间
|
|
public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {
|
this.audioStatusUpdateListener = audioStatusUpdateListener;
|
}
|
|
/**
|
* 更新麦克状态
|
*/
|
private void updateMicStatus() {
|
|
if (mMediaRecorder != null) {
|
double ratio = (double) mMediaRecorder.getMaxAmplitude() / BASE;
|
double db = 0;// 分贝
|
if (ratio > 1) {
|
db = 20 * Math.log10(ratio);
|
if (null != audioStatusUpdateListener) {
|
audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
|
}
|
}
|
mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
|
}
|
}
|
|
public interface OnAudioStatusUpdateListener {
|
/**
|
* 录音中...
|
*
|
* @param db 当前声音分贝
|
* @param time 录音时长
|
*/
|
public void onUpdate(double db, long time);
|
|
/**
|
* 停止录音
|
*
|
* @param filePath 保存路径
|
*/
|
public void onStop(String filePath);
|
|
public void onStartPlay();
|
|
public void onFinishPlay();
|
|
public void onGetDuration(int duration);
|
}
|
|
|
/**
|
* 开始播放音频
|
* @param context
|
* @param filePath
|
*/
|
public void startPlayMusic(Context context, String filePath) {
|
if (mMediaPlayer != null) {
|
stopPlayMusic(false);
|
}
|
mMediaPlayer = new SimpleExoPlayer.Builder(context).build();
|
mMediaPlayer.setVolume(volume);
|
isPause = false;
|
try {
|
Log.e("mmp", "开始播放 path:" + filePath);
|
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(filePath));
|
mMediaPlayer.setMediaItem(mediaItem);
|
mMediaPlayer.prepare();
|
mMediaPlayer.play();
|
mMediaPlayer.addListener(new Player.Listener(){
|
@Override
|
public void onPlayerError(PlaybackException error) {
|
Log.e("mmp","播放错误:"+error.getMessage());
|
}
|
|
@Override
|
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
if (playbackState == Player.STATE_BUFFERING)
|
Log.e("mmp","缓冲中...STATE_BUFFERING");
|
else if (playbackState == Player.STATE_READY){
|
Log.e("mmp","缓冲完成,音频准备就绪:STATE_READY");
|
|
} else if (playbackState == Player.STATE_ENDED){
|
Log.e("mmp","播放完成:STATE_ENDED");
|
stopPlayMusic(true);
|
} else if (playbackState == Player.STATE_IDLE){
|
Log.e("mmp","播放器空闲:STATE_IDLE");
|
}
|
}
|
});
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
|
/**
|
* 循环播放音频
|
* @param context
|
* @param filePath
|
*/
|
public void loopPlayMusic(Context context, String filePath) {
|
if (mMediaPlayer != null) {
|
stopPlayMusic(false);
|
}
|
mMediaPlayer = new SimpleExoPlayer.Builder(context).build();
|
mMediaPlayer.setVolume(volume);
|
isPause = false;
|
try {
|
Log.e("mmp", "循环播放 path:" + filePath);
|
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(filePath));
|
mMediaPlayer.setMediaItem(mediaItem);
|
mMediaPlayer.prepare();
|
mMediaPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
|
mMediaPlayer.play();
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
public void pause(){
|
if (mMediaPlayer != null) {
|
mMediaPlayer.pause();
|
isPause = true;
|
}
|
}
|
|
public void resume(){
|
if (mMediaPlayer != null) {
|
mMediaPlayer.play();
|
isPause = false;
|
}
|
}
|
|
public void seekTo(int now){
|
if (mMediaPlayer != null) {
|
mMediaPlayer.seekTo(now*1000);
|
}
|
}
|
|
public void setVolume(float volume){
|
this.volume = volume;
|
if (mMediaPlayer!=null){
|
mMediaPlayer.setVolume(volume);
|
}
|
}
|
|
public long getCurrentPosition(){
|
if (mMediaPlayer!=null){
|
return mMediaPlayer.getCurrentPosition();
|
}
|
return 0;
|
}
|
|
|
/**
|
* 结束录音播放
|
* @param needCallback true真实结束 才走结束回调,为了切换下一首而结束的 不调结束回调
|
*/
|
public void stopPlayMusic(boolean needCallback) {
|
if (mMediaPlayer == null)
|
return;
|
try {
|
mMediaPlayer.stop();
|
mMediaPlayer.release();
|
mMediaPlayer = null;
|
if (audioStatusUpdateListener != null&&needCallback)
|
audioStatusUpdateListener.onFinishPlay();
|
} catch (IllegalStateException e) {
|
e.printStackTrace();
|
}
|
}
|
|
/**
|
* 获取文件长度
|
*
|
* @param context
|
* @param filePath
|
* @return
|
*/
|
// public int getMusicTime(Context context, String filePath) {
|
// if (mMediaPlayer != null) {
|
// stopPlayMusic(false);
|
// }
|
// mMediaPlayer = new MediaPlayer();
|
// try {
|
// mMediaPlayer.setDataSource(context, Uri.parse(filePath));
|
// mMediaPlayer.prepare();
|
// int duration = mMediaPlayer.getDuration();
|
// if (0 != duration) {
|
// mMediaPlayer.release();
|
// return duration / 1000;
|
// }
|
// } catch (IOException e) {
|
// e.printStackTrace();
|
// }
|
// return 0;
|
// }
|
|
}
|