Android 音频 MediaRecorder和AudioRecord录音与MediaPlayer和AudioTrack播放

https://www.2cto.com/kf/201704/636266.html

Android 音频 MediaRecorder和AudioRecord录音与MediaPlayer和AudioTrack播放

2017-04-28 17:16:09      0个评论    来源:小码哥—WS的专栏  

收藏   我要投稿

 

录制声音MediaRecorder和AudioRecord 区别

MediaRecorder和AudioRecord都可以录制音频,区别是MediaRecorder录制的音频文件是经过压缩后的,需要设置编码器。并且录制的音频文件可以用系统自带的Music播放器播放。
而AudioRecord录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。
在用MediaRecorder进行录制音视频时,最终还是会创建AudioRecord用来与AudioFlinger进行交互。
C++层MediaRecorder创建AudioRecord类的代码位于AudioSource类构造函数中.

MediaRecorder录制的数据是 amr MP3 格式
AudioRecorder录制出来的是比较原始的PCM音频格式
PCM经过编码压缩可以为 amr MP3 AAC。

播放声音时MediaPlayer和AudioTrack的区别

播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供应用开发者使用。虽然都可以播放声音,但两者还是有很大的区别的。
其中最大的区别是MediaPlayer可以播放多种格式的声音文件,例如 MP3,AAC,WAV,OGG,MIDI等。MediaPlayer会在framework层创建对应的音频解码器。
而AudioTrack只能播放已 经解码的PCM流,如果是文件的话只支持wav格式的音频文件,因为wav格式的音频文件大部分都是PCM流。AudioTrack不创建解码器,所以只 能播放不需要解码的wav文件。当然两者之间还是有紧密的联系,MediaPlayer在framework层还是会创建AudioTrack,把解码后 的PCM数流传递给AudioTrack,AudioTrack再传递给AudioFlinger进行混音,然后才传递给硬件播放。

MediaRecorder与MediaPlayer前面的博客中已经有写,是视频的录制与播放。这里就不在举例。
下面主要实现一个AudioRecord ,AudioTrack音频的录制与播放。

?

1

public AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)

?

1

2

3

4

5

6

7

8

AudioTrack audio = new AudioTrack(

                          AudioManager.STREAM_MUSIC, // 指定在流的类型

                          32000, // 设置音频数据的采样率 32k,如果是44.1k就是44100

                          AudioFormat.CHANNEL_OUT_STEREO, // 设置输出声道为双声道立体声,而CHANNEL_OUT_MONO类型是单声道

                          AudioFormat.ENCODING_PCM_16BIT, // 设置音频数据块是8位还是16位,这里设置为16位。好像现在绝大多数的音频都是16位的了

                          AudioTrack.MODE_STREAM // 设置模式类型,在这里设置为流类型,另外一种MODE_STATIC貌似没有什么效果

                      );

   audio.play(); // 启动音频设备,下面就可以真正开始音频数据的播放了

下面是完整代码

?

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

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

 

import android.app.Activity;

import android.media.AudioFormat;

import android.media.AudioManager;

import android.media.AudioRecord;

import android.media.AudioTrack;

import android.media.MediaRecorder;

import android.os.Bundle;

import android.os.Environment;

import android.util.Log;

import android.view.View;

import android.widget.Button;

 

public class MainActivity extends Activity {

 

    private short[] mAudioRecordData;

    private short[] mAudioTrackData;

 

    private Button mStart;

    private Button mStop;

    private Button mPlay;

    private Button mWipe;

 

    private File mAudioFile;

    private AudioRecord mAudioRecord;

    private AudioTrack mAudioTrack;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        init();

 

        registerListener();

    }

 

    private void registerListener() {

//开始录制  把录制的数据存在mAudioFile文件中

        mStart.setOnClickListener(new View.OnClickListener() {

 

            @Override

            public void onClick(View v) {

                new Thread(new Runnable() {

                    public void run() {

                        try {

                            mAudioRecord.startRecording();

                            DataOutputStream dos = new DataOutputStream(

                                    new BufferedOutputStream(

                                            new FileOutputStream(mAudioFile)));

                            while (mAudioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {

                                int number = mAudioRecord.read(

                                        mAudioRecordData, 0,

                                        mAudioRecordData.length);

                                for (int i = 0; i < number; i++) {

                                    dos.writeShort(mAudioRecordData[i]);

                                }

                                if (AudioRecord.ERROR_BAD_VALUE != number

                                        && AudioRecord.ERROR != number) {

                                    Log.d("TAG", String.valueOf(number));

                                }

                            }

                            dos.flush();

                            dos.close();

                            Log.d("TAG", "dos.close()");

                        } catch (FileNotFoundException e) {

                            e.printStackTrace();

                        } catch (IOException e) {

                            e.printStackTrace();

                        }

                    }

                }).start();

            }

        });

//停止录音

        mStop.setOnClickListener(new View.OnClickListener() {

 

            @Override

            public void onClick(View v) {

 

                if (mAudioRecord != null

                        && mAudioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {

                    mAudioRecord.stop();

                }

            }

        });

//开始播放 将数据写入到AudioTrack中播放

        mPlay.setOnClickListener(new View.OnClickListener() {

 

            @Override

            public void onClick(View v) {

                new Thread(new Runnable() {

                    public void run() {

                        try {

                            mAudioTrack.play();

                            DataInputStream dis = new DataInputStream(

                                    new BufferedInputStream(

                                            new FileInputStream(mAudioFile)));

                            Log.d("TAG", "dis.available=" + dis.available());

                            while (mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING

                                    && dis.available() > 0) {

                                int i = 0;

                                while (dis.available() > 0

                                        && i < mAudioTrackData.length) {

                                    mAudioTrackData[i] = dis.readShort();

                                    i++;

                                }

                                wipe(mAudioTrackData, 0, mAudioTrackData.length);

                                // 然后将数据写入到AudioTrack中

                                mAudioTrack.write(mAudioTrackData, 0,

                                        mAudioTrackData.length);

                            }

                            mAudioTrack.stop();

                            dis.close();

                            Log.d("TAG", "dis.close()");

                        } catch (FileNotFoundException e) {

                            e.printStackTrace();

                        } catch (IOException e) {

                            e.printStackTrace();

                        }

                    }

                }).start();

            }

        });

 

        mWipe.setOnClickListener(new View.OnClickListener() {

 

            @Override

            public void onClick(View v) {

                wipe(mAudioTrackData, 0, mAudioTrackData.length);

            }

        });

    }

//初始化

    private void init() {

 

        mStart = (Button) findViewById(R.id.start);

        mStop = (Button) findViewById(R.id.stop);

        mPlay = (Button) findViewById(R.id.play);

        mWipe = (Button) findViewById(R.id.wipe);

        if (Environment.getExternalStorageState().equals(

                Environment.MEDIA_MOUNTED)) {

            File file = new File(Environment.getExternalStorageDirectory()

                    .getAbsolutePath() + "/audio/");

            if (!file.exists()) {

                file.mkdirs();

            }

            //创建录音文件

            mAudioFile = new File(file, System.currentTimeMillis() + ".pcm");

        }

 

        try {

            int sampleRateInHz = 44100;//所有Android系统都支持的频率

            //AudioFormat.CHANNEL_IN_MONO但声道输入    AudioFormat.ENCODING_PCM_16BIT这个所有Android系统都支持

            int recordBufferSizeInBytes = AudioRecord.getMinBufferSize(

                    sampleRateInHz, AudioFormat.CHANNEL_IN_MONO,

                    AudioFormat.ENCODING_PCM_16BIT);

            Log.d("TAG", "recordBufferSizeInBytes=" + recordBufferSizeInBytes);

            mAudioRecordData = new short[recordBufferSizeInBytes];

             // 创建AudioRecord实例

            mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,

                    sampleRateInHz, AudioFormat.CHANNEL_IN_MONO,

                    AudioFormat.ENCODING_PCM_16BIT, recordBufferSizeInBytes);

 

            int trackBufferSizeInBytes = AudioRecord.getMinBufferSize(

                    sampleRateInHz, AudioFormat.CHANNEL_IN_MONO,

                    AudioFormat.ENCODING_PCM_16BIT);

             // 创建mAudioTrack实例

            mAudioTrackData = new short[trackBufferSizeInBytes];

            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,

                    sampleRateInHz, AudioFormat.CHANNEL_OUT_MONO,

                    AudioFormat.ENCODING_PCM_16BIT, trackBufferSizeInBytes,

                    AudioTrack.MODE_STREAM);

        } catch (IllegalArgumentException e) {

            e.printStackTrace();

        }

 

    }

 

    /**

     * 消除噪音

     */

    private void wipe(short[] lin, int off, int len) {

        int i, j;

        for (i = 0; i < len; i++) {

            j = lin[i + off];

            lin[i + off] = (short) (j >> 2);

        }

    }

 

    @Override

    protected void onStop() {

        if (mAudioFile.exists()) {

            mAudioFile.delete();

        }

        if (mAudioRecord != null) {

            mAudioRecord.release();

            mAudioRecord = null;

        }

        if (mAudioTrack != null) {

            mAudioTrack.release();

            mAudioTrack = null;

        }

        super.onStop();

    }

 

}

?

1

<linearlayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" tools:context=".MainActivity" xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools"><button android:id="@+id/start" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="开始录音"></button><button android:id="@+id/stop" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="停止录音"></button><button android:id="@+id/play" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="播放录音"></button><button android:id="@+id/wipe" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="去除噪音"></button></linearlayout>

这里也推荐一个库VCamera

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值