Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

13.7. 麦克风

13.7.1. AudioRecord

		
    private AudioRecord getAudioRecord() {
        final int SAMPLE_RATE = 16000;
        final int WAVE_FRAM_SIZE = 20 * 2 * 16000 / 1000; //20ms audio for 16k/16bit/mono
        try {
            int bufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
//            AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);

            AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, SAMPLE_RATE,
                    AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, WAVE_FRAM_SIZE * 4);

            if (recorder.getState() == AudioRecord.STATE_INITIALIZED) {
                return recorder;
            }
        } catch (Exception e) {
            Log.e(TAG, "Error in Audio Record");
        }
        return null;
    }		
		
			

13.7.2. 选择麦克风

当设备中有多个麦克风时,我们希望切换到另一个麦克风,可以采用此方法。

		
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 16000 * 4);

        AudioManager audioManager = (AudioManager) MainApplication.getContext().getSystemService(Context.AUDIO_SERVICE);
        AudioDeviceInfo[] audioDeviceInfos = new AudioDeviceInfo[]{};
        audioDeviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
        for (AudioDeviceInfo device : audioDeviceInfos) {
            if (device.getType() == AudioDeviceInfo.TYPE_USB_DEVICE && device.getProductName().equals("USB-Audio - USB PnP Sound Device")) {
                audioRecord.setPreferredDevice(device);
                Log.d(TAG, "Set microphone: " + device.getProductName());
            }

            Log.d(TAG, device.getId() + " | " + device.getProductName() + " | " + device.getType());
        }
        audioRecord.startRecording();
        Log.d(TAG, "AudioRecord state: " + audioRecord.getState());

        if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
            Log.e(TAG, "audio recorder not init");
        } else {
            byte[] audioData = new byte[1024];
            for (int i = 0; i < 100; i++) {
                int ret = audioRecord.read(audioData, 0, 1024);
                Log.d(TAG, String.valueOf(audioData));
            }
        }
		
			

13.7.3. 设置蓝牙麦克风为默认麦克风

			
		if (ActivityCompat.checkSelfPermission(MainApplication.getContext(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
			// https://www.netkiller.cn/android/
            if (mAudioRecorder == null) {

                AudioManager audioManager = (AudioManager) MainApplication.getContext().getSystemService(Context.AUDIO_SERVICE);
                // 启动蓝牙SCO连接
                audioManager.startBluetoothSco();
                // 启用蓝牙SCO音频路由
                audioManager.setBluetoothScoOn(true);
                // 设置音频模式为通信模式(这会优先使用蓝牙麦克风)
                audioManager.setMode(AudioManager.MODE_COMMUNICATION_REDIRECT);

                // 获取所有音频输入设备
                AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);

                // 查找蓝牙设备
                AudioDeviceInfo bluetoothDevice = null;
                for (AudioDeviceInfo device : devices) {
                    if (device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO ||
                            device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP) {
                        bluetoothDevice = device;
                        break;
                    }
                }

                mAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_RATE,
                        AudioFormat.CHANNEL_IN_MONO,
                        AudioFormat.ENCODING_PCM_16BIT,
                        WAVE_FRAM_SIZE * 4);

                if (bluetoothDevice != null) {
                    if (mAudioRecorder.setPreferredDevice(bluetoothDevice)) {
                        Log.i(TAG, "成功设置蓝牙麦克风为首选设备 " + bluetoothDevice.getProductName());
                    }

                    AudioDeviceInfo currentDevice = mAudioRecorder.getRoutedDevice();
                    if (currentDevice != null) {
                        Log.d(TAG, "当前音频输入设备: " + currentDevice.getProductName());
                    }
                }
            } else {
                Log.w(TAG, "AudioRecord has been new ...");
            }
        } else {
            Log.e(TAG, "未获得录音权限 RECORD_AUDIO permission!");
        }			
			
			

13.7.4. 录音例子

			
package cn.netkiller.conference.test;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.nio.ByteBuffer;

import cn.netkiller.conference.MainApplication;
import cn.netkiller.conference.R;

public class TestActivity extends AppCompatActivity {

    private static final String TAG = TestActivity.class.getSimpleName();
    public String meetingJoinUrl;
    public String taskId;
    private AudioRecord audioRecord;


    @SuppressLint("MissingInflatedId")
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.UNPROCESSED, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 16000 * 4);

        AudioManager audioManager = (AudioManager) MainApplication.getContext().getSystemService(Context.AUDIO_SERVICE);
        AudioDeviceInfo[] audioDeviceInfos = new AudioDeviceInfo[]{};
        audioDeviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
        for (AudioDeviceInfo device : audioDeviceInfos) {
            Log.d(TAG, device.getId() + " | " + device.getProductName() + " | " + device.getType());

            if ((device.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || device.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) && device.getProductName().toString().contains("USB-Audio")) {
                audioRecord.setPreferredDevice(device);
                Log.d(TAG, "Set microphone: " + device.getProductName());
            }
        }
        audioRecord.startRecording();
        Log.d(TAG, "AudioRecord state: " + audioRecord.getState());

        if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
            Log.e(TAG, "audio recorder not init");
        } else {
            new Thread(new AudioRecordRunnable()).start();
        }


    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (audioRecord != null) {
            audioRecord.stop();
            audioRecord.release();
        }
    }

    private class AudioRecordRunnable implements Runnable {
        public void run() {
            Log.d(TAG, "Thread buffer start");
            ByteBuffer audioBuffer = ByteBuffer.allocate(1024);
            while (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
                int read = audioRecord.read(audioBuffer, audioBuffer.capacity());
                if (read > 0) {
                    Log.d(TAG, audioBuffer.toString());
                }
//                Log.d(TAG, String.valueOf(read));
            }

//            try (FileOutputStream fos = new FileOutputStream("output.pcm")) {
//                while (isRecording) {
//                    int read = audioRecord.read(audioBuffer, audioBuffer.capacity());
//                    if (read > 0) {
//                        fos.write(audioBuffer.array(), 0, read);
//                    }
//                }
//            } catch (Exception e) {
//                Log.e(TAG, "Error writing audio", e);
//            }
        }
    }

}