资源信息下载
链接:https://pan.baidu.com/s/1m-HqA88udn-N_kNgOtoA_Q
提取码:8x3e
jni:音频转成MP3格式的C库,将类名或者路径名改成自己项目路径,通过NDK生成so库。(建议把jni文件夹同时也拷贝至 mp3library
模块下面)
mp3library:录音、格式转换的Library,包括so库和工具类。
1.下载地址:http://tools.android-studio.org/
2.解压后,配置环境变量
将jni目录拷贝至 mp3library
依赖模块中的根目录下
将C代码中路径改成自己库(so库所在的位置)的路径,cd进入jni目录下,运行ndk-build 命令生成so库,之后将编译成功的libs文件下面的so库拷贝到自己的项目中。
try {
String path = recAudioDir(recordFilePath).getAbsolutePath();
recFile = new File(path, System.currentTimeMillis() + ".mp3");
// 初始化录音工具类(mp3library库中),传入录音保存的路径
mRecorder = new MP3Recorder(recFile);
// 开始录音
mRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
AndioRecord
类的主要功能是让各种JAVA应用能够管理音频资源,以便它们通过此类能够录制平台的声音输入硬件所收集的声音。此功能的实现就是通过 “pulling同步
” AudioRecord
对象的声音数据来完成的。在录音过程中,应用所需要做的就是通过 read
方法去及时地获取 AudioRecord
对象的录音数据. AudioRecord
类提供的三个获取声音数据的方法分别是read(byte[], int, int), read(short[], int, int), read(ByteBuffer, int)
. 无论选择使用那一个方法都必须事先设定方便用户的声音数据的存储格式。
开始录音的时候,一个 AudioRecord
需要初始化一个相关联的声音 buffer
, 这个 buffer
主要是用来保存新的声音数据。这个buffer
的大小,我们可以在对象构造期间去指定。它表明一个 AudioRecord
对象还没有被读取(同步)声音数据前能录多长的音(即一次可以录制的声音容量)。一般情况下录音实现的简单流程如下:
AudioRecord
对象,其中需要的最小录音缓存 buffer
大小可以通过 getMinBufferSize
方法得到。如果 buffer
容量过小,将导致对象构造的失败AudioRecord
对象用于写声音数据的 buffer
大小AudioRecord
中读取声音数据到初始化 buffer
,将 buffer
中数据导入数据流public void start() throws IOException {
//以地址的方式获取frameCount的值。最小缓冲区的大小
mBufferSize = AudioRecord.getMinBufferSize(DEFAULT_SAMPLING_RATE,
DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT.getAudioFormat());
/** 初始化 AudioRecord
* DEFAULT_AUDIO_SOURCE: 音源 MediaRecorder.AudioSource.MIC 本机的声音
* DEFAULT_SAMPLING_RATE: 采样率 44100,模拟器仅支持从麦克风输入8kHz采样率
* DEFAULT_CHANNEL_CONFIG:录音的声道数,当前设置的 16
* DEFAULT_AUDIO_FORMAT: 录音的比特数,当前设置的 PCMFormat.PCM_16BIT
* mBufferSize: 期望录音时系统为其提供的缓冲区大小
*/
mAudioRecord = new AudioRecord(DEFAULT_AUDIO_SOURCE,
DEFAULT_SAMPLING_RATE, DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT.getAudioFormat(),mBufferSize);
mPCMBuffer = new short[mBufferSize];
mAudioRecord.startRecording();
new Thread() {
@Override
public void run() {
//设置线程权限
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
while (mIsRecording) {
int readSize = mAudioRecord.read(mPCMBuffer, 0, mBufferSize);
if (readSize > 0) {
mEncodeThread.addTask(mPCMBuffer, readSize);
calculateRealVolume(mPCMBuffer, readSize);
}
}
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
}
}
}
因为Android录音完成保存的音频格式默认为 amr
,这是个体积较小,播放效果较差的音频格式,所以我们需要将 amr
格式的音频转成 mp3
格式。这个时候就需要使用我们刚刚编译的so库了。
/**
* 实现AudioRecord.OnRecordPositionUpdateListener
* 从缓冲区中读取并处理数据,使用lame编码MP3
* @return 从缓冲区中读取的数据的长度,缓冲区中没有数据时返回0
*/
@Override
public void onPeriodicNotification(AudioRecord recorder){
if (mTasks.size() > 0) {
Task task = mTasks.remove(0);
short[] buffer = task.getData();
int readSize = task.getReadSize();
// 调用so库转成mp3
int encodedSize = LameUtil.encode(buffer, buffer, readSize, mMp3Buffer);
if (encodedSize > 0){
try {
mFileOutputStream.write(mMp3Buffer, 0, encodedSize);
} catch (IOException e) {
e.printStackTrace();
}
}
return readSize;
}
return 0;
}
}
private void stopRecorder() {
try {
if (mRecorder != null) {
mRecorder.stop();
mRecorder = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}