kcat / openal-soft

OpenAL Soft is a software implementation of the OpenAL 3D audio API.
Other
2.12k stars 521 forks source link

[Android] Audio device needs to be restarted using Oboe + Bluetooth? #895

Open RusJJ opened 11 months ago

RusJJ commented 11 months ago

Hello! Got another little bit confusing issue using OAL Soft with bluetooth headsets. If your app has already opened device and you're using Oboe backend, connecting to another device (bluetooth headset for example) requires the device to be restarted/resetted (using alcResetDeviceSOFT). Doesnt even happen on OpenSLES. Is there any way to fix this? Seems like ALC_CONNECTED returns true.

kcat commented 11 months ago

What version of OpenAL Soft are you using? The latest release may not detect the device being lost/disconnected, but the current Git version should. I guess OpenSL ES automatically moves output when outputs are added/removed, while whatever Oboe is using needs it done manually.

RusJJ commented 11 months ago

What version of OpenAL Soft are you using?

Always the latest Oboe and OAL Soft

RusJJ commented 11 months ago

UPD: Haven`t really tested it for now. But it looks like ALC_CONNECTED is returning always 0, not 1. Because in the code i see it always resetting the device (doing it manually, resets only if ALC_CONNECTED gives 0). So is ALC_CONNECTED broken and also output device changing handled wrong?

kcat commented 11 months ago

Can you provide a trace log? If the device is disconnecting from OpenAL's point of view, there should be a message about why.

RusJJ commented 11 months ago

I will see that. Later i will give it to you

RusJJ commented 11 months ago

Sorry for being that late, here is the log:

In the log: it was playing the sound, connected bluetooth headset, disconnected it, quit the applciation.

android_log_print.txt

kcat commented 11 months ago

Looking at the log, it seems to be opening the device and starting playback fine, then playback immediately resets without an apparent issue. ALC_CONNECTED should return 1/true during this time with audio playing. Then about 1m20s later, it disconnects and stops:

Sat Aug 26 15:17:22 2023
 [DEBUG][AudioStreamLegacy] onAudioDeviceUpdate() devId 4045 => 4045

Sat Aug 26 15:17:22 2023
 [DEBUG][AudioStreamLegacy] onAudioDeviceUpdate() devId 4045 => 3

Sat Aug 26 15:17:22 2023
 [DEBUG][AudioStreamLegacy] onAudioDeviceUpdate() request DISCONNECT in data callback due to device change

...

Sat Aug 26 15:17:22 2023
 [DEBUG][openal] [ALSOFT] (II) Error was ErrorDisconnected

At that point, ALC_CONNECTED should return false. Calling alcResetDeviceSOFT should attempt to reconnect the device and restart playback (if it returns true, it should be playing again).

Is this not the behavior you're seeing? Are you able to provide the code relating to setting up the device/context, the ALC_CONNECTED check, and alcResetDeviceSOFT call?

RusJJ commented 11 months ago

After 1m20s the application is being closed. Context creation:

const ALCint attr[] = { \
        ALC_FREQUENCY, 44100,
        ALC_HRTF_SOFT, true,
        0 }
 alcCreateContext(device, attr);

Resetting + checking:

bool UpdateALDevice()
{
    const ALCint attr[] = { \
        ALC_FREQUENCY, 44100,
        ALC_HRTF_SOFT, true,
        0 }
    return alcResetDeviceSOFT(pSoundDevice, attr);
}
DECL_HOOKv(ServiceAudioHardware, void* self)
{
    ServiceAudioHardware(self);

    static uint32_t nextCheck = 0;
        logger->Info("ServiceAudioHardware");
    if(*m_snTimeInMilliseconds > nextCheck)
    {
        nextCheck = *m_snTimeInMilliseconds + 500;
        ALCint connected;
        alcGetIntegerv(pSoundDevice, ALC_CONNECTED, 1, &connected);
        if(!connected) UpdateALDevice();
    }
}
RusJJ commented 11 months ago

So, do you have any ideas?

kcat commented 11 months ago

As long as pSoundDevice is a valid handle (i.e. the function isn't being called before the device is open and the variable is set, or after the device is closed or the variable is cleared), I don't see anything wrong there. The device opens and starts normally, then immediately resets without any disconnection, then after about 1m20s the device gets a disconnection error from Oboe and is then closed without another reset.

You can check to make sure alcGetIntegerv succeeded by calling alcGetError(pSoundDevice), though if there's a race condition with pSoundDevice being set, that could erroneously report no error.