I guess the main problem is that I can't seem to find an en-/decoder to create test file. I have found some references to an "A2DP test specification" which is supposed to include windows binaries, but was unable to locate it.
There is a workaround of level matching the A2DP streamed via bluetooth with a lossless file playing on pc, but I don't trust myself to be able to level the volumes so perfectly. Besides, it wouldn't be an ABX test because I would have to manually switch the stream playing.
Would recording the A2DP stream to wav -> level matching with replaygain -> feeding both versions to foobar2000's foo_abx plugin be acceptable? Personally, I'd appreciate if someone could provide me with those binaries instead...
The problem with recording a bluetooth receiver, is that you won't be ABXing just SBC, but the receiver itself, with its own flaws added to the mix. If it rolls-off badly or if it's noisy or whatever, ABX results will be valid for the receiver, not for SBC.
The setup I currently thought of testing with is my phone (xperia m2) streaming music to a bluetooth usb adapter in my pc, so the "receiver" in that case would be my sound card (realtek alc889).
The playback noise should be the same in that case, but I guess there can also be noise while recording. Is that what you mean?
I wondered about doing the same however i have only an A2DP receiver in my car right now which makes ABX'ing impossible.
If you find a way to do is, it's very important to note however the bitrate the A2DP channel is using as well as the encoder. For example older Android phones used a low bitpool setting (https://code.google.com/p/android/issues/detail?id=9888) (~229kbps) with SBC which made the highs noticeable distorted. I think Jelly Bean was the first version where bitpool setting was increased (~328 kbps). My Galaxy S2 sounded awfully for example with ICS, but my Note 2 and my current Nexus 5 sounds indistinguishable for me, at least in the car while driving in noise. My headunit is a low priced JVC KD-X250BT (http://support.jvc.com/consumer/product.jsp?archive=true&pathId=139&modelId=MODL029193) after market stereo with the stock car speakers and a small Blaupunkt subwoofer. Nothing high end, still sounds okay for me in the car.
I don't know which SBC encoder is used in non Android phones. It's highly probably that every Linux based smartphone is using the default BlueZ SBC encoder though. Don't know what is the case with the iPhone or Windows Phone. Maybe it's possible to strip out the BlueZ SBC code and write a CLI encoder/decoder around it. I wonder why nobody done this already?
What also matters is the source. SBC makes highly compressed stuff sound worse. What worked the best for me is: lossless, lossywav, wavpack lossy, musepack, high bitrate AAC (QAAC iTunes+ setting for example). These all sound nice even after SBC transcoding.
For example older Android phones used a low bitpool setting (https://code.google.com/p/android/issues/detail?id=9888) (~229kbps) with SBC which made the highs noticeable distorted.
That would explain my awful experience from 2010.
I feel stupid. There's a complete SBC tester app provided with the SBC implementation of BlueZ: http://bluez.cvs.sourceforge.net/viewvc/bluez/utils/sbc/ (http://bluez.cvs.sourceforge.net/viewvc/bluez/utils/sbc/)
I'm trying to compile it right now Seems like the only dependency is libsndfile which is probably used for opening source files.
Mod: this will not going to work on Cygwin since it's part of the util package. I'm trying instead with this separate SBC source release: http://www.bluez.org/sbc-10/ (http://www.bluez.org/sbc-10/)
I've tried to compile it using MinGW but no luck. I've got as far as correctly compiling libsndfile and had some problems with pkg-config but the real issues was compiling sbc_math where some strange macro issues showed up. I'm not too good at compiling C/C++ code so others might spot the issue instantly.
However i've compiled it on my Ubuntu Atom box and could encode files with it I think MinGW has a different GCC version which is incompatible with the SBC source. I'll get back to this later.
I've used the latest source release which is dated this January: http://www.bluez.org/sbc-12/ (http://www.bluez.org/sbc-12/)
After issuing make install you get sbcenc, sbcdec and sbcinfo. It requires input files in AU format so you have to convert WAV files to AU first and back so you can listen to it with standard players. I've used SoX for this.
The "sbcenc" tool encodes with bitpool 32 setting by default which results in audio quality very similar to what i heard from the older Android phones (distorted highs). sbcinfo shows this:
Filename out.sbc
mSBC 0
Subbands 8
Block length 16
Sampling frequency 44.1 kHz
Channel mode Stereo
Allocation method Loudness
Bitpool 32
Number of frames 69636
Frame length 76 Bytes
Bit rate 209.475 kbps
Bumping it to 52 (which i think is the default with newer Android phones and Cyanogenmod build) provides a much better quality. In this case sbcinfo shows this:
Filename out.sbc
mSBC 0
Subbands 8
Block length 16
Sampling frequency 44.1 kHz
Channel mode Stereo
Allocation method Loudness
Bitpool 52
Number of frames 69636
Frame length 116 Bytes
Bit rate 319.725 kbps
Bitrate wise: 209kbps vs 320kbps.
sbcenc has some other interesting options though:
Usage:
sbcenc [options] file(s)
Options:
-h, --help Display help
-v, --verbose Verbose mode
-m, --msbc mSBC codec
-s, --subbands Number of subbands to use (4 or 8)
-b, --bitpool Bitpool value (default is 32)
-j, --joint Joint stereo
-d, --dualchannel Dual channel
-S, --snr Use SNR mode (default is loudness)
-B, --blocks Number of blocks (4, 8, 12 or 16)
For eg. i don't know what is that mSBC codec option there.
It would be interesting to extract the actual values the Android project using. There is an sbc_t structure initialized at the beginning of the encode method in sbcenc, Android should have a similar initialization somewhere.
Although frequency spectrum alone doesn't say too much, i thought it would be interesting to show the effect on a source file. The source audio was a loud EDM music. I've choosen this to clearly see the subbands and other kind of lowpassing.
Original:
(http://i.imgur.com/1KH1U7h.png)
Encoded with default settings (bitpool 32):
(http://i.imgur.com/pageV7Y.png)
Encoded with -b 52 (bitpool 52):
(http://i.imgur.com/OtfOYEk.png)
I happen to have an arch VM, and it has the sbc library and binaries in a package already <3
Was able to encode to a2dp, but decoding gives me "Can't open output /dev/dsp: No such file or directory"
What am I supposed to pass for the -d option? Or rather, what command parameters have you used to decode it back to .au?
What am I supposed to pass for the -d option? Or rather, what command parameters have you used to decode it back to .au?
You can use the --file switch of sbcdec to decode back to .au.
sbcdec --file out_dec.au out.sbc
Which version of SBC Tools your Arch build has? My compiled encoder says:
SBC encoder utility ver 1.2
Copyright (c) 2004-2010 Marcel Holtmann
Ok, I messed up on the commandline, put the -f option after the input...
Arch is a bleeding edge rolling release distro, so it gets the newest stuff ASAP. The version is 1.2, same as yours.
Will try to abx it tomorrow probably, a bit tired atm. Thanks for the pointer!
edit: actually, ABXing the default settings turned out to be effortless, way too much distortion:
foo_abx 1.3.4 report
foobar2000 v1.3.3
2014/07/17 23:42:08
File A: R:\lossless.wav
File B: R:\a2dpfromlossless.wav
23:42:08 : Test started.
23:42:33 : 01/01 50.0%
23:42:49 : 02/02 25.0%
23:44:59 : 03/03 12.5%
23:45:13 : 04/04 6.3%
23:45:23 : 05/05 3.1%
23:45:53 : 06/06 1.6%
23:46:04 : 07/07 0.8%
23:46:07 : Test finished.
----------
Total: 7/7 (0.8%)
What we'd need, as darkbyte said, is to know which settings android uses... anyone has the AOSP repository setup or a link to an online viewable code?
You are welcome, and curious about your test.
Tried to look up what settings Android is using. Haven't found the exact parameters (I'm especially curious about loudness/SNR and Joint Stereo) but looks like the newer version tries to negotiate with the receiver to use the maximum possible bitpool which is 53 by most hardware (not 52, so this makes that small bitrate difference). At least this is what I've found on XDA reported by other users.
The sbc_t initialization occurs in liba2dp.c (http://osxr.org/android/source/external/bluetooth/bluez/audio/liba2dp.c), check the function bluetooth_a2dp_init. The whole configuration seems to start at a2dp_init which starts the a2dp handling thread which retreives the capabilities data in bluetooth_configure from an external service. This is where i got lost sadly.
I assume the device capabilities are obtained on pairing, then depending on signal strength, the bitrate (and possibly other parameters) are varied.
Maybe it's possible to obtain some info by attaching adb logcat on the phone and then pairing and playing something to the receiver. This should show up:
W/BTLD ( 1677): ### :: codec open ::
W/BTLD ( 1677): ### mtu 512, 660 bytes/frame, bitrate 229, nbr ch 0, freq 240
W/BTLD ( 1677): ### alloc : 3, blk len 240, chmode:15, bitpool 32:2, subbands 12
These lines are printed in: btif_media_task.c (https://code.google.com/p/android-source-browsing/source/browse/btif/src/btif_media_task.c?repo=platform--external--bluetooth--bluedroid&r=7a291d46e4d535e4c17bd7c6e2b637fa26d24ff3#1566) Not sure where those constant values are defined. The chmode (if it's encoding mono/stereo/jstereo/etc.) doesn't line up with the values defined in sbc.h (http://osxr.org/android/source/external/bluetooth/bluez/sbc/sbc.h#0053).
btif_media_task.c is the correct place. I have found a (now closed) google issue here (https://code.google.com/p/android/issues/detail?id=9888) and the last post says cyanogenmod fixed the issue by setting the default bitrate from 229 to 328. I guess google did, too: if you look here (https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/btif/src/btif_media_task.c), you can see
140. /* Middle quality quality setting @ 44.1 khz */
141. #define DEFAULT_SBC_BITRATE 328
142.
143. #ifndef BTIF_A2DP_NON_EDR_MAX_RATE
144. #define BTIF_A2DP_NON_EDR_MAX_RATE 229
145. #endif
It also seems that if the device does not support EDR, the rate will be reduced to 229kbps. (see lines 586-591)
Looking at files created with -b 53 gives the following output:
Filename test.a2dp
mSBC 0
Subbands 8
Block length 16
Sampling frequency 44.1 kHz
Channel mode Stereo
Allocation method Loudness
Bitpool 53
Number of frames 83560
Frame length 118 Bytes
Bit rate 325.238 kbps
Not quite 328kbps, but increasing to -b54 gives 330.750 kbps, so I think we can safely assume current android sends data encoded with -b 53 at optimal conditions.
Nice finding. I still interested if Android is using Joint-Stereo or not, also i think the Loudness vs. SNR bit allocation mode makes a noticable change in quality as well.
I would think that because SBC is actually a specialized MPEG Layer-I codec and even MPEG Layer-II's Joint-Stereo mode is more like MP3's Intensity Stereo (separation information for higher bands is dropped and replaced with more simple phase information) Android is using standard Stereo mode at this bitrate to achieve higher quality. But i'm just assuming this.
I've tried to compile sbc-1.2 on my Windows 8 box with MinGW-W64 which has GCC-4.8.2, the same as my Ubuntu box, but still getting strange compile errors. I don't know whats wrong. Here's the starting of the error log: http://pastebin.com/bFn6PMH7 (http://pastebin.com/bFn6PMH7) The complete compile log has errors like this. Seems like it cannot find even standard headers, but i wonder how could i compile autoconf, pkgconfig-lite and libsndfile then. Seems like ./configure generated by autoconf is wrong and miss detects things. Might someone has an idea to try.
Hello,
SBC ver 1.2 Win32 binaries (http://aiz.free.fr/sbc12_win32.zip). Parameter "-f" is mandatory for sbcdec, of course. AU files generated by sbcdec have a bunch of '0' after the header, hopefully SoX can deal with that problem (same behaviour under Linux).
Have a nice day,
AiZ
Thanks for the binaries! Damn Chrome is blocking the download, but the files are clean according to virustotal. I hate it when programs are trying to be smarter than the user.
SoX can deal with the zeroes, just warns you about header being too small or something. Foobar can't play those .au file directly though, so converting with SoX it is. Or maybe this plugin (http://www.hydrogenaud.io/forums/index.php?showtopic=97414&hl=) can be of use? (edit: no, it can't. probably because decoding a2dp results in the same .au unplayable by foobar)
That said, I can't seem to be able to ABX A2DP at -b 53. Haven't tried values in between yet. With windows binaries being available, maybe more people will be willing to test.
Thanks AiZ for the Windows build! Can i ask you which tool did you use to compile it? I like to learn how to do these stuff.
I haven't done ABX'ing yet, just some casual listening on some samples i thought might reveal issues. Haven't detected anything wrong with -b53 with my headphones on. So I'm suspecting that i will be not able to ABX SBC@B53 which is actually very good, haven't expected this. I thought headphones will reveal artifacts very quickly.
Now that we have Windows binaries i would like to give classic MPEG killer samples a go though
Hi,
I've used MSYS2/gcc 4.9.1 environment. Libsndfile, which is available as a package in MSYS2 (like pkg-config), is only needed by the sbctester tool. Google a bit for pkg-config with MSYS and you can keep your MSYS setup if you only need sbcenc and sbcdec.
Of course, you'll have to slightly modify the source code to get rid of glibc, soundcard, whatever else stuff.
PM me if you need more information,
AiZ
I've made a batch script to ease encoding-decoding. It uses temp files, i don't know how to make SoX pipe to stdout. By writing "-" to the output filename it tries to create a file with that name.
Put SoX and sbcenc, sbcdec next to the batch file in a directory and then you can use it in Foobar as a passthrough encoder like this:
Hello,
SBC ver 1.2 Win32 binaries (http://aiz.free.fr/sbc12_win32.zip) again.
Don't use stdin (-) as input for sbcenc as it seems to be broken (MSYS/MinGW problem?).
Modified sbcdec to output to stdout when not using -f or --file parameter.
Fixed .au files generated by sbcdec to be playable by foobar2000 and others (wrong default value in header).
AiZ
Thanks for that fix. Now we can both encode to .a2dp and play it directly from foobar! Just take the foobar decoder wrapper (http://www.foobar2000.org/components/view/foo_input_exe) and use this template (https://dl.dropboxusercontent.com/u/19330332/foo_input_exe_a2dp_profile.xml)(save as .xml) to enable playing/ABXing .a2dp files.
Just take the foobar decoder wrapper (http://www.foobar2000.org/components/view/foo_input_exe)
Wow, didn't know there is something like this exists for Foobar
AiZ: thanks for the updated build!
So I couldn't ABX SBC at 320kbps when playing it on my PC, but now that I got myself some BT headphones, I clearly hear artifacts on some songs. I thought it was supposed to be fixed with Android 4.0, but it isn't so.
My Xperia M2 runs 4.3, looking at google's repository, the first version with bitrate of 320kbps is android 4.4
Bummer. At least mine is getting an update to 4.4.2, so I will get the "full" quality in the future. Otherwise the only solution would be a custom ROM.
edit: before I get murdered: obligatory ABX of SBC@229 vs lossles:
foo_abx 1.3.4 report
foobar2000 v1.3.3
2014/08/19 14:53:00
File A: R:\01. TK from 凛として時雨 - unravel.tak
File B: R:\01. TK from 凛として時雨 - unravel_lq.a2dp
14:54:32 : Test started.
14:54:47 : 01/01 50.0%
14:55:45 : 02/02 25.0%
14:55:55 : 03/03 12.5%
14:56:06 : 04/04 6.3%
14:56:20 : 05/05 3.1%
14:56:56 : 06/06 1.6%
14:57:09 : 07/07 0.8%
14:57:12 : Test finished.
----------
Total: 11/12 (0.3%)
That's one of the many reasons why i love my Nexus phone and tablet. Always getting new software instantly.
I hate Nexus for not offering an SD card
But I've tested it just now on my brother's Moto G (4.4.4) and the sound is transparent to my ears. Definitely no distorted cymbals anymore.