Friday, February 23, 2007

Stereo Bluetooth Profile (A2DP) on Mac OS X Tiger

This post is now obsolete, please check out the new instructions which use Jack Audio, here.

Using the following instructions will allow full use of stereo bluetooth headphones on a mac without waiting for Leopard! Unfortunately The audio is delayed by nearly a second because this is such an indirect method.


  1. Install Darwin Ports (Install Guide)

    From http://darwinports.com/

  2. Install Soundflower

    http://www.cycling74.com/products/soundflower
    A restart is required.

  3. Set input and output sound devices to "Soundflower (2ch)"

  4. Install esd

    From a terminal window run:

    sudo port install pkgconfig audiofile esound

  5. Start esd for the first time (It should autostart afterwards):

    esd &


  6. Download bttest02.zip

    This is a GPL A2DP player by bkc based on a2player, available from www.emucamp.com/boukichi/btplay02.zip.

    Download Tim Hewett's modified version that works on both PPC and Intel from here.

    Extract the files and copy bttest and sbcenc to your local bin folder (e.g. /usr/local/bin).

  7. Create a shell script called in your local bin folder called a2dp.sh, replacing HEADSET with your bluetooth headset's device address.

    This address can be obtained in System Preferences -> Bluetooth - Devices, after pairing.

    Place these lines in the shell script:
    #!/bin/sh

    mkfifo /tmp/mixer

    ADDR=HEADSET

    esdrec | sbcenc -z 44 -s 4 -j - | bttest $ADDR -

    rm /tmp/mixer
  8. Run a2dp.sh

The resulting sound quality is at least as good as my Motorola V3x produces. Another thing to note is that if the headset goes out of range it does not reconnect properly.


If you try this with a headset other than the Motorola HT820, please post a comment about your experience. So far there have been some negative reports for Sony Ericsson headsets.

Thanks to bkc for the port! Also this hint was helpful, Create a wireless speaker setup without AirTunes.

Enjoy!

Update: New version of btplay.

Update 2: Added link to install guide.

Update 3: Tweaked instructions to include pkgconfig and starting esd (thanks jon) for the first time.

Update 4: Request for information on experiences with other headsets.

Update 5: Thanks to Tim Hewett this now works on PPC and the shell script has been improved. Confirmed working on Jabra BT320s. As always reports of success or otherwise are greatly appreciated!!

96 comments:

David Connolly said...

Comments are now fixed, Thanks to Jonathan for informing me they where broken...

leskovartem said...

MacBook-Pro:~ leskovartem$ sudo port install esound
Password:
---> Configuring audiofile
Error: Target com.apple.configure returned: configure failure: shell command "cd "/opt/local/var/db/dports/build/_opt_local_var_db_dports_sources_rsync.rsync.darwinports.org_dpupdate_dports_audio_audiofile/work/audiofile-0.2.6" && ./configure --prefix=/opt/local" returned error 1
Command output: checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
checking whether make sets ${MAKE}... yes
checking for gcc... no
checking for cc... no
checking for cc... no
checking for cl... no
configure: error: no acceptable C compiler found in $PATH

Error: The following dependencies failed to build: audiofile automake autoconf perl5.8 libtool
Error: Status 1 encountered during processing.

How fix it?

David Connolly said...

A working build system is required for darwinports!

Install the latest version of Xcode available from here.

Indeed it would be a good idea to follow the darwinports install guide.

Hope that helps,

gekong said...

hope this will work on my ppc will try this soon.

if anyone is smart enough to make an app that runs this automatically i'd buy it!

jon said...

Hrm, I keep getting "This is not an SBC file" as my output from the shell script. Any idea what I'm doing wrong here?

jon said...

Ah, figured out my problem, forgot to start esd...

yaro said...

Is it possible to eliminate the delays?

David Connolly said...

Hi Yaro,
I have yet to figure out a way to reduce lag. When I have time I'm going to look into replacing ESD with Jack, hopefully should help.

I'll try other things after that especially now leopard's not out for ages...

Slash said...

I made a .sh script on my desktop containing:

#!/bin/sh

esd &

sleep 1

/usr/bin/a2dp.sh


Set under get info for Terminal to open it. To do this you need to change the pulldown "Recommended Applications" to "All Applications."

Now, I just double-click to connect to my Griffin Bluetrip base.

paobeleeso said...

What an tantalizing tutorial - has anyone tried it on a PPC mac?

I have an old ibook with a D-link bluetooth adapter (with upgraded firmware for headsets). After following all the instructions (I am a novice, but I think everything's as it should be), when I run the a2dp.sh shell script in /usr/local/bin I get this message in terminal:
a2dp.sh: line 5: sbcenc: command not found
a2dp.sh: line 5: bttest: command not found

Any ideas? does this mean it won't work on PPC macs? are sbcenc and bttest compiled only for intel macs? Have I understood correctly that, after downloading btplay02.zip, I copy just the sbcenc and bttest executables into /usr/local/bin, and nothing else?

Many thanks for any comments, ideas, or help.

David Connolly said...

The binaries are build for PPC but untested by me.

You'll need to add /usr/local/bin to your .profile for example add:


export PATH=/opt/local/bin:$PATH


To your ~/.profile file,

Good Luck, and please post back if works!

paobeleeso said...

Thanks for your suggestion. When I installed MacPorts I created a .profile containing this:


export PATH=/opt/local/bin:/opt/local/sbin:$PATH

export DISPLAY=:0.0


I have tested it according to the MacPorts tutorial using the env command - it seems ok.

David Connolly said...

hmm thats odd, are the sbcenc and bttest executable?

What happens if you run sbcenc and bttest directly?

cd /usr/local/bin
./bttest
Bluetooth SBC player ver 0.1
Usage <addr> <file>
./sbcenc
SBC encoder utility ver 0.5
Copyright (c) 2004 Marcel Holtmann

Usage:
sbcenc [options] file(s)


Options:
-h, --help Display help
-v, --verbose Verbose mode
-r, --rate [n] Sampling rate
-c, --chan [n] Channel
-z, --skip [n] Skip n bytes
-b, --noswap No swap bytes
-s, --subbands Number of subbands to use (4 or 8)
-j, --joint Joint stereo

paobeleeso said...

yes, executing them directly works exactly as you have posted

David Connolly said...

Ok then you can just hardcode for their locations in a2dp.sh


#!/bin/sh

mkfifo /tmp/mixer
ADDR=HEADSET
esdrec > /tmp/mixer & /usr/local/bin/sbcenc -z 44 -s 4 /tmp/mixer | /usr/local/bin/bttest $ADDR -


rm /tmp/mixer

No idea why it's not respecting your path, its odd!

paobeleeso said...

Great - that solved the issue, and the shell script now seems to try to start the stereo BT process correctly.

Unfortunately, I still can't get it to work. I'm going to keep fiddling with it tomorrow, and I'll post back if I can get it to work, or with the error messages - thanks for your help getting me this far.

Dongnak Lee said...

I have Sony Ericsson's HBH-DS970 and MacPro.

I tried it but it was fail.
BT connected successfully, but it doen't make any sound, just silent.

paobeleeso said...

I've tried to make sure that I've done everything right, but I still can't get it to work on a PPC 800MHz iBook, with the HT820 headset. I'm using an external BT adapter from Dlink (with updated firmware which supports headsets).
When I run the script, the computer connects to the headset, and terminal returns this:


opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 57
open : control channnel
discover : try again
Too short received data!
Can't open stream port
/usr/local/bin/a2dp.sh: line 6: 1987 Broken pipe esdrec >/tmp/mixer

Any ideas?

David Connolly said...

Perhaps 800mhz isn't powerful enough to handle realtime capturing of audio, transcoding of it to sbc and then streaming it over bluetooth.

paobeleeso said...

Activity monitor doesn't show the the processor being overloaded (I forgot to mention it is a G4), or any obvious problems with RAM (I have 640Mb).
One day I may go to the trouble of booting from an external drive to see if faster disk access or usb hub power is an issue.
Maybe someone has got it to work on an iBook with internal bluetooth?

Thanks again for you help.

Ryan said...

I am so close, yet so far away. When I run my a2dp.sh I can only hear the sound from the microphone on my S805 looped back to me. That sounds to me like I've set the input wrong - but I am unsure how to specify to esdrec which audio device to pull from. Can anyone tell me what obvious step I am missing?

Ron said...

Hi. I am trying to use an Omiz combo BT headphone, and this is the output I get:

opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 68
open : control channnel
discover : received
SEID = 1

Sent set configurations command
set_config : rejectedOPEN : rejected
Can't open stream port
/usr/local/bin/a2dp.sh: line 6: 354 Broken pipe esdrec >/tmp/mixer

Seems like bttest doesn't work well with my set. Any ideas?

paobeleeso said...

Just to let anyone who is interested know, I'm using a D-link BT adapter, "rev B3" model, with firmware updated to BT class 1.2 using Apple's updater. Terminal says "discover : try again", "Too short received data!" & "Can't open stream port" etc. (see my previous post above) when I use the D-link adapter.
I swapped it with a regular BT adapter which is incompatible with headsets on a mac (i.e. class 1.1 bluetooth adapter - the one that comes bundled with the motorola stereo BT headsets) and terminal spits out the very same message about not being able to establish a stereo connection with the headset (even though the shell script succeeds in pairing the headset to the mac with either BT adapter). That seems to imply that my BT dongles can't interact with the mac and a stereo headset - right?
Has anyone with a PPC mac and internal BT got it to work?

Kyle said...

I am trying to connect a new Motorola S9 and receive pretty much the same error as Ron gets:

opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 68
open : control channnel
discover : received
SEID = 2
SEID 2 : MPEG codec
SEID = 1
Sent set configurations command
set_config : accepted
OPEN : rejected
Can't open stream port
a2dp.sh: line 5: 637 Broken pipe esdrec >/tmp/mixer


This is my first time messing with scripts and such, just wondering if there was any more info I could get.

David Connolly said...

Posted at Tue, 1 May 7:58 PM

Sorry for the late responses. I'm in the last three weeks of my degree course and have got very little free time!!!

Unfortunately from the "OPEN : rejected" message, it looks to me like it is the bttest program that is incompatible with your headsets, rather than a mistake on your behalf!

Teddy said...

Posted at Tue, 1 May 9:54 PM

This worked excellently for me, although I am quite disappointed with the delay. I try to watch a video, and they delay makes me want to rip my hair out. And solution to this would be greatly appreciated. :)

A said...

Posted at Sat, 5 May 8:26 AM

Will the mac mini connect the Motorola HT820 without any receivers.

Thanks

Rick said...

I'm trying to get the Motorola S9 working on my MacBook Pro (Intel) and am having a strange problem - the only audio which will come through is via the build-in Mic. I think I have tried changing ALL the settings in Soundflowerbed, even tried running esd with -d /dev/audio, /dev/sound, /dev/mixer (which don't exist on the Mac anyway) to no avail. I can MUTE the mic and get no sound but I cannot get the actual audio playing in iTunes. I get no errors and other than the echo, it *does* work to play iTunes through the speakers, get picked up by the Mac mic, and then sent to the headphones, just sounds really bad and obviously the reason for headphones is so everyone else doesn't have to listen :).

Ideas? Anyone?

Thanks,
Rick

David Connolly said...

Hi Rick,
esdrec appears to only ever use the devices chosen in "System Preferences -> Sound", of which both input and output should be set to "Soundflower 2ch".

If its set up right you shouldn't hear any sound from your built in speakers or have any volume control.

(Its really unclear in the instructions that I mean in the system preferences, I'll change it when I get the chance...)

Best of luck,

Taif Rahman said...

Works well with Motorola HT820.
But when attempting to connect to Motorola DC800 get the following screen output

Taifs-MacBook:~ Taif$ a2dp.sh
mkfifo: /tmp/mixer: File exists
opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 68

open : control channnel
discover : received
SEID = 2
Sent set configurations command
set_config : accepted
open : stream channnel
open_stream : ok
start_stream : ok
49612 bytes/sec
sleep_usec : 62500
mtu = 672
5 : delayed = -19884
5 : delayed = -6467
5 : delayed = -4438
6 : delayed = -15497
6 : delayed = -12913
6 : delayed = -14452

6 : delayed = -23445
6 : delayed = -6451
6 : delayed = -4495
6 : delayed = -4455
6 : delayed = -34451
6 : delayed = -8439
.....

Justin Patrin said...

I've gotten this to work with a Plantronics Pulsar 260. It took me a while to get it to work, however, as I had to change the Audio format to 44100.0 Hz for the various audio devices before esd would work.

JohnK said...

I'm using a Jensen WBT212 headset with a new MacBook (built-in bluetooth). I know my esd is fine, since it produces sounds upon startup if I direct the output to the internal speakers instead of SoundFlower. I know the Bluetooth connection is fine because I can send over (horrible sounding) audio by selecting the headset directly in the Sound part of System Prefs.

When I run the script, though, I get the same output as Taif reported above (mine is pasted below). Suggestions would be most welcome, I'd really love to get this working!


----------------------------------

jk.local ~/temp % ./a2dp.sh
Bluetooth SBC player ver 0.1
opening socket, format = 0x00002021 at 44100 Hz
using device Soundflower (2ch) for output:
with sample rate 44100.000000, 2 channels and 32-bit sample
using device Soundflower (2ch) for input:
with sample rate 44100.000000, 2 channels and 32-bit sample
frm_len = 68
open : control channnel
discover : received
SEID = 1
Sent set configurations command

set_config : accepted
open : stream channnel
open_stream : ok
start_stream : ok
49612 bytes/sec
sleep_usec : 62500
mtu = 672
17 : delayed = -5735
18 : delayed = -511
18 : delayed = -3485
18 : delayed = -215
18 : delayed = -20489
18 : delayed = -511
18 : delayed = -1432
18 : delayed = -10452
18 : delayed = -420
19 : delayed = -182

19 : delayed = -12210
19 : delayed = -24950
(more of these ad infinitum....)

David Connolly said...

Hi John,
Unfortunately I've no suggestions for headset compatibility at the moment.

Phil said...

same here. running on a macbook. I've had mplayer working for fairly long periods before the "delayed = ..." error and also noticed that the sound sampling rate varies... sound slooooowwwwsss ddooooowwwwwnnnnn before the delayed error kicks in. (mplayer is great since it allows you to vary the audio offset and remove that delay through this method). Itunes however just kills this pretty much immediately for me.

David Connolly said...

Hi Phil,
Maybe try renice'ing the processes, it might help with problems on high CPU usage caused by itunes!

ps aux (to find pids of esd apps, sbcenc and bttest)

sudo renice -25 PID_NUM

Good Luck!

Phil said...

Thanks David, but it's not actually a CPU issue as my machine is not maxed out. It's like the pipe can't handle the throughput rate or something.

I have ...

opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1

using device Soundflower (2ch) for output:
with sample rate 44100.000000, 2 channels and 32-bit sample
using device Soundflower (2ch) for input:
with sample rate 44100.000000, 2 channels and 32-bit sample

is there an easy way to change this to a lower samplerate and bit precision. Assume it's probably a hack and a recompile?

Ahmad Nassri said...

I just purchased a Jabra BT 620s stereo headphones, to my disappointment i found out that osx does not support stero sound over BT and my Palm LifeDrive does not support BT headphones period!
I found a hack for my pda just about the time I found this post
I'm listining to stereo heavy rock music on my headphones from iTunes as I'm hacking my palm to have the same feature.

just wanted to say thanks :)

Kamon said...

I'm using the Mototola HT820 on a G4 PPC iBook with internal BT. I'm getting somthing similar to what paobeleeso was getting

ibook-g4:~/btplay02 kyle$ a2dp.sh
opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 57
open : control channnel
discover : try again
Too short received data!
Can't open stream port
/usr/bin/a2dp.sh: line 6: 395 Broken pipe esdrec >/tmp/mixer

Has anyone gotten this to work with PPC at al?

David Connolly said...

There hasn't been a single report of success on PPC so far, and I've only got access to Intel Macs so can't test

Marc said...

Success report:

Mac Book Pro -> Jabra BT 620s
Quality comparable to Treo 650 - > Jabra BT 630s

Everything worked fine, immediately, as described in your blog.

Thanks
Marc

Thorsten said...

Trying MacBook Pro --> Jabra BT 620s


Works for some seconds, then again for less than one second, then not at all.

Have to admit, I tried it with Fink rather than the Darwinports.

Here's a report of what happened:



Banana-9:/usr/local/bin thorsten$ sh a2dp.sh
opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
using device Soundflower (2ch) for output:
with sample rate 44100.000000, 2 channels and 32-bit sample
using device Soundflower (2ch) for input:
with sample rate 44100.000000, 2 channels and 32-bit sample
frm_len = 68

open : control channnel
discover : received
SEID = 6
Sent set configurations command
set_config : rejectedopen : stream channnel
open_stream : ok
start_stream : ok
49612 bytes/sec
sleep_usec : 62500
mtu = 672
6 : delayed = -1146
6 : delayed = -8379
6 : delayed = -3943
6 : delayed = -6356
6 : delayed = -8532
6 : delayed = -19490
6 : delayed = -4916

7 : delayed = -7192
7 : delayed = -43433
7 : delayed = -27074
7 : delayed = -9451
7 : delayed = -5424
7 : delayed = -6144
7 : delayed = -7487
7 : delayed = -7463
7 : delayed = -8467
7 : delayed = -8412
7 : delayed = -8528
7 : delayed = -8465
7 : delayed = -7448
8 : delayed = -20048
8 : delayed = -8413
8 : delayed = -7461
...


and so on.

What is actually going wrong?
Any idea is greatly appreciated.
The quality of what I hear, when I hear it, is great!

Pablo said...

Hi, I've tried the hint with a Macbook Pro and Motorola HT820. It worked greatly. I'll analyse the sound chain to see if the quality can be improved, though. Best,

Pablo

Raj said...

I cannot get this to work on my iMac G5. Since no PPC user has reported this working, I'm assuming it likely does not work on a PPC Mac. I get the same error as Kamon. It appears that it never can hook up with the 'phones. The discovery does not appear to work. I am using the iLuv i903 headphones.

Leon said...

MacBook Pro (intel) - Jabra 620s
I get this when I run a2dp.sh
-------------

Last login: Fri Jun 1 09:15:26 on ttyp2
Welcome to Darwin!
voids-computer:~ void$ /opt/local/bin/a2dp.sh; exit
logout

[Process completed]

----------

What is actually going on here? Thanks for any advice.

Ray said...

This worked flawlessly with MacBook and iMuffs.

Thanks.

PS. I launched as follows "a2dp.sh &" so that I could close my terminal afterwards.

Tim said...

Re: PPC, it doesn't work. It works fine on a Intel Mac Mini, but not on a PPC iBook G4.


I messed around with the code for bttest for a while and found that swapping bitfields around allowed the iBook to connect to the device (a Jabra BT320s) when it wouldn't discover it previously (error was "discover: try again"), but still only silence.

I get the feeling it is very nearly "there" but there's a final hurdle.

Tim said...

I now have it working on PPC (and Intel). I'm not sure who to contact to have the changes integrated into the btplay zip download, anyone know?

It looks like the core part of btttest needs to be run using realtime scheduling, I find that the slightest use of the computer while it is transmitting to my Jabra BT320s causes gaps in the music, and the music pitch can "wow" presumably because the device is receiving the audio packets at an uneven rate. This iis the same for both Intel and PPC.

BTW the Jabra 320s sounds great, the best thing being that it is a receiver which is separated from the headphones, meaning that you can plug in your own favourite 'phones instead of having to put up with what you're given.

David Connolly said...

Hi Tim!
That is really cool, the author of bttest's email address is:

alf_bincyou at hotmail dot com

If you like I'll host the modified version on this page? drop me an email.

P.S. Sorry for the weirdness on this site, I'm migrating it to blogger.

justen deal said...

Motorola S9. Made it through, right up to the end, on an iBook G4. Unfortunately, all I get from the headset is static that corresponds with the actual audio output.

Any ideas?

justen

paobeleeso said...

Great news about updating sbcenc and bttest for PPC, but I still can't get it to work. Like Justen, I'm getting static, though it comes and goes and doesn't seem to correspond with anything in particular.

tanguy said...

i followed the instructions exactly as is (except the url for darwinports didnt work.
i am using the plantronics pulsar 590A
and it works awsome

David Connolly said...

thanks tanguy, great its working, I'll fix the links now.

Also I'll add the headsets to the list of non working on PPC, thanks paobeleeso and justen for the reports.

Stone said...

Thanks it works with sony dr-bt30q.

Anonymous said...

Thx for the info. It works great on my MacBook Pro with Sony CMT-BX5BT hi-fi.

John said...
This comment has been removed by the author.
John said...

Hey David, it's syperium@gmail.com. I now know why it wasn't working... and I was very stupid for not figuring it out before. My headset was paired with my cell phone. But... you were right still. It doesn't work with PPC.

So... even with help from David, the Motorola HT820 does not work with and iBook G4. All I get is static.

Thanks for the help again, David!

Tim Hewett said...

The PPC "static" issue is very strange as the current download works fine on my iBook G4 (as well as my Intel Mac Mini) with the Jabra BT320s. The only difference is that I wasn't using esd (it won't start up on either my iBook or Mini, it errors with "unsupported device.").

This leaves me wondering if esd doesn't work properly on PPC, as I've been using sbcenc and bttest fine on PPC.

Try downloading this SBC sample, tested successfully on PPC. Play it using 'bttest ADDR monkey.sbc' (replace ADDR with your device's address)

http://www.coolatoola.com/monkey.zip

Tim.

Tim Hewett said...

... also try chaning the shell script startup line from

esdrec | sbcenc -z 44 -s 4 -j - | bttest $ADDR -

to

esdrec | dd conv=swab | sbcenc -z 44 -s 4 -j - | bttest $ADDR -

as it looks as if esdrec is providing wrong-endian PCM on PPC - that certainly sounds like static.

Tim.

John said...

I'm a bit confused with what I'm suppose to do with the SBC sample. Do I replace a file with it...? Or... do I put it somewhere? And, the command line edit. Do I change it in the 'a2dp.sh' file? Or... a different file?

I'm a bit of a noob when it comes to things like this. I appoligize.

paobeleeso said...

Tim, I downloaded the monkey and I can hear him.

I also tried your altered line of code, and instead of static, I now get snippets of sound! Sometimes up to about 10 seconds of a track, but quite often there are long gaps of silence. When it works, it actually sounds pretty good - it's close!

My setup is ibook G4, a slow 800mHz, with the motorola HT820 headphones. The processor doesn't seem to be overtaxed. But another factor in the mix is that I'm using a D-Link adapter - maybe your altered line of code will be enough for PPC Macs with built in bluetooth 2.0+EDR modules ... (like Justen?). Any other ideas or tweaks would of course be welcome - thanks.

paobeleeso said...

John, I'm a bit of a terminal novice, but I think I can help you with this one. Yes, change the code in the a2dp.sh file. The changed version looks like this:

#!/bin/sh
mkfifo /tmp/mixer
ADDR=HEADSET
esdrec | dd conv=swab | sbcenc -z 44 -s 4 -j - | bttest $ADDR -
rm /tmp/mixer

If you really want to hear the monkey, if bttest is in the usr/local/bin folder and your monkey.sbc is on the desktop, in terminal type:

/usr/local/bin/bttest HEADSET /Users/YourUserNameEgJohn/Desktop/monkey.sbc

(replacing HEADSET with your bluetooth headset's device address, the same one which you've inserted into the a2dp.sh script).

Tim Hewett said...

So esdrec is sending wrong-endian audio... strange but easily fixed.

Regarding the audio gaps, I suffer the same problem on my 1.33GHz iBook G4 and 1.5GHz Intel Mini with the current download. The problem is that the Bluetooth A2DP audio transmission is very time-sensitive and if the Mac decides it has to do something else then you get gaps.

MacOS provides a way to give a process priority and I've been experimenting and have something which is working pretty reliably (using real-time scheduling, if interested).

This has only been done for bttest so far when really it needs to be done for the whole command chain starting with esdrec. Ideally it would all be integrated into one command and if we can get it working with JackOSX it'll be worth the effort to do it.

To try the current effort at a real-time bttest, download it from here:

http://www.coolatoola.com/bttest.zip

Incidentally it looks like sbcenc already provides a byte swap function, meaning that you can get rid of the new PPC "dd conv=swab" command and simply add the '-b' option to sbcenc.

Anonymous said...

I am trying to use this on a MacBook Pro with Jensen WBT212 headphones. It is connecting and is able to output sound, but the sound is messed up. When I play music, it makes a short noise every 5-10 seconds. When I do not play music, it makes no noise, so I think it is actually trying to play the audio. I have tried every bttest you've linked to, and it is the same.

Any ideas?

Tim Hewett said...

Unfortunately I can't test using esd as it won't work on either of my Macs. It's beginning to look as if the entire record/SBC encode/bttest command chain is going to have to be integrated into one high priority command. Fortunately I've found a recording application which doesn't need esd AND which works with Jack and it may not be too much work to create a single process as mentioned above.

As a test, try recording SBC into a file (replace "| bttest $ADDR -" with "> FILE.sbc" (replace FILE with a filename of your choice) - this will record into a file in SBC format instead of sending to the headphones. Once you have recorded a decent amount of audio to test with, do control-C and then "bttest ADDR FILE.sbc" to play the file out to the headphones. Make sure you use the bttest version from the location given in my previous post rather than the standard one included in the download.

Doing this should give you stable audio and it should usually survive you using the Mac of other things at the same time.

paobeleeso said...

Tim, I've tried the latest bttest version, and there are far less gaps in playback. But still too many to make it useable, and you're right about the gaps occuring when the computer is asked to do something.

I also did a test recording, outputting an .sbc file, and playing it back - there doesn't seem to be any gaps. But in the recording, I'm starting to hear what you call the pitch 'wow' much more. And the tempo 'wows' too - in the recording (or at least when playing it back) it is very marked.

All of that seems to confirm your hypotheses. Thanks!

Tim Hewett said...

Paobeleeso,

Make sure that the bttest you are using is the one at

http://www.coolatoola.com/bttest.zip

as that should cut the wow problems to pretty much zero. If it doesn't please say, but it does for me, and also cuts to virtually nil any problems with using the Mac while bttest is running.

It does sound like you're still using the old bttest...

John said...

Thank you, Paobeleeso.

But, I do have another problem that I don't know how to fix. When I try to open the 'a2dp.sh' file in Terminal, I get this annoying message that terminates the command. It says 'This is not an SBC file'. I have no idea what the problem could be...

paobeleeso said...

Tim, I downloaded the new bttest again, copied it to my local bin folder, and recorded another 2 minutes of music. Playing it back is totally gapless, and I can do other things at the same time, like type this comment (of course if I really tax the processor, I can produce gaps). But every now and again the recording stutters, speeds up, slows down, and messes around with pitch and tempo (I've listened over and over again to check whether it was the recording itself or the process of playing it back which contained the 'wow' effects). Really all of that is only minor though - it has no gaps and is already a great improvement on the live process. My machine and BT dongle are very old technology - maybe they have too many additional bottlenecks compared to your PPC machine ...

I've just realised that Soundflower doesn't need (or no longer needs) to be selected as the input device for this to work ... It only needs to be set as the output device.

Tim Hewett said...

Paobeleeso,

This all at least proves that reliably transmitting A2DP is fundamentally possible even on a 800MHz G4 using a USB 1.1 Bluetooth device. The pitch deviation and gaps were probably caused by hard disk delays reading the SBC file - even high priority processes have no choice but to wait for hard drives :-) . Also you can get pitch issues if radio noise causes the headphones to lose contact with the Mac temporarily (or if you go out of range etc.) and then recover.

I'm expecting that hard disk delays will disappear with a process which integrates recording, SBC encoding and A2DP transmission, since the entire process will keep the data in RAM.

I'm working on that and feel it isn't too far away. So far I've had a process which has recorded from JackOSX, piped that to sbcenc in the same way as esdrec and played it out to the headphones with a delay of about 0.5 seconds. The delay should come right down to the SBC framelength (plus whatever Jack adds) which amounts to 1-2ms, or the PCM frame size received from Jack which is 256 stereo 16 bit samples - about 6ms. Those are low latency figures. It could happen...

Kai said...

Hi...just found this.

Reporting that this seems to working fine for me on a macbook pro using built-in bluetooth and the absolutely *awesome* Motorola "thank god i no longer look like a total geek" S9 headphones.

I pretty much followed this giude to the letter...the only thing i did different was compile esound directly from the sources (latest is version 0.2.38).

What i am not clear on tho is why this is using soundflower...

Tim Hewett said...

Here is an integrated process for Mac A2DP which works with Jack (on PPC at least). I can't get it working with Jack on Intel at the moment, not sure why yet although recording from the built-in audio device works fine.

I have renamed the tool from bttest to a2dpcast.

What it now does is to record from the current sound input device as set in System Preferences, convert it to SBC and transmit that to the headphones. If you want to use JackOSX as the sound input, just select it in System Preferences as usual. To listen to iTunes, use the Jack router window to connect iTunes to a2dpcast (on PPC only as mentioned, though your Intel mileage may vary).

To use, extract the zip from

http://www.coolatoola.com/a2dpcast.zip

and copy the a2dpcast executable to your usual place, e.g. /usr/local/bin.

Then run it using "a2dpcast ADDR", replacing ADDR with your device's address as previously. No need for the old shell script as everything is now integrated into a2dpcast.

The tool does detect the incoming sample rate and adapt the SBC encoder and headphones to suit, but if the rate changes (as it can do by itself for Macs with optical digital inputs) you need to restart a2dpcast to have it adapt.

Lipsync is very good (i.e. audio latency is very low), at least if you use the built-in audio input device, but any radio glitch or other loss of contact between the headphones and Mac can cause this to be lost, at least for a time (I've seen it recover). At its best the lipsync is so good that you can't tell that your 'phones aren't directly connected. Also assuming decent reception, the pitch wow is minimal and resistance to the Mac being used for other things is high.

Tim Hewett said...

In addition to my last post, and as credit, this work has been very much piggy-backed on top of Apple's AudioFileTools example in /Developer/Examples, in fact there is a lot still there which isn't needed...

The creator of bttest (i.e. "bkc") will still recognise his code in spite of the severe mangling needed to have it all integrate.

Anonymous said...

Hi Tim,
thanks for your work.
I tried it, connecting my Jabra BT620s with my MacBook Pro.
I got this and very brief moment of sound...

Banana-9:~ thorsten$ /usr/local/bin/a2dpcast 00-13-17-71-aa-ff
setting thread 0x1d13 to precedence policy
sample rate is 44100, channels is 2
discover : received
SEID = 6
Sent set configurations command
set_config : rejected (serv_cat : 2, error_code: 0)
open : stream channnel
open_stream : ok
start_stream : ok
mtu = 672

frm_len = 69
50301 bytes/sec, hdr.sampling_frequency is 2
Transmitting A2DP, press RETURN to stop.

What does it actually mean above, that "set_config" is "rejected"?

Cheers, Thorsten.

Tim Hewett said...

I don't know what the set_config error is but mine does it too. I don't know why you're not getting audio, do you use the headphones right next to the Mac? From those logs everything is looking good, or normal at least.

I'm going to go back to the Linux roots of the bttest source and see how well it works with that. I'm suspicious of how well the tinny/mono audio that MacOS X System Preferences sends directly to the 'phones works when the phones go to the limit of the range - there's crackle and glitches but no huge gaps. If that behaviour can be transferred to the A2DP code then we're cooking, and it would be interesting to see how well Linux manages.

Anonymous said...

I tried to follow all instructions and succeeded insofar that from the bluetooth setup assistant I cannot pair. iStumbler allowed me to pair the Jabra BT320s via the A320s dongle. Upon running a2dp.sh both with bttest 1 and 2, I get the following result:
opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 69
open : control channnel
Failed to open connection
connectBTdevice : ng
I copied the device ADDR from iStumbler, using both notation $00-16-8f-etc as well as $00168fetc. Any hints?

Ard said...

Running Powerbook G4, using bttest2, entering the device address as a series of 0-9a-f without preceding $ or 0x, I managed to pair a BT320S via an A320s dongle. The device was unpaired at that moment, I discovered its address through iStumbler as the Bluetooth configuration assistand told me 'headsets are not supported on your Bluetooth hardware'.
The result is a purple breathing jabra BT dongle and an intermittant hissing when an audio source (eg. iTunes) is activated. 8 sec silence, 2 sec hiss, processor load is neglegtible. From the hissing one can deduce that someone is speaking (podcast). This is the output of the terminal at that time:

1-GHz-TiBook:/usr/local/bin ard$ ./a2dp.sh
opening socket, format = 0x00002021 at 44100 Hz
Bluetooth SBC player ver 0.1
frm_len = 69
open : control channnel
discover : received
SEID = 6
Sent set configurations command
set_config : rejected (serv_cat : 2, error_code: 0)
open : stream channnel
open_stream : ok
start_stream : ok
50301 bytes/sec
mtu = 672
k is 12345679ns

Tim Hewett said...

I'm using the Jabra BT320s using an iBook G4 1.33GHz and Intel Mac Mini 1.5GHz, both running OS 10.4.9. It paired fine using the Bluetooth pane of System Preferences with it set to search for headsets. Perhaps you are using an older version of OS X?

The best way to enter the device address is to copy/paste it from the device listing in System Preferences.

ard said...

In attempting to pair using the bluetooth assistant assistant, the very second I click 'continue' in the step to search for bluetooth headsets, I get a dialog 'Failed to setup the headset. Headsets are not supported on your bluetooth hardware'. I'm running 10.4.9, on a 1 GHz TiBook G4. The bluetooth hardware is the A320s dongle on the USB 1.0 bus in the back of the TiBook.
When I start a2dp.sh, I get a 'seemingly BlueTooth setup assistant' dialog that asks for a passphrase. After that, the headset is showing up in the Bluetooth Devices list of the system preferences.
I cannot configure however, the bluetooth setup assistant says 'therre were no supported services found on your device'. Continuing the setup congratulates me with my computer now being setup to use my bluetooth headset.
The headset is now blinking purple and is quiet until I start an audio source. The processor load (using menu meters) shows less than 25% load.
Switching on the SoundFlower output and starting to play iTunes gives a continuous hiss. The sunfower input input level jumps up and down wildly.
Pausing iTunes both stops the hiss and seemingly unrelated motion in the input devices input level.

Tim Hewett said...

The only USB Bluetooth adaptor supported by Apple is the DLink DT200 - your A320s isn't supported and it looks like Jabra don't provide their own OS X driver for it either.

I guess that might change with OS 10.5, who knows.

ard said...

Pairing is no evidence of working apparently. When changin ghe A320S Jabra dongle for a D-link DBT-120, the BT320S could be paired with without a hitch. The system preferences 'sound' now show both soundflower and Jabra BT320s. The soundflower still sends the hissing. It sounds as if 16-bit sound is sent, but is clipped to 8-bit sound; silence is OK, the moment a person starts to speak in the podcast you can hear them breath in and start speaking the first vowel, then hissing follows and this is repeated in every spoken word.
When one switches to the Jabra BT320s sound output in the system preferences 'sound' however, the sound is reasonable. Not HiFi stereo, but clearly one can hear the music and the spoken text, both overlayd with a substantial amount of noise.
It seems that I have had quite a workout to discover that the A320s is not supported and the audio quality of the BT320s is, well, not hifi.

Tim Hewett said...

Ard,

Don't select the Jabra in the System Preferences Sound pane as this is for mono telephony quality only (hands free profile). Instead choose your normal sound input and use the a2dpcast program, this will record from the sound input and transmit it to the headphones, and will have hifi stereo quality.

Ard said...

I followed your recommendation and indeed, audio quality now is as it should be. Occasionally the audio is dropped (processor load only reaches 50%) but quality is certainly hifi. Now I guess I just have to find the software to operate the mac via Bluetooth using the BT320s controls ;-)

Tim Hewett said...

If you use Linux then the control buttons work, I've had mine controlling Linux's XMMS media player for next/previous track and play/pause.

Unfortunately I've not managed to get any A2DP audio using Linux yet, only mono telephony.

Phil said...

Yep got it working... building from source is the go (the binaries as they are didn't work on my mac book - got the delayed = -xxx error)

Thanks David for getting this going, it's great... and to others I say use mplayer to handle the lag in vids with its real time audio delay keys +/-)

ben said...
This comment has been removed by the author.
ben said...

Followed the instructions from tim hewett (in his earlier post) and got my headphones (bluespoon spider on a 1.42GHz PPC mac mini) working perfectly....thanks to everybody who worked on this!

dsteinbrink said...

Just to add another "It Worked!" post.

I have a macbook pro and a Scosche BTHPK headset and now that i have this fix it's clearer than using the dongle that it came with.

For awhile I was hearing noise from both my headphones AND my speakers until I clicked the "routing" button in jackpilot, clicked "itunes" under send ports, and after made sure to double-click "a2dpcast" ALSO made sure to double click "aggregate device". The latter turned off the laptop speakers.

Thanks for the help!

John said...
This comment has been removed by the author.
John said...

In reply to the JackRouter way...

When I'm in the a2dpcast folder directory in Terminal, when I type in ./a2dpcast 00-07-a4-f2-9d-a1, it says there's no file...

Any help?

Anonymous said...

MacBook-Pro:~ leskovartem$ a2dp.sh
-bash: /usr/local/bin/a2dp.sh: Permission denied

any ideas?

David Connolly said...

please follow the updated instructions, noted on the first line of this blog post, that method is a dramatic improvement.

If there is a compelling reason why your using these old instructions do a:

chmod +x a2dp.sh

which will give the script permission to run.

Best of luck!

sam said...

I just found this conversation. I have a new Macbook with the Motorola HT820 headphones. The phones are "paired" and working fine but the sound is bad (like I'm in a tin box). Is this the problem for which you all are providing the remedy? I'm a bit of a novice. So if I follow your directions, my ears will be "happy"? Thanks in advance.

Quixotic said...

S-u-c-c-e-s-s:

Metal: MacBook Core Duo
Headset: Dell BH200
Tips: Make sure you d/l the XCode first. Let it run, and dont do any sound configs in the meantime. Install Soundflower. It took me about 10 minutes to run the process. D/L the bttest and go to your bin directory - which is hidden - unlock it by typing this in the terminal: defaults write com.apple.finder AppleShowAllFiles -bool TRUE . Now edit the a2dp.sh file in the desktop then transfer it over. Apple protects itself from the user so it's not going to keep asking you for your pass along the way, and this is the path of least resistance.

Now: Specify i/o as soundflower in the sys prefs. Run the process. Does it work? For me it didn't, however when I switched to my headset from the sys prefs afterwards, it did. So follow the instructions above, and do a little debugging, and you should be good.

Thanks for the tut, David!

Ceilidh Madigan said...
This comment has been removed by the author.
David Connolly said...

Hi, it has been a while since I've been intrested in this topic. I've upgraded to leopard and have not looked back since!

The only flaw (I can see) in the otherwise excellent instructions from asae / reposted on skyhorse.org is the presumption of /usr/local/bin being included in your bash profile path.

you can get around that easy, instead of typing:
1. a2dpcast aa-bb-cc-dd-ee-ff 27
type:
/usr/local/bin/a2dpcast aa-bb-cc-dd-ee-ff 27

etc.

Details on where it is failing would allow people to help, do the programs output anything when you run them?

Best of luck!

Gaurav said...

I have been trying to pair mot a120s9 and jabra A120 s but it fails.

please tell me as to how can they be paired. Few days back it worked fine and there was no problem in pairing....urgent reply will be appreciated ..mail me at achhabachha@gmail.com