Android:通过 Sco 蓝牙耳机播放声音

发布于 2024-12-01 19:40:21 字数 2429 浏览 0 评论 0原文

在过去的几天里,我一直试图通过我的 Android 手机通过我的 sco 蓝牙耳机播放任何声音。我这个项目的最终目标是最终制作一个车库门开启器,但首先我需要能够通过耳机播放声音。

以下是我正在使用的当前代码的基础:

==Manifest==
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />


==Code==
    audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

    audioManager.setMode(AudioManager.MODE_IN_CALL);
    audioManager.startBluetoothSco();
    audioManager.setBluetoothScoOn(true);

    short[] soundData = new short [8000*20];
    for (int iii = 0; iii < 20*8000; iii++) {
        soundData[iii] = 32767;
        iii++;
        soundData[iii] = -32768;
    }

    audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
            8000, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, soundData.length
            * Short.SIZE, AudioTrack.MODE_STATIC);
    audioTrack.write(soundData, 0, soundData.length);
    audioTrack.play();

在运行此代码之前,我将蓝牙耳机与手机配对并连接。我已经通过拨打我的语音信箱验证了它的工作原理。然而,当我运行代码时,任何地方都没有声音。

以下是不同代码行的效果:

当我刚刚运行我的应用程序时:

    audioManager.setMode(AudioManager.MODE_IN_CALL);

无论我做什么,这一行都会使我的所有声音停止工作,因此通常会被注释掉。

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

这两行使声音停止从前置扬声器中发出,并使我的耳机发出咔哒声和嘶嘶声,就像它已打开但没有输出一样。

AudioManager.STREAM_VOICE_CALL

这是我对 AudioTrack 构造函数的调用的一部分,但它有很大的不同。由于此设置为 STREAM_VOICE_CALL,声音从前置扬声器发出,如果我将其设置为 STREAM_MUSIC,则声音从后置扬声器发出。

当我在通话期间打开应用程序时:

    audioManager.setMode(AudioManager.MODE_IN_CALL);

在通话期间,此行无效,因为 MODE_IN_CALL 已设置。但不同的是,我的声音与通话混合在一​​起,而通常它根本不播放。

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

这些与它们的对应部分一起控制音频的来源。如果我关闭这些功能,我的声音和电话呼叫将来自前置扬声器,如果我打开这些功能,电话呼叫将来自我的耳机,并且我的声音会丢失。

至于为什么我的代码不起作用,老实说我不知道​​。我相信我已经完成了使用 startBluetoothSco() 的清单。

Even if a SCO connection is established, the following restrictions 
apply on audio output streams so that they can be routed to SCO headset: 
- the stream type must be STREAM_VOICE_CALL - the format must be mono - 
the sampling must be 16kHz or 8kHz

那么,有人知道我做错了什么吗?有一次我设法让声音通过耳机播放,但当我忘记停止()我的 AudioTrack 时,它只是一个短音,所以我不得不假设这是一个故障。

For the past few days I have been trying to play any sound over my sco bluetooth headset from my android phone. My final goal with this project is to eventually make a garage door opener, but first I need to be able to play sound over the headset.

Here is the basis of the current code I'm using:

==Manifest==
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />


==Code==
    audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

    audioManager.setMode(AudioManager.MODE_IN_CALL);
    audioManager.startBluetoothSco();
    audioManager.setBluetoothScoOn(true);

    short[] soundData = new short [8000*20];
    for (int iii = 0; iii < 20*8000; iii++) {
        soundData[iii] = 32767;
        iii++;
        soundData[iii] = -32768;
    }

    audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
            8000, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, soundData.length
            * Short.SIZE, AudioTrack.MODE_STATIC);
    audioTrack.write(soundData, 0, soundData.length);
    audioTrack.play();

Before I run this, I pair my bluetooth headset to my phone and have it connected. I have verified it works by calling my voicemail. When I run my code however, no sound comes from anywhere.

Here are the effects of the different lines of code:

When I'm just running my app:

    audioManager.setMode(AudioManager.MODE_IN_CALL);

This line makes all of my sound stop working no matter what I do, so it is typically commented out.

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

These two lines make the sound stop coming out of the front speaker and make my headset click and hiss like it's turned on but there's no output.

AudioManager.STREAM_VOICE_CALL

This is part of my call to the AudioTrack constructor, but it makes quite a difference. Since this is set to STREAM_VOICE_CALL the sound comes out of the front speaker, if I set this to STREAM_MUSIC, the sound comes out the back speaker instead.

When I open my app during a call:

    audioManager.setMode(AudioManager.MODE_IN_CALL);

During a call, this line has no effect because MODE_IN_CALL was already set. But what's different however is that my sound is mixed with the phone call, whereas normally it doesn't play at all.

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

These, with their counterpart off halves, control where the audio is coming from. If I turn these off, my sound and the telephone call come from the front speaker, with these on, the telephone call comes from my headset and my sound is lost.

As to why my code is not working, I honestly have no idea. I believe I have fulfilled the checklist for using startBluetoothSco().

Even if a SCO connection is established, the following restrictions 
apply on audio output streams so that they can be routed to SCO headset: 
- the stream type must be STREAM_VOICE_CALL - the format must be mono - 
the sampling must be 16kHz or 8kHz

So, does anyone have an idea of what I am doing wrong? There was one time that I managed to get my sound to play through the headset, but it was only a short tone when I forgot to stop() my AudioTrack so I have to assume it was a glitch.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光礼记 2024-12-08 19:40:21

我在此页面上找到了解决方案。
仅当套接字连接后,即收到 AudioManager.SCO_AUDIO_STATE_CONNECTED 后,您才必须调用 audioManager.setMode(AudioManager.MODE_IN_CALL);。我可以在运行 Android 2.2.2 的 Spica 上听到 TTS。

编辑:
这是我的(旧的)实现:

public class BluetoothNotificationReceiver
extends BroadcastReceiver
{   

    /**
     * 
     */
    public BluetoothNotificationReceiver(Handler h)
    {
        super();
        bnrHandler = h;
    }

    /* (non-Javadoc)
     * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
     */
    @Override
    public void onReceive(Context arg0, Intent arg1)
    {
        String action = arg1.getAction();
        if (action.equalsIgnoreCase(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED))
        {
            int l_state = arg1.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
            Log.d("bnr", "Audio SCO: " + AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
            switch(l_state)
            {
            case AudioManager.SCO_AUDIO_STATE_CONNECTED:
            { 
                Log.i("bnr", "SCO_AUDIO_STATE_CONNECTED");
            }
            break;
            case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
                { 
                    Log.e("bnr", "SCO_AUDIO_STATE_DISCONNECTED");                   
                }
            break;
            default: Log.e("bnr", "unknown state received:"+l_state);
            }
        }
        else
            Log.e("bnr", "onReceive:action="+action);
    }
}

我不知道它是否仍然可以使用新的 API。

I found the solution on this page.
You have to call audioManager.setMode(AudioManager.MODE_IN_CALL); only after the socket is connected, i.e., you received AudioManager.SCO_AUDIO_STATE_CONNECTED. I could hear the TTS on my Spica running android 2.2.2.

Edit:
Here is my (old) implementation:

public class BluetoothNotificationReceiver
extends BroadcastReceiver
{   

    /**
     * 
     */
    public BluetoothNotificationReceiver(Handler h)
    {
        super();
        bnrHandler = h;
    }

    /* (non-Javadoc)
     * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
     */
    @Override
    public void onReceive(Context arg0, Intent arg1)
    {
        String action = arg1.getAction();
        if (action.equalsIgnoreCase(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED))
        {
            int l_state = arg1.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
            Log.d("bnr", "Audio SCO: " + AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
            switch(l_state)
            {
            case AudioManager.SCO_AUDIO_STATE_CONNECTED:
            { 
                Log.i("bnr", "SCO_AUDIO_STATE_CONNECTED");
            }
            break;
            case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
                { 
                    Log.e("bnr", "SCO_AUDIO_STATE_DISCONNECTED");                   
                }
            break;
            default: Log.e("bnr", "unknown state received:"+l_state);
            }
        }
        else
            Log.e("bnr", "onReceive:action="+action);
    }
}

I don't know if it is still working with the new APIs.

甜柠檬 2024-12-08 19:40:21

尝试将音频管理器设置为 AudioManager.MODE_NORMAL。这对我有用。

Try setting the audiomanager to AudioManager.MODE_NORMAL. Thos worked for me.

一梦等七年七年为一梦 2024-12-08 19:40:21

添加到清单:

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />

Add to manifest:

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
时间海 2024-12-08 19:40:21

我实际上设法解决了这个问题。问题是我通过耳机播放的音调频率太高。我通过简单地将创建音频文件的代码加倍来修复它,使其变为 HIGH HIGH LOW LOW 而不是 HIGH LOW HIGH LOW。

I actually managed to fix this. The problem was that my pitch that I played over the headset was too high of a frequency. I fixed it by simply doubling up the code that creates the audio file so that it goes HIGH HIGH LOW LOW instead of HIGH LOW HIGH LOW.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文