- 표준 SBC 코덱의 낮은 음질은 코덱 한계만이 아니라 Bluetooth 스택과 헤드폰 설정의 보수적 제한에서 비롯되며, 기존 기기도 소프트웨어 수정으로 개선 여지가 있음
- 일반 Bluetooth 스택은 44.1kHz 스테레오를 보통 328kbps로 협상하지만, Dual Channel을 강제하면 같은 bitpool 53에서 약 617kbps까지 올라감
- Android 8.1·9 패치는 Bluetooth 기기 설정에 SBC Dual Channel을 HD Audio 옵션처럼 추가하고, EDR 3Mb/s 기기에는 551kbps, EDR 2Mb/s 기기에는 452kbps를 사용함
- 551kbps와 452kbps는 Bluetooth 5-slot 전송 효율을 고려한 값이며, bitpool을 더 올리면 프레임 묶음 수가 줄어 나쁜 무선 환경에서 끊김 가능성이 커짐
- LineageOS, Resurrection Remix, crDroid 사용자는 설정 체크박스로 고비트레이트 SBC를 켤 수 있고, Linux 사용자는 PulseAudio 패치로 더 높은 SBC 비트레이트와 aptX 계열 지원을 얻을 수 있음
SBC 음질이 낮게 들리는 이유
- 일부 무선 헤드폰 사용자는 모든 Bluetooth 오디오 기기가 지원하는 SBC 코덱에서 음질 저하와 고역 부족을 경험함
- aptX나 LDAC 지원 기기와 헤드폰을 사는 방법도 있지만, 해당 코덱은 라이선스 비용이 필요해 기기 가격을 높일 수 있음
- 낮은 SBC 품질의 핵심 원인은 현재 Bluetooth 스택과 헤드폰 설정의 인위적 제한이며, 기존 기기도 소프트웨어 수정으로 우회 가능함
SBC 파라미터와 비트레이트
- SBC는 연결 설정 단계에서 여러 파라미터를 협상함
- 오디오 채널 유형과 개수: Joint Stereo, Stereo, Dual Channel, Mono
- 주파수 밴드 수: 4 또는 8
- 패킷 내 오디오 블록 수: 4, 8, 12, 16
- 양자화 비트 할당 방식: Loudness, SNR
- 양자화에 쓰는 최소·최대 bitpool: 보통 2..53
- 디코더는 이 파라미터 조합을 모두 지원해야 하지만, 인코더는 일부만 구현할 수 있음
- 기존 Bluetooth 스택은 보통 Joint Stereo, 8 bands, 16 blocks, Loudness, bitpool 2..53 조합을 협상하며, 이때 44.1kHz 스테레오 오디오는 328kbps로 인코딩됨
- bitpool은 인코딩 비트레이트를 바꾸는 값으로, 값이 높을수록 비트레이트와 품질이 올라감
- 정확한 bitpool 값과 비트레이트의 대응은 특정 프로파일 안에서만 성립함
- 채널 유형, 주파수 밴드 수, 오디오 블록 수도 비트레이트에 큰 영향을 줌
- Dual Channel은 Stereo나 Joint Stereo와 달리 각 채널을 별도로 인코딩하고 채널마다 개별 bitpool을 사용함
- Joint Stereo 대신 Dual Channel을 강제하면 같은 bitpool 53에서도 비트레이트가 약 617kbps로 거의 두 배가 됨
A2DP 사양과 현재 스택의 제한
- 2007년부터 2015년까지 유효했던 A2DP specification v1.2는 디코더가 최대 비트레이트를 넘지 않는 모든 bitpool 값을 지원해야 한다고 요구함
- 이 프로파일은 mono에서 320kb/s, 2채널 모드에서 512kb/s를 최대 비트레이트로 제한함
- 새 사양에는 비트레이트 제한이 명시되어 있지 않음
- 2015년 이후 출시된 EDR 지원 최신 헤드폰은 최대 730kbps까지 지원할 수 있다고 가정됨
- 테스트된 Bluetooth 스택인 Linux PulseAudio, Android, Blackberry, macOS는 모두 최대 bitpool 파라미터에 인위적 제한을 둠
- 거의 모든 헤드폰도 최대 bitpool 값을 53으로 제한함
- 수정된 Bluetooth 스택에서는 대부분의 기기가 551kbps에서 끊김이나 잡음 없이 동작했지만, 기본 Bluetooth 스택은 일반 조건에서 이 비트레이트를 협상하지 않음
Android Bluetooth 스택 패치
- 모든 A2DP 호환 Bluetooth 스택은 Dual Channel 모드를 지원해야 하지만, 일반 사용자가 이 모드를 강제할 방법은 없음
- Android 8.1과 Android 9용 패치는 Dual Channel을 스택과 개발자 메뉴에 추가하고, aptX, AAC, LDAC처럼 Bluetooth 기기 설정의 HD Audio 코덱 옵션으로 다룸
- 패치 링크
- 이 체크박스는 Dual Channel 모드를 전환하며, 기기별로 다음 비트레이트를 사용함
- EDR 3Mb/s 기기: 551kbps
- EDR 2Mb/s 기기: 452kbps
- 패치셋은 다음 대체 펌웨어에 병합됨
- LineageOS 15.1: 2019년 3월 31일부터
- LineageOS 16.0: 2019년 5월 13일부터
- Resurrection Remix: 2019년 5월 14일부터
- crDroid: 2019년 5월 13일부터
551kbps와 452kbps를 고른 이유
- Bluetooth 시분할 전송은 큰 고정 크기 패킷을 효율적으로 보내도록 설계됨
- 한 번의 전송에서 보낼 수 있는 최대 슬롯 수는 5개이며, 1-slot과 3-slot 전송 모드도 있지만 2-slot과 4-slot 모드는 없음
- 5-slot 전송에서 보낼 수 있는 데이터량은 다음과 같음
- 2Mbps 연결: 최대 679 bytes
- 3Mbps 연결: 최대 1021 bytes
- 3-slot 전송의 최대 데이터량은 다음과 같음
- 2Mbps 연결: 367 bytes
- 3Mbps 연결: 552 bytes
- 367 또는 552 bytes보다 크고 679 또는 1021 bytes보다 작은 데이터를 보내면 여전히 5-slot이 필요해 전송 효율이 낮아짐
- 44.1kHz 오디오를 SBC Dual Channel, bitpool 38, 16 blocks, 8 frequency bands로 인코딩하면 164-byte 오디오 프레임과 452kbps 비트레이트가 나옴
- 오디오 페이로드는 L2CAP과 AVDTP 전송 프로토콜로 감싸야 하며, 이 과정에서 오디오 페이로드에서 16 bytes의 오버헤드가 빠짐
- EDR 2Mb/s DH5에서 5-slot 오디오 전송 하나는 오디오 프레임 4개를 담을 수 있음
679 - 4(L2CAP) - 12(AVDTP/RTP) - 1(SBC header) - (164*4) = 6- 패킷에는 6 bytes가 남음
- 단일 패킷은 최대 11.7ms의 오디오 데이터를 담고 3.75ms에 전송됨
- bitpool을 조금만 올려도 오디오 프레임 4개를 한 번의 전송에 담지 못해 3개씩 보내야 함
- 전송 효율이 낮아짐
- 한 패킷에 담는 오디오량이 줄어듦
- 나쁜 무선 환경에서 오디오 끊김 가능성이 커짐
- EDR 3Mb/s용 551kbps도 같은 원리로 선택됨
- bitpool 47, 16 blocks per frame, 8 frequency bands에서 프레임 크기는 200 bytes
- 한 번의 전송에 최대 5프레임, 즉 14.6ms의 음악을 묶을 수 있음
- SBC 파라미터 계산은 복잡해 수동 계산에서 실수하기 쉬우며, 계산용 웹 도구가 제공됨
aptX와 SBC의 음질 차이
- aptX가 항상 SBC보다 낫다는 통념과 달리, 일부 경우 aptX는 표준 SBC 328kbps보다 낮은 음질을 낼 수 있음
- SBC는 주파수 밴드에 양자화 비트를 동적으로 할당하며, 아래쪽에서 위쪽으로 비트를 배분함
- 낮은 주파수와 중간 주파수에 전체 비트레이트를 쓰면 높은 주파수는 잘리거나 무음 처리됨
- aptX는 주파수 밴드를 항상 같은 비트 수로 양자화하는 고정 비트레이트 코덱임
- 44.1kHz에서 352kbps
- 48kHz에서 384kbps
- aptX는 필요한 주파수로 비트를 옮길 수 없고, 주파수를 자르지는 않지만 양자화 노이즈를 추가해 오디오의 동적 범위를 줄이며 때로 잡음을 만들 수 있음
- SBC는 반대로 조용한 영역을 버리며, 328kbps SBC와 비교하면 aptX는 넓은 주파수 범위의 음악에서 평균적으로 왜곡이 적음
- 좁은 주파수 범위와 넓은 동적 범위를 가진 음악에서는 SBC 328kbps가 때때로 aptX보다 나을 수 있음
- 피아노 녹음 예시에서는 대부분의 에너지가 0~4kHz에 있고 10kHz까지 이어짐
- SBC 328kbps는 16kHz 이상 범위를 주기적으로 완전히 잘랐음
- aptX는 사람이 들을 수 있는 주파수 스펙트럼에 더 많은 왜곡을 넣었음
- SBC 328kbps는 0~10kHz 범위에서 더 적은 왜곡을 냈고 나머지 주파수를 잘랐음
- SBC 485kbps는 전체 주파수 범위를 자르지 않고 보존하기에 충분했음
- 원본 오디오와 SBC/aptX 인코딩 파일 자료가 제공됨
- 고비트레이트 SBC를 쓰면 대부분의 경우 aptX보다 나은 소리를 얻을 수 있으며, EDR 3Mb/s 지원 헤드폰에서 551kbps SBC는 aptX HD에 매우 가까운 소리를 냄
더 높은 비트레이트 옵션
- Android 패치셋에는 EDR 2Mb/s 기기의 비트레이트를 더 높이는 추가 옵션이 있음
persist.bluetooth.sbc_hd_higher_bitrate값을 1로 설정하면 비트레이트를 452kbps에서 595kbps로 올릴 수 있음- 이 옵션은 혼잡한 무선 환경에서 전송 안정성을 낮출 수 있음
# setprop persist.bluetooth.sbc_hd_higher_bitrate 1
- 극단적 비트레이트 패치는 현재 LineageOS 15.1에만 병합되어 있으며, LineageOS 16.0에는 병합되지 않음
호환 기기와 비교 도구
- SBC Dual Channel은 거의 모든 헤드폰, 스피커, 차량용 헤드 유닛에서 지원됨
- 표준이 모든 디코딩 기기에서 이 모드 지원을 요구하므로 대부분의 기기에서 동작함
- 이 모드에서 문제가 생기는 기기도 소수 존재하지만 매우 드문 사례임
- 호환 기기 정보는 다음 커뮤니티에서 확인할 수 있음
- 브라우저에서 오디오를 실시간으로 SBC, aptX, aptX HD로 인코딩하는 웹 서비스도 제공됨
- btcodecs.valdikss.org.ru/sbc-encoder
- Bluetooth로 실제 전송하지 않고도 유선 헤드폰이나 스피커에서 여러 SBC 프로파일과 다른 코덱의 소리를 비교할 수 있음
- 오디오 재생 중에도 인코딩 파라미터를 직접 바꿀 수 있음
AOSP 반영 시도와 사용 방법
- Google의 Bluetooth 스택 개발자들에게 Android 메인 브랜치인 AOSP에 패치를 포함해 달라고 연락했지만 답변을 받지 못함
- Gerrit code review system for Android에 올라간 패치도 Android 개발 관련자에게서 코멘트를 받지 못함
- Gerrit 패치셋은 오래된 초기 리비전 중 하나이며, 개발자가 관심을 보이면 업데이트할 수 있음
- LineageOS, Resurrection Remix, crDroid 사용자는 Bluetooth 기기 설정에서 체크박스를 켜 Bluetooth 오디오 품질을 높일 수 있음
- Linux 사용자는 Pali Rohár의 PulseAudio 패치를 설치해 더 높은 SBC 비트레이트를 사용할 수 있음
- 이 패치는 aptX, aptX HD, FastStream 코덱 지원도 추가함
댓글과 토론
Hacker News 의견들
-
이건 훌륭함: SBC는 널리 지원되고, 기존 표준의 자연스러운 확장처럼 보임
개인적으로 문제는 SBC냐 LDAC/AAC냐가 아니라 HFP가 형편없다는 데 있음. 마이크가 켜지는 순간 90년대로 돌아간 느낌이고, 양방향 Bluetooth 오디오를 제대로 만들 수 있다면 정말 반가울 것 같음- 결국 낮은 지연 시간이 필요해서 그런 것 아닌가 싶음. “미디어” 음악·영상은 음질은 좋지만 지연이 크고, 영상은 같은 만큼 늦춰서 보정할 수 있지만 전화 통화에는 그 지연이 너무 큼
- HFP가 왜 아직도 업계 표준인지 이해가 안 됨. MacBook / iPhone / AirPods처럼 같은 생태계 안의 기기들도 음질을 보면 HFP를 쓰는 것 같음
아니면 AVRCP일 수도 있지만, 어느 쪽이든 소리가 끔찍함 - 이 기능은 LE Audio / Auracast로 천천히 시장에 들어오고 있음. 다만 좋은 운영체제 지원이 갖춰지려면 시간이 좀 걸릴 듯함
-
이 글은 Bluetooth 전반이 아니라, Android Bluetooth 스택 안에 묻힌 버그를 깊게 파고드는 글임
글쓴이가 전혀 인정하지 않는 부분은 기반 하드웨어가 매우 다양하다는 점임. Android는 수많은 Bluetooth 칩셋 위에서 동작하므로, 자기 하드웨어에서 패치가 동작해 보인다고 다른 Android 폰에서도 된다는 보장은 없음
또한 기기가 그 순간 무엇을 하고 있는지도 영향을 줌. BT+Wi-Fi 공유 칩셋에서 Wi-Fi로 영상을 스트리밍하면서 오디오를 헤드폰으로 보내면, 기기는 Wi-Fi 사용량과 Bluetooth 사이에서 자원을 배분해야 함. 그래서 로컬 저장 오디오와 스트리밍 오디오가 반드시 같은 코덱 파라미터를 받지는 않음
이 주제에는 글쓴이가 고려하지 않은 미묘한 요소가 너무 많으니, 읽는 내용을 조심해야 함- 예전에 커스텀 ROM을 개발했고 valdikSS 수정사항을 검토·통합해 본 입장에서 보면, 이 패치셋이 하는 일은 버그 수정이 아니라 소스와 싱크 연결에서 듀얼 채널 SBC 협상이 가능하게 하는 것임
이렇게 하면 Android와 Bluetooth 수신기가 강제하는 최대 bitpool을 넘지 않고도 더 높은 비트레이트를 쓸 수 있음
여전히 소스와 싱크 사이의 협상은 일어나며, 둘 중 하나가 듀얼 채널 SBC를 지원하지 않으면 지원 가능한 방식으로 되돌아감. 내가 유지보수하던 기기들은 모두 지원했고, 당시 테스트한 일부 저가 스피커는 지원하지 않아서 joint stereo 세션으로 협상됐음 - Bluetooth 전반에 관한 글은 여기 있음: https://habr.com/en/articles/456182/
- 예전에 커스텀 ROM을 개발했고 valdikSS 수정사항을 검토·통합해 본 입장에서 보면, 이 패치셋이 하는 일은 버그 수정이 아니라 소스와 싱크 연결에서 듀얼 채널 SBC 협상이 가능하게 하는 것임
-
Windows에서는 Alternative A2DP Driver가 이 기능을 제공함. SBC 파라미터를 조정하고, AAC나 aptX도 쓸 수 있게 해줌
내 경험상 잘 동작했고, Sony XM4에서 LDAC를 쓰는 데도 도움이 됨. 체험판 방식이지만 가격은 저렴함
고품질 모드에서 Bluetooth 범위가 줄어드는 걸 본 적이 있는데, 실제로 코덱이나 최소한 무언가가 바뀌고 있고 플라시보는 아니라는 신호처럼 보임
https://www.bluetoothgoodies.com/a2dp/ 와는 아무 관련 없음- 48KHz에서 44.1KHz로 다운샘플링할 때 말하는 “Quality Loss”가 뭔지 모르겠음. 리샘플링을 제대로 하면 아주 높은 주파수, 즉 22050Hz 이상만 잃게 됨
사람의 가청 범위는 보통 20KHz까지로 문서화되지만, 일부 젊은 사람은 그보다 약간 높은 주파수도 들을 수 있음
- 48KHz에서 44.1KHz로 다운샘플링할 때 말하는 “Quality Loss”가 뭔지 모르겠음. 리샘플링을 제대로 하면 아주 높은 주파수, 즉 22050Hz 이상만 잃게 됨
-
참고로 Linux에서도 SBC XQ라고 불리는 방식으로 더 높은 비트레이트의 SBC 오디오를 켤 수 있음. 비슷하게 mSBC로 더 나은 헤드셋 오디오도 쓸 수 있음
물론 여전히 SBC나 aptX 같은 수준에는 전혀 못 미침
Google 쪽에서 이런 것을 이미 병합해 줬으면 좋겠음. 더 나은 오디오 코덱은 많은 헤드폰 등이 지원하지만 보편적이지 않고, 양방향 오디오 개선은 특히 아직 부족함- 이 글은 4년 전 글이라, 이후 Android에 병합된 LE Audio 지원 같은 변화가 반영되기 전임
- Linux에서 그걸 어떻게 켜는지 궁금함
현재 헤드셋이 무엇을 쓰고 있는지 확인하는 방법도 알고 싶음
예전에 적절한 설정을 노출하는 패치된 PulseAudio를 썼던 기억이 있는데, 나중에 “메인스트림에 병합”됐다고 들었지만 정작 설정이나 실제 사용 정보를 찾을 수 없었음 - Linux에서 AirPods를 간신히 지원하는 것만으로도 너무 힘들게 씨름 중임
-
미리 오래 버퍼링할 수 있는 Bluetooth 오디오 프로파일을 누가 만들어 줬으면 좋겠음
예를 들어 1분짜리 노래를 재생하면 노래 전체가 버퍼에 올라가야 함. 물론 일시정지하거나 볼륨을 바꾸면 버퍼는 버려져야 함
긴 버퍼가 있으면 휴대폰이 더 자주 잠들 수 있어 전력을 아끼고, 무선 연결이 나빠도 버틸 수 있음- 그런 일은 가능성이 낮아 보임. 대부분의 헤드폰에 그런 버퍼를 위한 메모리가 있을지 매우 의심스러움
RAM 1~2MB 정도에 불과하다고 해도, 헤드폰은 그 RAM을 활성 상태로 유지하는 데 귀한 배터리를 써야 함
예전에 오디오 앱을 조금 다뤄본 바로는, 애플리케이션 지원도 까다로울 것 같음 - 전화가 걸려왔을 때 Led Zeppelin의 다음 1분을 먼저 다 듣는 대신, 그 버퍼링된 내용을 건너뛰고 수신 전화를 바로 받고 싶어지는 순간까지만 좋아할 것임
- 충분한 임베디드 메모리가 있으면 가능하긴 하지만, 오디오와 영상을 동기화하려 할 때 문제가 됨
그래서 이건 프로토콜 문제라기보다는 개별 제품이 설계로 넣고, 앱에서 사용자가 켜고 끌 수 있게 할 기능에 가까움 - 안타깝지만 그건 대부분의 사용자가 오디오에서 원하는 것과 거의 정면으로 반대됨
- 그런 일은 가능성이 낮아 보임. 대부분의 헤드폰에 그런 버퍼를 위한 메모리가 있을지 매우 의심스러움
-
LineageOS에서 이 기능을 써 봤고 솔직히 정말 좋았음. 서드파티 코덱을 지원하지 않는 차량 스테레오 같은 장비에 더 높은 품질의 오디오를 보낼 수 있었고, 헤드폰에도 꽤 도움이 됨
사용자 경험은 다듬을 필요가 있지만 기능 자체는 훌륭함- 안타깝게도 최신 Lineage 버전에서는 사라졌음. 지금은 사실상 잊힌 상태임
-
제목에 2019를 붙이는 게 좋겠음. “현재의 모든 Bluetooth 스택” 같은 표현이 나오지만, 이런 것들은 이미 한동안 PulseAudio와 PipeWire에 구현돼 있었음
-
551kbps Dual Channel이 328kbps Joint Stereo보다 눈에 띄게 더 나은 품질을 낸다는 데는 조금 회의적임. 그냥 중복 정보를 인코딩하는 데 더 많은 비트를 쓰는 것일 수도 있음
적어도 대부분의 음악에서는 그렇고, 좌우에 서로 다른 녹음 트랙을 의도적으로 배치한 곡 같은 예외는 있을 수 있음 -
관련 질문으로, macOS에서 Bluetooth HFP를 개선할 방법이 있는지 궁금함
같은 헤드셋을 Linux에서는 mSBC로 꽤 좋은 품질로 쓰고 있는데, macOS에서는 완전히 형편없고 전화선/모노 품질로 바뀜. Darwin에서 제대로 동작하게 만드는 해킹이 이미 있는지 궁금함 -
이 글을 보기 전까지 내가 SBC를 쓰고 있는지도 몰랐음. Lineage 18.1은 SBC 지원 기기를 연결해도 그 UI 체크박스를 보여주지 않음. 마법 같음 -