Cảnh báo: Đây là hướng dẫn nâng cao sửa đổi Bluetooth stacks trên Android - đọc kỹ toàn bộ và làm theo chính xác hướng dẫn.
Dù tai nghe Bluetooth và audio Bluetooth phổ biến, nó vẫn vấn đề cho audiophile vì Bluetooth chứng minh giảm chất lượng âm thanh, bit thông tin âm thanh và tần số mất đi khi stream qua Bluetooth.
Đây là lý do một số hãng tung ra codec aptX và LDAC, tăng chất lượng so với codec SBC Bluetooth tiêu chuẩn hỗ trợ bởi mọi tai nghe và hầu hết thiết bị Bluetooth - tuy nhiên thiết bị aptX/LDAC đắt hơn nhiều do phí license, consumer trả tiền dài hạn.
Chất lượng âm thanh thấp của codec SBC Bluetooth do giới hạn nhân tạo của tất cả Bluetooth stacks hiện tại và cấu hình tai nghe, và giới hạn này có thể bypass trên mọi thiết bị hiện có.
Nếu bạn quan tâm audio Bluetooth, cuối hướng dẫn sẽ chỉ cách dump log audio Bluetooth và kiểm tra để xem chất lượng âm thanh và tần số bạn nhận được từ Bluetooth receiver Android.
Phần lớn hướng dẫn tập trung vào vài tweak đơn giản và cách đọc output audio Bluetooth để tăng chất lượng output codec SBC tiêu chuẩn đáng kể - đọc kỹ toàn bộ vì khá giáo dục và có nhiều thứ flash/tweak tùy model thiết bị.
Cuối hướng dẫn có danh sách Bluetooth stacks đã patch sẵn cho nhiều thiết bị Android phổ biến - flash trong recovery như file .zip flashable bình thường - nếu không có thiết bị của bạn, làm theo hướng dẫn sửa Bluetooth stacks trên Android.
Thông tin kỹ thuật ngắn về codec SBC
SBC có nhiều tham số khác nhau được thương lượng khi thiết lập kết nối:
- Loại và số kênh âm thanh: Joint Stereo, Stereo, Dual Channel, Mono;
- Số band tần số: 4 hoặc 8;
- Số audio blocks trong một packet: 4, 8, 12, 16;
- Thuật toán phân bổ bit quantization: Loudness, SNR;
- Bit pool tối đa và tối thiểu dùng trong quantization: thường 2-53.
Decoder bắt buộc hỗ trợ mọi tổ hợp tham số. Encoder có thể chỉ implement một phần.
Bluetooth stacks hiện tại thường thương lượng profile sau: Joint Stereo, 8 bands, 16 blocks, Loudness, bitpool 2..53. Profile này encode audio 44.1 kHz với bitrate 328 kbps.
Tham số bitpool ảnh hưởng trực tiếp bitrate trong cùng profile: càng cao, bitrate càng cao, chất lượng càng tốt.
Tuy nhiên, bitpool không gắn với profile cụ thể. Bitrate cũng chịu ảnh hưởng lớn bởi tham số khác: loại kênh âm thanh, số band tần số, số audio blocks. Có thể tăng bitrate gián tiếp bằng cách thương lượng profile non-standard, không đổi bitpool.
Ví dụ: Dual Channel encode kênh riêng biệt, dùng toàn bộ bitpool cho mỗi kênh. Buộc thiết bị dùng Dual Channel thay Joint Stereo cho bitrate gần gấp đôi ở cùng max bitpool, 617 kbps.
Cảm thấy bitpool nên là biến nội bộ. Là lỗi thiết kế spec A2DP v1.2 mà bitpool không gắn với tham số codec khác, chỉ định nghĩa là giá trị global.
Các giá trị Bitpool và Bitrate cố định xuất phát từ giá trị khuyến nghị cho audio chất lượng cao. Nhưng khuyến nghị không phải lý do giới hạn profile ở các giá trị đó.
A2DP spec v1.2 (hoạt động 2007-2015) yêu cầu tất cả decoder hoạt động đúng với bitrate lên tới 512 kbps:
The decoder of the SNK shall support all possible bitpool values that do not result in the excess of the maximum bit rate. This profile limits the available maximum bit rate to 320kb/s for mono, and 512kb/s for two-channel modes.
Trong spec mới không có giới hạn bitrate. Giả định tai nghe hiện đại sau 2015 hỗ trợ bitrate lên tới 1000 kbps.
Với lý do nào đó, tất cả Bluetooth stacks đã test (Linux PulseAudio, Android, Blackberry, macOS) có giới hạn nhân tạo max bitpool, ảnh hưởng trực tiếp max bitrate. Nhưng không phải vấn đề lớn nhất, hầu như mọi tai nghe cũng giới hạn max bitpool 53.
Hầu hết thiết bị chạy ổn trên Bluetooth stack sửa đổi với bitrate 507 kbps, không gián đoạn, không kẽo. Nhưng bitrate như vậy không bao giờ được thương lượng trong điều kiện bình thường, với stock Bluetooth stacks.
***Yêu cầu test theo hướng dẫn dưới: bluetooth-dualchannel-test-ubuntu-18.04.1-desktop-amd64.iso.torrent
Cách test trên PC
Test tương thích tai nghe SBC high bitrate dễ nhất trên PC với Bluetooth adapter. Tôi chuẩn bị Ubuntu image với Bluetooth stack sửa đổi, chạy được trên virtual machine (kết nối Bluetooth adapter như USB device trong VM, cũng chạy với adapter built-in laptop) hoặc boot từ USB flash drive. Image dùng profile: Dual Channel, 8 bands, 16 blocks, Loudness, bitpool 2..41, 44.1 kHz, cho bitrate 485 kbps.
Chạy trong VM
- Tải Virtualbox và Virtualbox Extension Pack: https://www.virtualbox.org/wiki/Downloads;
- Cài Virtualbox, chạy;
- Cài Extension Pack qua File → Preferences → Extensions;
- Tạo VM mới: Linux, Ubuntu (64-bit), 1024 RAM. Không tạo HDD.
- Vào Settings VM, Storage chọn Controller: IDE, Empty, bấm icon CD → Choose virtual optical disk file;
- Chọn file bluetooth-dualchannel-test-ubuntu-18.04.1-desktop-amd64.iso đã tải;
- Lưu và đóng settings, start VM;
- Right-click icon USB cable góc dưới phải, chọn Bluetooth adapter;
Chạy trên PC thật
Image hỗ trợ boot BIOS/CSM và UEFI.
- Burn image vào USB flash drive bằng Etcher: https://www.balena.io/etcher/. Thao tác này xóa toàn bộ file trên USB.
- Tắt PC;
- Cắm USB, bật PC, bấm nút boot order (thường Esc hoặc F12);
- Chọn USB flash drive.
Thực hiện test
- (khuyến nghị) Double click script "Btsnoop Dump" trên desktop. Bắt đầu capture dữ liệu Bluetooth để phân tích sau. Không đóng terminal.
- Chuyển tai nghe sang pairing mode;
- Click mũi tên góc trên phải, chọn Bluetooth icon → Bluetooth Settings;
- Chọn tai nghe, chờ pairing xong, đóng cửa sổ;
- Đặt âm lượng Ubuntu ~2/3. Giảm volume bằng nút tai nghe vì có thể to sau pairing.
- Mở thư mục "music", phát "testrecord1.flac";
- (khuyến nghị) Đóng player, đóng terminal. Dừng capture dữ liệu.
- (khuyến nghị) Mở Firefox, upload data dump (btsnoop_hci.btsnoop trên desktop) lên https://btcodecs.valdikss.org.ru/
Có thể nghe nhạc khác trong thư mục music, hoặc upload file riêng;
Tai nghe không nên có kẽo, ngắt quãng âm thanh hay méo mó. Nếu nghe âm thanh chất lượng cao, nghĩa là tai nghe hỗ trợ audio bitrate 485 kbps.
Cách test trên thiết bị Android
Để test từ smartphone/tablet Android cần Bluetooth stack sửa đổi, yêu cầu root.
Cách capture Bluetooth data dump trên Android
- Tắt Bluetooth;
- Trong Developer Settings, bật switch "Enable Bluetooth HCI snoop log";
- Bật Bluetooth, kết nối tai nghe qua menu Bluetooth (QUAN TRỌNG! Không cho auto connect!);
- Phát đoạn audio ngắn;
- Vào developer settings, tắt switch "Enable Bluetooth HCI snoop log";
- Sẽ có file /storage/emulated/0/btsnoop_hci.log hoặc /data/misc/bluetooth/logs/btsnoop_hci.log. Nếu thiếu, mở /etc/bluetooth/bt_stack.conf bằng text editor xem path trong option BtSnoopFileName.
Tai nghe không nên có kẽo, ngắt quãng, méo mó. Nếu nghe âm thanh chất lượng cao với library patch, nghĩa là tai nghe hỗ trợ audio bitrate 512 kbps.
Làm theo chính xác thuật toán trên. Đặc biệt, nếu tắt tai nghe hoặc ngắt kết nối sau pairing, quan trọng: kết nối thủ công từ Bluetooth settings, KHÔNG cho auto connect!
Thiết bị hỗ trợ ít nhất 512 kbit/s SBC
- 1MORE iBFree
- JBL Everest 310
- JBL Everest 700
- Skullcandy HESH 3
- Sony WI-C400
- Sony MDR-1ABT
- Sony MDR-ZX770BT
- Sony MDR-XB650BT
- Sony MDR-XB950B1
- Sony SBH50
- Bluedio T4s (Bitpool max 39. Phản hồi không hỗ trợ Dual Channel, nhưng chạy nếu ép, 462 kbit/s. Không tuân thủ spec A2DP.)
- Bluedio T5 (Phản hồi không hỗ trợ Dual Channel, nhưng chạy nếu ép. Không tuân thủ spec A2DP.)
- Bluedio T6 (Phản hồi không hỗ trợ Dual Channel, nhưng chạy nếu ép. Không tuân thủ spec A2DP. Chip Adopt Max 97220.)
- Marshall Major II Bluetooth
- Overdrive RealForce D1
- Edifier W830BT
- DEXP BT-250
- Logitech BT Adapter
- Noname automotive head unit (chip CSR8645)
- Sony DSX-A400BT automotive head unit
Thiết bị hỗ trợ SBC cao hơn 512 kbit/s
- JBL Everest 310 (617-660 kbit/s)
- Sony WI-C400 (576 kbit/s)
- Sony MDR-ZX770BT (617-660 kbit/s)
- Marshall Major II Bluetooth (617-660 kbit/s)
- Overdrive RealForce D1 (730 kbit/s, dual channel, 4 subbands)
Thiết bị KHÔNG chạy high bitrate hoặc Dual Channel
- Harper HB-202 (kẽo; chip Beken BK3256)
- Sony Ericsson MW600 (méo tần số cao, kẽo; thiết bị 2009)
Tại sao quan trọng: SBC 328k và 485k vs aptX
Khác với niềm tin phổ biến về chất lượng aptX, trong một số trường hợp aptX tạo chất lượng kém hơn SBC 328k tiêu chuẩn.
SBC phân bổ bit quantization động cho band tần số, cơ chế "bottom-to-top". Nếu toàn bộ bitrate dùng cho tần số thấp và trung, tần số cao bị "cắt" (im lặng).
aptX quantization band tần số với số bit cố định, làm nó thành codec constant bitrate: 352 kbps cho 44.1 kHz, 384 kbps cho 48 kHz. Nó không thể "chuyển bit" cho tần số cần thiết nhất. Khác với SBC, aptX không "cắt" tần số, nhưng thêm nhiễu quantization, giảm dynamic range, đôi khi gây kẽo. SBC ngược lại, "ăn chi tiết" - loại bỏ vùng yên tĩnh nhất.
Trung bình, so với SBC 328k, aptX làm ít méo hơn trên nhạc dải tần rộng, nhưng trên nhạc dải tần hẹp và dynamic range rộng, SBC 328k đôi khi thắng.
Xét trường hợp đặc biệt: bản ghi piano. Spectrogram:

Năng lượng lớn nằm ở 0-4 kHz, kéo dài tới 10 kHz.
Spectrogram file aptX:

Đây là SBC 328k:

Thấy SBC 328k định kỳ cắt hoàn toàn dải trên 16 kHz, dùng toàn bộ bitrate cho dải dưới giá trị này. Tuy nhiên aptX gây méo nhiều hơn vào phổ tần số nghe được, thấy trên spectrogram trừ original từ aptX (càng sáng, càng méo):

Trong khi SBC 328k gây ít méo hơn tín hiệu 0-10 kHz, phần còn lại bị cắt:

Bitrate 485k cho SBC đủ lưu toàn bộ dải tần số, không cắt band.

SBC 485k trên sample này tốt hơn aptX đáng kể ở 0-15 kHz, và khác biệt nhỏ nhưng nhận thấy ở 15-22 kHz (càng tối, càng ít méo):

Chuyển sang high-bitrate SBC, bạn nhận được âm thanh vượt trội aptX hầu hết thời gian, trên mọi tai nghe.
- original_and_aptx.zip
- sbc.zip
Cách sửa đổi Bluetooth Stacks trên Android 5 - 7
Các sửa đổi áp dụng cho Bluetooth stacks stock Android: Bluedroid (Android 5) và Fluoride (Android 6-7). Stack sửa đổi bởi Qualcomm không hỗ trợ.
Thay Joint Stereo bằng Dual Channel trong config SBC tiêu chuẩn
android/platform/external/bluetooth/bluedroid/btif/co/bta_av_co.c:99
Code:
const tA2D_SBC_CIE btif_av_sbc_default_config = {
BTIF_AV_SBC_DEFAULT_SAMP_FREQ, /* samp_freq */
A2D_SBC_IE_CH_MD_JOINT, /* ch_mode */
A2D_SBC_IE_BLOCKS_16, /* block_len */
A2D_SBC_IE_SUBBAND_8, /* num_subbands */
A2D_SBC_IE_ALLOC_MD_L, /* alloc_mthd */
BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
};
Thay A2D_SBC_IE_CH_MD_JOINT bằng A2D_SBC_IE_CH_MD_DUAL.
Tăng ưu tiên Dual Channel
android/platform/external/bluetooth/bluedroid/btif/co/bta_av_co.c:41
Code:
if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_JOINT) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_JOINT; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO;
Di chuyển if với A2D_SBC_IE_CH_MD_DUAL lên đầu.
Vô hiệu hóa hoặc tăng giới hạn bitrate
Android bluetooth stack không chỉ giới hạn bitpool, còn giới hạn bitrate 328 kbit/s. Nếu tai nghe hỗ trợ bitpool 53 cho 48 kHz, Android sẽ giảm bitpool để vừa 328 kbit/s. Điều này xảy ra SAU thương lượng codec, ở giai đoạn encoding, không tính bitpool trong packet Bluetooth SetCapabilities.
android/platform/external/bluetooth/bluedroid/btif/src/btif_media_task.c:172
Code:
#define DEFAULT_SBC_BITRATE 328
Thay bằng 512.
(Chỉ để test) Vô hiệu hóa giới hạn MTU
Cần cho bitrate cao hơn ~580 kbit/s.
btif/src/btif_media_task.c:174
Code:
/* 2DH5 payload size of 679 bytes - (4 bytes L2CAP Header + 12 bytes AVDTP Header) */ #define MAX_2MBPS_AVDTP_MTU 663
Cách sửa đổi Bluetooth Stacks trên Android 8 - 9
Các sửa đổi chưa test nhưng nên chạy.
Thêm hỗ trợ Dual Channel vào A2DP SBC Source
/platform/system/bt/stack/a2dp/a2dp_sbc.cc:55
Code:
/* SBC SRC codec capabilities */
static const tA2DP_SBC_CIE a2dp_sbc_caps = {
A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */
(A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_JOINT), /* ch_mode */
(A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | A2DP_SBC_IE_BLOCKS_4), /* block_len */
A2DP_SBC_IE_SUBBAND_8, /* num_subbands */
A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */
A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */
A2DP_SBC_MAX_BITPOOL, /* max_bitpool */
BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
};
Thêm A2DP_SBC_IE_CH_MD_DUAL vào ch_mode.
Thay Joint Stereo bằng Dual Channel trong default config
/platform/system/bt/stack/a2dp/a2dp_sbc.cc:82
Code:
/* Default SBC codec configuration */
const tA2DP_SBC_CIE a2dp_sbc_default_config = {
A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */
A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */
A2DP_SBC_IE_BLOCKS_16, /* block_len */
A2DP_SBC_IE_SUBBAND_8, /* num_subbands */
A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */
A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */
A2DP_SBC_MAX_BITPOOL, /* max_bitpool */
BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
};
Thay A2DP_SBC_IE_CH_MD_JOINT bằng A2DP_SBC_IE_CH_MD_DUAL.
Tăng ưu tiên Dual Channel
/platform/system/bt/stack/a2dp/a2dp_sbc.cc:1155
Code:
static bool select_best_channel_mode(uint8_t ch_mode, tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) {
if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT;
p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
return true;
}
if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO;
p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
return true;
}
if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL;
p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
return true;
}
if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO;
p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
return true;
}
return false;
}
Di chuyển if với A2DP_SBC_IE_CH_MD_DUAL lên đầu.
Tăng giới hạn bitrate
/platform/system/bt/stack/a2dp/a2dp_sbc_encoder.cc:42
Code:
#define A2DP_SBC_DEFAULT_BITRATE 328
Thay bằng 512.
(Chỉ test) Vô hiệu hóa giới hạn MTU
Cần cho bitrate > ~580 kbit/s.
/platform/system/bt/stack/a2dp/a2dp_sbc_encoder.cc:47
Code:
#define MAX_2MBPS_AVDTP_MTU 663