AudioRecord指定音频输入设备录音

经过上次的AAudio踩坑后,一段时间信心指数跌到了谷底。调整情绪后,再次把目光指向了AudioRecord。

构造函数的MediaRecorder.AudioSource

创建AudioRecord时,可以指定音频源

AudioRecord audioRecord = new AudioRecord(
    MediaRecorder.AudioSource.MIC,
    sampleRate,
    inChannelConfig,
    audioFormat,
    bufferSize);

这里的音频源无法对应到具体的音频设备,尝试MediaRecorder.AudioSource.VOICE_xxx等,不是没什么效果,就是创建失败。

成员函数setPreferredDevice指定设备

实践发现,创建完AudioRecord后,可以使用setPreferredDevice()函数实现音频源设备的指定。其参数是AudioDeviceInfo,音频设备AudioDeviceInfo,可以通过之前提到过的AudioManager进行枚举。

        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

        AudioDeviceInfo[] inputDevices = new AudioDeviceInfo[]{};
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            inputDevices = audioManager.getDevices(DeviceFlag);

            for (AudioDeviceInfo device : inputDevices) {
                if (deviceID == device.getId()) {
                    return device;
                }
            }
        }

实际应用中,setPreferredDevice()可以指定录音设备。当硬件有多个麦克风时,可以设置多声道,来实现立体声录音。比如设置双声道,底部和顶部麦克风分别对应左声道和右声道。

另外,setPreferredDevice()也可以指定输出音频设备,这样的话,可以实现任意音频设备的输入、任意音频设备的输出。

应用举例

手机麦克风>耳机——对着手机说话,可以从耳机中听到声音;如果耳机线连接的是音响,手机这时可以作为有线扩音器使用。

手机麦克风>听筒/手机外放——由于现款手机顶部/底部都有麦克风,基本上这种模式都会出现刺耳的声音回授(audio feedback)。

耳机麦克风>听筒/手机外放——手机声音较少,达不到扩音的目的。

耳机麦克风>耳机——用来测试耳机麦克风。

蓝牙麦克风>耳机/听筒/手机外放——耳机连接音响时,蓝牙麦克风可作为无线扩音器使用;可进行近距离远程监听,把蓝牙耳机需要监听的位置,躲在一旁用手机监听。

手机麦克风>蓝牙听筒——近距离远程监听,把手机需要监听的位置,躲在一旁用蓝牙耳机监听。

蓝牙耳机

以上应用中,除了蓝牙麦克风以外,目前为止其它的都可以实现了。

在上述代码实现中,设置从蓝牙麦克风中录音时,一直是静音状态。多次修改采样率、声道数都无法正常收音,差点放弃。后来想到腾讯会议时,是可以指定从蓝牙耳机收音的,因此一定有办法。

经过了解,蓝牙设备有三种类型:

  • A2DP (Advanced Audio Distribution Profile)
  • SCO (Synchronous Connection Oriented Link)
  • BLE(Bluetooth Low Energy)

我手里的蓝牙话筒JBL KMC300连接后,设备只有A2DP类型的一种播放设备,它的麦克风实际只是在话筒扬声器里回放,并不能通过麦克风录音;

另外两款蓝牙耳机有SCO录音设备、SCO播放设备、A2DP播放设备三种。其中A2DP播放设备与其它播放设备使用方法类似,SCO两个设备无论是录音还是放音,都是静音状态;

BLE类型设备我手上没有;

经过多次尝试,要想从SCO设备录音,需要开启Sco模式。老版本的办法:

AudioManager.startBluetoothSco();

新版本(34以后)的办法:

AudioManager.setCommunicationDevice(device);

比较奇怪的是setCommunicationDevice只能设置输出音频。当仅仅是将setCommunicationDevice设置为输出音频时,存在蓝牙麦克风>手机内置扬声器不收音的情况。

解决办法是如果输入设备是SCO时,找到对应的SCO输出设备,用setCommunicationDevice设置,即使这个输出设备并不是我们指定的输出设备。

实现代码如下:


    if (InputDeviceInfo != null && InputDeviceInfo.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {

        for (AudioDeviceInfo btDevice : audioManager.getAvailableCommunicationDevices()) {

            if (btDevice.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
                audioManager.setCommunicationDevice(btDevice);
            }
        }
    }

参考

https://developer.android.com/reference/android/media/AudioManager#setCommunicationDevice(android.media.AudioDeviceInfo)

https://github.com/google/oboe/wiki/TechNote_BluetoothAudio

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值