简体   繁体   English

Android蓝牙音频播放和录制

[英]Android Bluetooth Audio Play and Record

I have a bluetooth headset (which can play stereo music) connected to my android phone (Android 4.4.3). 我有一个蓝牙耳机(它可以播放立体声音乐)连接到我的Android手机(Android 4.4.3)。 Now I want my code to play a stereo music and record audio from that headset, both at high sampling rates (44100). 现在我希望我的代码能够以高采样率(44100)播放立体声音乐并从该耳机录制音频。 I followed the solutions in the following posts. 我按照以下帖子中的解决方案。

How to record sound using bluetooth headset 如何使用蓝牙耳机录制声音

Capture Audio through Bluetooth Headset paired with Android Device 通过与Android设备配对的蓝牙耳机捕获音频

My basic code looks like this. 我的基本代码看起来像这样。

Permissions: 权限:

android.permission.WRITE_EXTERNAL_STORAGE
android.permission.RECORD_AUDIO
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.BROADCAST_STICKY
android.permission.BLUETOOTH

Code to turn on Bluetooth Sco: 打开蓝牙Sco的代码:

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);
    }
}

Code to play a stereo music: 播放立体声音乐的代码:

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();
}

Code to record audio: 录制音频的代码:

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
}

How here are the problems. 这是怎么回事。

Case 1: if I call the following sequence 案例1:如果我调用以下序列

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

The music plays through the phone's speaker rather than the bluetooth headset. 音乐通过手机的扬声器而不是蓝牙耳机播放。 The recorder can record sound from the bluetooth headset's mic but at very low sampling rate (8kHz). 录音机可以录制来自蓝牙耳机麦克风的声音,但采样率非常低(8kHz)。

Case 2: if I do not call turnOnBluetooth(), ie, execute the following sequence 情况2:如果我不调用turnOnBluetooth(),即执行以下序列

playMusic();
recordAudio();

The music plays through the bluetooth headset now, but the recorder only records audio from the phone's built-in mic. 音乐现在通过蓝牙耳机播放,但录音机仅记录手机内置麦克风的音频。

I also tried to change the mode of the AudioManager by 我还试图改变AudioManager的模式

m_amAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);

and set the audio route by 并设置音频路由

m_amAudioManager.setSpeakerphoneOn(false);
m_amAudioManager.setBluetoothScoOn(true);

The result is the same to case 1. And if I set 结果与案例1相同。如果我设置

m_amAudioManager.setBluetoothScoOn(false);

It repeats case 2. 它重复案例2。

I have worked on this for a few days and the above behavior is puzzling me a lot. 我已经为此工作了几天,上面的行为让我很困惑。 Have I missed anything in audio settings? 我在音频设置中遗漏了什么吗? Or do I need more sophisticated control with the bluetooth headset's settings? 或者我需要使用蓝牙耳机的设置进行更复杂的控制? Thanks for reading this and any suggestion is welcome. 感谢您阅读本文,欢迎任何建议。 Thank you! 谢谢!

This may be too late, but here it is my solution. 这可能为时已晚,但这是我的解决方案。

you need to setup the mediarecorder as follows 您需要按如下方式设置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);

in order to play on the bluetooth headset you need to turn on bluetoothsco and turnoff speakers 为了在蓝牙耳机上播放,您需要打开蓝牙耳机和关闭扬声器

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

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

for recording at other frequency that 8KHz you need to use the AudioRecorder class 用于以8KHz的其他频率录制您需要使用AudioRecorder类

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM