项目中用的评论回复功能,录制语言时为pcm格式,然后转换为MP3格式:

package zhiji.dajing.com.util;import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;import com.jiangdg.lametomp3.LameMp3;
import com.jiangdg.lametomp3.Mp3Recorder;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class AudioRecoderUtils {//文件路径private String filePath;//文件夹路径private String FolderPath;AudioRecord audioRecord;private final String TAG = "AudioRecoderUtils";public static final int MAX_LENGTH = 1000 * 1000 * 1000 ;// 最大录音时长private OnAudioStatusUpdateListener audioStatusUpdateListener;private  String voicePath = Environment.getExternalStorageDirectory()+"/dajing/audio/pcm/";private String voiceName = TimeUtils.getCurrentTime() + ".pcm";private boolean isRecording = false;int nMinBufSize =AudioRecord.getMinBufferSize(16000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);private double volume;private ExecutorService mThreadExecutor;private Handler handler;static AudioRecoderUtils audioRecoderUtils_p ;public boolean isTmpConversition;/*** 文件存储默认sdcard/record*/public AudioRecoderUtils(){//默认保存路径为/sdcard/record/下this(Environment.getExternalStorageDirectory()+"/dajing/audio/pcm/");mThreadExecutor = Executors.newScheduledThreadPool(3);}public AudioRecoderUtils(String filePath) {File path = new File(filePath);if(!path.exists())path.mkdirs();this.FolderPath = filePath;handler = new Handler();}public static AudioRecoderUtils getInstance(){if (audioRecoderUtils_p == null){audioRecoderUtils_p = new AudioRecoderUtils();}return audioRecoderUtils_p;}private long startTime;private long endTime;public void startRecord(){audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 16000,AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, nMinBufSize);final File file = new File(voicePath);voiceName = TimeUtils.getCurrentTime() + ".pcm";final File fileaudio = new File(voicePath + voiceName);filePath = voicePath + voiceName;if (fileaudio.exists()) {fileaudio.delete();}if (!file.exists()) {file.mkdirs();}audioRecord.startRecording();isRecording = true;startTime = System.currentTimeMillis();mThreadExecutor.execute(new Runnable() {@Overridepublic void run() {FileOutputStream fos = null;byte data[] = new byte[nMinBufSize];try {fos = new FileOutputStream(fileaudio);} catch (FileNotFoundException e) {e.printStackTrace();}if (null != fos) {while (isRecording) {int read = audioRecord.read(data, 0, nMinBufSize);volume = getVolume(read, data.clone());handler.post(new Runnable() {@Overridepublic void run() {audioStatusUpdateListener.onUpdate(volume,System.currentTimeMillis()-startTime);}});//返回正确时才读取数据if (AudioRecord.ERROR_INVALID_OPERATION != read) {try {fos.write(data);} catch (IOException e) {e.printStackTrace();}}}try {fos.close();} catch (IOException e) {e.printStackTrace();}}}});}private double getVolume(int r, byte[] bytes_pkg) {int v = 0;for(int i = 0; i < bytes_pkg.length; i+=2){int v1 = bytes_pkg[i] & 0xFF;int v2 = bytes_pkg[i + 1] & 0xFF;int temp = v1 + (v2 << 8);// 小端if (temp >= 0x8000) {temp = 0xffff - temp;}v += Math.abs(temp);}int tmp_v = v / bytes_pkg.length / 2;volume = Math.log10(1 + tmp_v) * 10;return volume;}public Long stopRecord() {isRecording = false;if (audioRecord != null) {audioRecord.stop();audioRecord.release();//调用release之后必须置为nullaudioRecord = null;}endTime = System.currentTimeMillis();process();return endTime - startTime;}public static String path;private File mFile;public  String processPath = voicePath + System.currentTimeMillis() + "process.pcm";private Timer timer;private void process() {mThreadExecutor.execute(new Runnable() {@Overridepublic void run() {mFile = new File(filePath);try {FileInputStream ins = new FileInputStream(mFile);byte[] bbytes = new byte[(int) mFile.length()];int readBytes = ins.read(bbytes);ins.close();Log.i(TAG,"读取pcm数据流,大小为:"+readBytes);//录音用16K采用,单声道,16位//读取PCM文件到bbytes[]int count = bbytes.length/2;      //16位数组的长度short[] data = new short[count];for (int i = 0; i < count; i++) {data[i] = (short) (bbytes[i * 2] & 0xff | (bbytes[2 * i + 1] & 0xff)<< 8);            //需要确认是否是小端模式}int num = 0;float allNum = 0;for (int i = 0; i < count; i++) {if (data[i] > 1800) {allNum = allNum + data[i];num = num + 1;}}float multiple;if(allNum==0||num==0){multiple=6;}else{if (allNum / num < 2500) {multiple = (float) (32000 / (allNum / num) / 2.5);}else{multiple = (float) (32000 / (allNum / num) / 6.5);}if (multiple < 1) {multiple = 1;}}for (int i = 0; i < count; i++) {if (Math.abs(data[i]) < ((short)32000 / multiple)) {data[i] = (short) (data[i] * multiple);}}for (int i = 0; i < count; i++) {bbytes[i * 2] = (byte) (data[i] >> 0);bbytes[i * 2 + 1] = (byte) (data[i] >> 8);         //需要确认是否是小端模式}byte[] bbytes8000 = new byte[count];int j = 0;for (int i = 0; i < bbytes.length ; i++) {if((i%4) == 0){bbytes8000[j] = bbytes[i];bbytes8000[j+1] = bbytes[i+1];j+=2;}}// 保存bbytes[]到PCM文件try {String finalPath = "";if (isTmpConversition){OutputStream out = new FileOutputStream(processPath);out.write(bbytes8000);out.close();finalPath = AmrEncoder.pcm2Amr(processPath, Environment.getExternalStorageDirectory() +"/dajing/audio/amr/");}else {/** 初始化lame库,配置相关信息* @param inSampleRate pcm格式音频采样率* @param outChannel pcm格式音频通道数量* @param outSampleRate mp3格式音频采样率* @param outBitRate mp3格式音频比特率* @param quality mp3格式音频质量,0~9,最慢最差~最快最好*/LameMp3.lameInit(16000,AudioFormat.CHANNEL_IN_MONO,16000, Mp3Recorder.LAME_BITRATE_32,5);byte[] mp3Bytes = new byte[bbytes.length];int lameFlush = LameMp3.lameEncode(data,data,data.length,mp3Bytes);Log.i(TAG,"lame编码,大小为:"+ lameFlush);int flush = LameMp3.lameFlush(mp3Bytes);Log.i(TAG,"录制完毕,大小为:" + flush);OutputStream mp3Out = null;String mp3Path = Environment.getExternalStorageDirectory() + "/dajing/audio/mp3/" + System.currentTimeMillis() + ".mp3";File file = new File(Environment.getExternalStorageDirectory() + "/dajing/audio/mp3/");if (!file.exists()){file.mkdirs();}try {mp3Out = new FileOutputStream(mp3Path);mp3Out.write(mp3Bytes,0,lameFlush );mp3Out.close();finalPath = mp3Path;} catch (Exception e) {e.printStackTrace();}}String finalPath1 = finalPath;handler.post(new Runnable() {@Overridepublic void run() {audioStatusUpdateListener.onStop(finalPath1);}});} catch (Exception e) {e.printStackTrace();}finally {LameMp3.lameClose();}} catch (Exception e) {e.printStackTrace();}}});}private short[] transferByte2Short(byte[] data,int readBytes){// byte[] 转 short[],数组长度缩减一半int shortLen = readBytes / 2;// 将byte[]数组装如ByteBuffer缓冲区ByteBuffer byteBuffer = ByteBuffer.wrap(data, 0, readBytes);// 将ByteBuffer转成小端并获取shortBufferShortBuffer shortBuffer = byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();short[] shortData = new short[shortLen];shortBuffer.get(shortData, 0, shortLen);return shortData;}/*** 取消录音*/public void cancelRecord(){isRecording = false;try {audioRecord.stop();audioRecord.release();audioRecord = null;}catch (RuntimeException e){audioRecord.release();}finally {audioRecord = null;}File file = new File(filePath);if (file.exists())file.delete();filePath = "";}public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {this.audioStatusUpdateListener = audioStatusUpdateListener;}/*** 更新麦克状态*/private void updateMicStatus() {if (audioRecord != null) {timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {try {byte data[] = new byte[nMinBufSize];int read = audioRecord.read(data, 0, nMinBufSize);volume = getVolume(read, data.clone());Log.e("reaudioTime","time 3 = " + volume);double ratio =0.0;if (volume < 1000 && volume > 0){ratio = volume / 600;}else {ratio = volume / 4000;}double db = 0;// 分贝if (ratio > 1) {db = 20 * Math.log10(ratio);if(null != audioStatusUpdateListener) {double finalDb = db;handler.post(new Runnable() {@Overridepublic void run() {}});}}} catch (Exception e) {e.printStackTrace();}}},100,100);}}public interface OnAudioStatusUpdateListener {/*** 录音中...* @param db 当前声音分贝* @param time 录音时长*/public void onUpdate(double db, long time);/*** 停止录音* @param filePath 保存路径*/public void onStop(String filePath);}}

Android 录音(录音时为pcm,然后转为MP3)相关推荐

  1. 录音播放系统(实现pcm转码mp3,wav)

    本文介绍了基于waveX低级音频API采集音频,然后播放的技术,也支持实时的播放.对于将录音和播放分开的做法原因是为了保存pcm文件(未经压缩过的音频文件), 然后转码wav和mp3格式. PCM(P ...

  2. 【Android FFMPEG 开发】Android 中使用 FFMPEG 将 PCM 音频采样转为 MP3 格式

    文章目录 一.前置操作 ( 移植 FFMPEG ) 二.FFMPEG 将 PCM 采样转为 MP3 格式的命令 三.Android FFMPEG 混音源代码完整示例 四.博客源码 一.前置操作 ( 移 ...

  3. Android 录音文件有杂音,录音文件时长比实际时长长问题解决

    问题:在使用Android的AudioRecord进行录音时,录制生成的录音文件的时长比实际录制时间长,且录制的音频有一部分是有杂音或者没有声音的. 安卓出现录音问题还可以参考另一篇文章 Androi ...

  4. Android变录音边转换为mp3格式的声音---libmp3lame库的使用

    Android录音支持的格式有amr.aac.3gp,但这三种音频格式在跨平台上表现并不好.而mp3格式是跨平台最好的音频格式,所以如果能转成mp3格式的音频文件,那是极好的. 那转成mp3格式又有两 ...

  5. android java 录音放大_Android实现录音功能实现实例(MediaRecorder)

    本文介绍了Android实现录音的实例代码(MediaRecorder),分享给大家,具体如下: Android提供了两个API用于录音的实现:MediaRecorder 和 AudioRecord, ...

  6. Android 实时录音和回放,边录音边播放 (KTV回音效果)

    原文地址为: Android 实时录音和回放,边录音边播放 (KTV回音效果) 上一篇介绍了如何使用Mediarecorder来录音,以及播放录音.不过并没有达到我的目的,一边录音一边播放.今天就讲解 ...

  7. Android 多通道录音笔记

    Android 多通道录音笔记 安卓提供了单双通道录音接口以及多通道录音接口 若底层只支持单双通道, 可以使用掩码格式只获取第二个通道数据 此时如果指定多通道录音,则打开设备时候会出错. (录音阶段, ...

  8. 曝iPhone15或换用USB-C接口;Google将下架第三方Android通话录音APP|极客头条

    「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 梦依丹 出品 | CSDN(ID:CSDNnews ...

  9. android按住录音按钮_Android实现录音方法(仿微信语音、麦克风录音、发送语音、解决5.0以上BUG)...

    先给大家展示下效果图,如果大家感觉不错,请参考使用方法, 效果图如下所示: 使用方法: 录音工具类:AudioRecoderUtils.java,代码如下: public class AudioRec ...

最新文章

  1. 2022-2028年中国输送胶管行业市场全景调查及投资前景趋势报告
  2. Android常用逆向工具总结(未完待续)
  3. 适合0基础的web开发系列教程-web 存储
  4. linux 通过命令行获取本机外网IP
  5. 【踩坑】遇到 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 报错...
  6. hbuilderx简单网页代码_Python爬取网页数据
  7. CentOS7中安装图形界面
  8. C#并行编程中的Parallel.Invoke
  9. 180°舵机的使用步骤
  10. git(12)---Git的基础知识
  11. TP5.1 查询数据库中上一条和下一条记录
  12. 技巧 | 如何使用R语言的常用工具包绘制双变量填充地图
  13. 如何解决海量数据的处理问题
  14. 【STM32F407F429H7的DSP教程】第34章 滤波器基础知识
  15. 计算机cpu占用率高,CPU占用率高的原因及解决方法
  16. 使用Spring Data MongoDB操作SequoiaDB巨杉数据库简易教程
  17. 始终从最不易改变的方面开始
  18. pip install下载速度太慢
  19. DevExpress_Winform_使用汇总
  20. Core Animation (2)

热门文章

  1. 单面机51小车程序_车辆工程学院举行“51单片机智能小车”电子设计成果答辩展示...
  2. 怎样把书读得“四通八达”?(文/王路)
  3. 「真实案例」数字化商品企划让服装零售企业数字化升级事半功倍
  4. JAVA毕业设计机械生产企业办公设备管理系统计算机源码+lw文档+系统+调试部署+数据库
  5. 提示libface.dll找不到
  6. java 墨卡托转经纬度_经纬度,墨卡托等坐标转换
  7. Nacos 1.4.1 紧急升级修复Alibaba Nacos 认证绕过漏洞
  8. 用javascript模拟实现计算器
  9. python列表第几个怎么表示-Python列表操作大全(非常全)
  10. 图像处理函数详解——bwareaopen