I am currently working on an Android audio visualizer using connected smart home devices (such as Philips hue) to visualize music. I have trouble compensating the delay caused by bluetooth speakers.
I have noticed, that the Youtube app, in difference to many other video streaming apps, has almost no delay between audio and video, when using bluetooth speakers.
I figure, that they must compensate for the bluetooth latency by adjusting (delaying) the video signal.
Is there a reasonable way of detecting or approximating the latency/delay of bluetooth speakers?
Thank you very much for you help!!
Best,
Stefan
This would not work for Bluetooth speakers. However, I have been able to measure the audio latency of a Bluetooth dongle using Google's Dr. Rick O'Rang loopback dongle, using Glenn Kasten test app.
AVDTP 1.3 protocol supports delay reporting. Try looking to see if Android exports this data.
It's in the somewhere: AVDT_PSC_DELAY_RPT is present in https://android.googlesource.com/platform/system/bt/+/master/stack/include/avdt_api.h#153.
I'm considering building an Android app that allows for streaming audio via bluetooth to and from the Android phone. I've read similar questions on Stackoverflow before, and based on my understanding, A2DP cannot be used as Android can't become an A2DP sink.
In theory, I believe that a profile such as HFP or HFP AG should allow for bidirectional audio streams. In the Android API, is there a way to force a bluetooth pairing to follow this profile, or does the OS decide which profile to use (such as forcing HFP only when there's a phone call going on)?
I've been able to achieve what I wanted using RFCOMM-based SPP. In order to send audio to the external device, I use the AudioRecord API to record PCM-16 audio to stream audio realtime over Bluetooth. In order to receive audio, I spawn a thread that is responsible for outputting audio to the speaker using the AudioTrack API (in streaming mode)
We are developing the Android Framework, and the default of the audio output is HDMI.
When the bluetooth is connected with the Android, the audio output will be redirected to the bluetooth via A2DP protocol. How can we route the audio to the bluetooth speaker and the HDMI output at the same time? We have looked framework/base/media/java/android/media/AudioService.java and the frameworks/av/services/audioflinger/AudioFlinger.cpp, but I have no idea now. Does someone has the experience? Thanks!
I am quite certain that this is not possible to do.
I am completely convinced that this is something that you shouldn't do.
When you send audio over A2DP it is re-encoded, it is not the same audio stream that the one you send over HDMI.
They will also be out of sync, since you have completely different delays between A2DP and HDMI.
I'm working on an audio recorder app that uses a bluetooth mic to record audio on to an Android device (Nexus 7 - rooted Android 4.4.2). It's currently implemented on HFP and everything is working fine. The bluetooth mic is implemented with Bluegiga's WT32 bluetooth module + a mic input, audio quality via HFP isn't great but it's sufficient for now.
However, I'm now trying to change the bluetooth profile to A2dp, since there are two mic inputs (L/R) and WT32 supports A2dp (source). After much research I found that stock Android doesn't support A2dp (sink), and it's possible to modify Android's bluetooth stack to enable A2dp (sink).
What I don't understand is how does one access and modify the bluetooth stack. It would be nice if someone with an answer is able to break-down the steps to achieve this.
I've tried following the answer to this question:
Receive audio via Bluetooth in Android, yet I can't seem to find the appropriate file to modify. Actually, I don't even know if I'm looking into the right folder. I've looked through the devices file via Android-studio's DDMS-File Explorer.
ps, I'm still fairly new with Android app development, so I may have misused some of the terminologies and I apologies in-advance for that.
So the above answer isn't totally correct.
The following is how it breaks down:
HAL, is the hardware abstraction layer that implements the actual Bluetooth state machines in c/cpp code, as such it controls the various state machines for A2dp, HFP, GATT, SPP, AVRCP, etc. services. Each of these services also reference SMP and ATT files for controlling the actual Bluetooth server or client databases, and there security.
HCI, is where the actual work gets done. the HAL doesn't really do anything, it assembles the complex data messages that get sent along a tty serial (either spi, or UART) to an inter-network connected chip on the PCBA via the methods used in the HCI layer, which can be found in the "BTE" layer in /external/bluetooth/bluedroid/ directory of an android compiling trunk from AOSP 4.2.2 to current. - currently there are several manufacturers of these chips but they are mostly all Broadcom based ic's packaged in a dual, or triple radio package that contains a wifi, Bluetooth 4.0 Smart, and Bluetooth 4.0 radio.
It is possible to do what you are trying to do, but you would need to include hardware.so, and bluetooth_jni.so into an NDK/JNI package/project that goes with your apps, and registers via the calls from the .cpp files for each of the Bluetooth services found in "Packages/apps/Bluetooth/jni", you would then handle the registration in your NDK library of 'com_android_bluetooth_a2dp.cpp', and 'com_android_bluetooth_avrcp.cpp', as their appropriately typed objects.
The other issue is, you will need to implement your own custom A2DP stack, as the Android Bluedroid stack only has bit's and piece's of the Sink role implemented in the frameworks while the A2DP role has a full implementation of Source role. Additionally, depending what you actually intend to do with your Bluetooth A2DP sink implementation you will need to implement AVRCP as well - as per the Bluetooth SIG (special interest group), there are inter-connectivity requirements between Bluetooth devices that will lead to major issues if you implement sink role, without AVRCP "remote control target device" and "remote control control device", as the sink role ATT commands from Bluetooth over A2DP (or any Bluetooth service/profile) execute certain handshakes during the service discovery process, when the associated gateway ( the connecting device ), executes a capabilities request the A2DP service is expected to implement i/o capabilities for Start Stop commands, and possibly skip/track advance commands.
Additional to all of this, when implementing A2DP you will need to choose whether you will be handling PCM streams or AAC streams. If you are handling AAC streams (or DRM protected PCM streams for that matter, which anything like Pandora, spotify, etc. uses), you need to implement the SBC Encoder or Decoder appropriate to you implementation, else all you will have is a bunch of encrypted data. Also, be sure to implement the bitrate at the appropriate speed for your devices AudioManager implementation, some phones use 48,000hZ and some us 44,100hZ, this is important if you want high quality audio as generally most PCM A2DP implementations that are utilizing Surround Sound 7.1+ will require 48,000hZ as well as AAC encoding/decoding.
I hope this provides you with some insight.
https://android-review.googlesource.com/#/c/98161/ implements A2DP Sink. It works on Nexus 5. You can try it.
This is actually what I'm trying to do for a long time...
The reason you can't find the configuration file is because Google replaced the Bluetooth stack from BlueZ with a new stack built by Google and Broadcom. The new stack uses a different configuration file, which I don't know how to tinker with.
If you are serious about it, the closest thing I found to start with is the official introduction for the bluetooth framework on Android:
https://source.android.com/devices/bluetooth.html
There are lots of changes happened in Android OS over the time.
As of Android O (Android 8.*), sink profiles are partially supported by Google. Such as Audio sink will easily work if enabled in profile. It looks like the higher layer of BT is kind of implementation complete at the framework, which is in the form of App i.e. packages/app/Bluetooth (with some bugs but still works). But all profiles are not completed at framework lower layer via HAL interfaces which is btif framework (such as btif_rc.cpp, etc which you can look at Android source) and which is the replacement to older Bluez stack by Google.
As I said BT sink is partially implemented and is in work in progress state. BT sink such as Audio will easily work if enabled as sink profile but not all such as AVRCP will not work. At present, I saw the issue with AOSP code that incoming traffic from the remote device to Android works but outgoing traffic from Android to the remote device doesn't work (upon which AVRCP profile works) as remote device object is not maintained in the stack and so JNI calls from app/Bluetooth fails with null device at btif_*.cpp files. For example, send pass-through commands doesn't work.
So, we may see Bluetooth sink profiles working in future.
If you want to explore more check AOSP,
Services at packages/app/Bluetooth/
HAL's at system/bt/btif/
I am trying to access, programatically, the data received from 2 microphones on Android devices.
This arises several questions:
Are there shipping Android devices with 2 microphones (e.g. for stereo recording)? I know there are devices with 2 microphones for echo cancellation / noise reduction, but as far as I could find they can be accessed as a single microphone for any programatic purpose.
Are there devices with a microphone / headphone socket supporting stereo external microphones?
Assuming any of the above is positive, is there a way to know what is the currently operating microphone setup?
I will appreciate any response!
Thanks,
Yoav
I only found out that e.g. once you plug in wired headset with microphone it doesn't matter what AudioSource you specify in you code - it always give you the audio stream form headset mic. I tried to get access to internal mic using AudioSource.CAMCORDER but without luck. I haven't tried with wireless (BT) headset though. However if I plugin headphones (w/o mic) it uses internal microphone. At least this is the outcome on my SGS2 with ICS 4.0. If somebody find a workaround I would be happy to hear as well.
I haven't tried yet, but maybe the Native Developement Tools can allow you to access any microphone you want from low level.
If you want to make things a bit simpler, you could consider using OpenSL ES for Android, although i have no idea if it provides low-level microphone control.