Android蓝牙音频播放和录制

时间:2015-08-04 02:25:34

标签: android audio bluetooth

我有一个蓝牙耳机(它可以播放立体声音乐)连接到我的Android手机(Android 4.4.3)。现在我希望我的代码能够以高采样率(44100)播放立体声音乐并从该耳机录制音频。我按照以下帖子中的解决方案。

How to record sound using bluetooth headset

Capture Audio through Bluetooth Headset paired with Android Device

我的基本代码如下所示。

权限:

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

public void turnOnBluetooth() {
    final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
              int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
              if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
                    System.err.println("bluetooth connected");
                    unregisterReceiver(this);
              } else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) {
                    System.err.println("bluetooth disconnected");
              }
           }
        };

    registerReceiver(broadcastReceiver, new IntentFilter(
            AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));

    try {
        if (m_amAudioManager.isBluetoothScoAvailableOffCall()) {
            if (m_amAudioManager.isBluetoothScoOn()) {
                m_amAudioManager.stopBluetoothSco();
                m_amAudioManager.startBluetoothSco();
                System.err.println("Bluetooth SCO On!");
            } else {
                System.err.println("Bluetooth Sco Off!");
                m_amAudioManager.startBluetoothSco();
            }

        } else {
            System.err.println("Bluetooth SCO not available");
        }
    } catch (Exception e) {
        System.err.println("sco elsepart startBluetoothSCO " + e);
        unregisterReceiver(broadcastReceiver);
    }
}

开启蓝牙Sco的代码:

public void playMusic(){
    this.mediaPlayer = new MediaPlayer();
    this.mediaPlayer
            .setOnCompletionListener(new OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mp.release();
                }
            });
    this.mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().
         getAbsolutePath()+ "/"+ folderName + "/stereo.wav");
    // change type to STREAM_VOICE_CALL can partly solve the problem 
    // but reduces the quality of the music, which is critical in my case
    this.mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    this.mediaPlayer.prepare();
    this.mediaPlayer.start();
}

播放立体声音乐的代码:

public void recordAudio() {
    AudioRecorder recorder = new AudioRecord(
            audioSource,         // MediaRecorder.AudioSource.MIC
            RECORDER_SAMPLERATE, // 44100
            RECORDER_CHANNELS,   // AudioFormat.CHANNEL_IN_MONO
            RECORDER_AUDIO_ENCODING, // AudioFormat.ENCODING_PCM_16BIT 
            bufferSize           // obtained by AudioRecord.getMinBufferSize()
    );
    int i = recorder.getState();
    if (i == 1)
        recorder.startRecording();
    // then read bytes from the recorder
}

录制音频的代码:

turnOnBluetooth();
playMusic();
recordAudio();

这是怎么回事。

案例1:如果我调用以下序列

playMusic();
recordAudio();

音乐通过手机的扬声器而不是蓝牙耳机播放。录音机可以录制来自蓝牙耳机麦克风的声音,但采样率非常低(8kHz)。

案例2:如果我不调用turnOnBluetooth(),即执行以下序列

m_amAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);

音乐现在通过蓝牙耳机播放,但录音机只能录制手机内置麦克风的音频。

我还尝试通过

更改AudioManager的模式
m_amAudioManager.setSpeakerphoneOn(false);
m_amAudioManager.setBluetoothScoOn(true);

并按

设置音频路线
m_amAudioManager.setBluetoothScoOn(false);

结果与案例1相同。如果我设置

<script type="text/javascript">
    require(["dojo/ready","dojo/dom","dojo/dom-attr"], function(ready,dom,domAttr){
        ready(function(){
            var Geo = {};
            if (navigator.geolocation){
                navigator.geolocation.getCurrentPosition(success, error);
            }else{
            }
            function success(position) {
                Geo.lat = position.coords.latitude;
                Geo.lng = position.coords.longitude;
                populateHeader(Geo.lat, Geo.lng);
            }
            function error() {
                console.log("Geocoder failed");
                domAttr.set(dom.byId("criteria_postcode"),"required",true);
            }
            function populateHeader(lat, lng) {
                dom.byId("criteria_latitude").value=Number(lat);
                dom.byId("criteria_longitude").value=Number(lng);
            }
        });
     });
</script>

重复案例2.

我已经为此工作了几天,上面的行为让我很困惑。我在音频设置中遗漏了什么吗?或者我需要使用蓝牙耳机设置进行更复杂的控制?感谢您阅读本文,欢迎任何建议。谢谢!

1 个答案:

答案 0 :(得分:0)

这可能为时已晚,但这是我的解决方法。

您需要按照以下步骤设置mediarecorder

mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
mediaRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder.setOutputFile(AudioSavePathInDevice);

要在蓝牙耳机上播放,您需要打开蓝牙并关闭扬声器

audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();

audioManager.setSpeakerphoneOn(false);
audioManager.setMode(audioManager.MODE_NORMAL);

要以8KHz的其他频率进行录制,则需要使用AudioRecorder类

new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);