我是靠谱客的博主 苗条铅笔,这篇文章主要介绍Android音视频学习(二),现在分享给大家,希望可以做个参考。

引用

感谢灰色飘零大佬的这篇指南

概念

Android提供了两种音频录制方式, 这里讲比较底层一些的AudioRecord.

引用一下google的定义:

AudioRecord类管理Java程序的音频资源, 以记录来自音频输入硬件的音频. 这是通过向AudioRecord对象读取数据来实现的. 应用通过以下三种方法之一及时的查询AudioRecord对象:

  1. read(byte[], int, int)
  2. read(short[], int, int)
  3. read(ByteBuffer, int)

具体使用哪个, 是根据音频数据存储格式自由选择的. 创建后, AudioRecord对象初始化其关联的音频缓冲区, 它将填充新的音频数据. 在构造期间指定的缓冲区大小决定了AudioRecord在"过度运行"时, 尚未读取的数据可以保存多长时间. 因此从音频硬件读取的数据块大小应该小于缓冲区大小.

下面是具体实现

权限申请

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void checkPermission() { //6.0以后需要动态申请权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //检查是否已经获取权限, 没有获取的权限放到list里 for (String permission : permissions) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { mPermissionList.add(permission); } } //list不为空, 就去申请所需要的权限 if (!mPermissionList.isEmpty()) { String[] permissions = mPermissionList.toArray(new String[0]); ActivityCompat.requestPermissions(this, permissions, MY_PERMISSIONS_REQUEST); } } } 复制代码

创建AudioRecord

这里写了个方法来创建AudioRecord:

复制代码
1
2
3
4
5
6
7
8
9
private void createAudioRecord() { //这里通过AudioRecord类获取最小的缓存大小 recordBufSize = AudioRecord.getMinBufferSize(GlobalConfig.SAMPLE_RATE_INHZ, GlobalConfig.CHANNEL_CONFIG, GlobalConfig.AUDIO_FORMAT); mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, GlobalConfig.SAMPLE_RATE_INHZ, GlobalConfig.CHANNEL_CONFIG, GlobalConfig.AUDIO_FORMAT, recordBufSize); } 复制代码

用到的配置类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
public class GlobalConfig { //采样率 public static final int SAMPLE_RATE_INHZ = 44100; //声道 public static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO; //返回的音频数据格式 public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; } 复制代码

开始录制音频

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private void startRecord() { createAudioRecord(); //buffer, 用来从AudioRecord中获取录制的音频 final byte[] data = new byte[recordBufSize]; //pcm文件存储位置 final File file = new File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.pcm"); if (!file.mkdirs()) { Log.d(TAG, "startRecord: " + "Directory not created"); } if (file.exists()) { file.delete(); } //开始录制 mAudioRecord.startRecording(); //录制标记 isRecording = true; //不阻塞主线程 new Thread(new Runnable() { @Override public void run() { //新建文件输出流, 把录制音频存储 FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } if (fileOutputStream != null) { while (isRecording) { //将录制音频传到buffer里 int read = mAudioRecord.read(data, 0, recordBufSize); if (read != AudioRecord.ERROR_INVALID_OPERATION) { try { //buffer数据没问题写入到文件中 fileOutputStream.write(data); } catch (IOException e) { e.printStackTrace(); } } } try { //不要忘记关文件输出流 fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } 复制代码

停止录制

复制代码
1
2
3
4
5
6
7
8
9
10
11
private void stopRecord() { //停止录音 isRecording = false; //不要泄露 if (mAudioRecord != null) { mAudioRecord.stop(); mAudioRecord.release(); mAudioRecord = null; } } 复制代码

原始音频文件转化

这里直接给一个大佬提供的转化工具类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/** * 将pcm音频文件转换为wav音频文件 */ public class PcmToWavUtil { /** * 缓存的音频大小 */ private int mBufferSize; /** * 采样率 */ private int mSampleRate; /** * 声道数 */ private int mChannel; /** * @param sampleRate sample rate、采样率 * @param channel channel、声道 * @param encoding Audio data format、音频格式 */ PcmToWavUtil(int sampleRate, int channel, int encoding) { this.mSampleRate = sampleRate; this.mChannel = channel; this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, encoding); } /** * pcm文件转wav文件 * * @param inFilename 源文件路径 * @param outFilename 目标文件路径 */ public void pcmToWav(String inFilename, String outFilename) { FileInputStream in; FileOutputStream out; long totalAudioLen; long totalDataLen; long longSampleRate = mSampleRate; int channels = mChannel == AudioFormat.CHANNEL_IN_MONO ? 1 : 2; long byteRate = 16 * mSampleRate * channels / 8; byte[] data = new byte[mBufferSize]; try { in = new FileInputStream(inFilename); out = new FileOutputStream(outFilename); totalAudioLen = in.getChannel().size(); totalDataLen = totalAudioLen + 36; writeWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate); while (in.read(data) != -1) { out.write(data); } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 加入wav文件头 */ private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException { byte[] header = new byte[44]; // RIFF/WAVE header header[0] = 'R'; header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); //WAVE header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; // 'fmt ' chunk header[12] = 'f'; header[13] = 'm'; header[14] = 't'; header[15] = ' '; // 4 bytes: size of 'fmt ' chunk header[16] = 16; header[17] = 0; header[18] = 0; header[19] = 0; // format = 1 header[20] = 1; header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); // block align header[32] = (byte) (2 * 16 / 8); header[33] = 0; // bits per sample header[34] = 16; header[35] = 0; //data header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); out.write(header, 0, 44); } } 复制代码

总结

到这里, 就可以进行音频录制啦

转载于:https://juejin.im/post/5c67b89451882561ff304e60

最后

以上就是苗条铅笔最近收集整理的关于Android音视频学习(二)的全部内容,更多相关Android音视频学习(二)内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(89)

评论列表共有 0 条评论

立即
投稿
返回
顶部