Audio support
I have some research to be able playing audio on DS4.
Audio data send by opcode 0x14, 0x15, 0x17, 0x19.
And code by SBC audio codec.
I used this python script to wrap the audio data
play.py
This script takes the SBC audio data and send it to DS4
You can use gstreamer to prepare audio data.
gst-launch-1.0 -q audiotestsrc ! sbcenc ! 'audio/x-sbc,channels=2,rate=32000,channel-mode=dual,blocks=16,subbands=8,bitpool=25' ! queue ! fdsink | ./play.py
But there is a small problem, periodically occur stuttering.
But it may be caused by improper operation with HID device.
I hope this helps to add audio support.
Wow! This is actually working. Thank you so much for this.
I also get some stuttering. Perhaps the bluetooth signal is not perfect.
And small addition
If add is-live=true to audiotestsrc
gst-launch-1.0 -q audiotestsrc is-live=true ! sbcenc ....
Stuttering becomes much less
And useful pipeline to play all output to DS4
gst-launch-1.0 -q pulsesrc device="alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" ! queue ! audioresample ! 'audio/x-raw,rate=32000' ! audioconvert ! sbcenc ! 'audio/x-sbc,channels=2,rate=32000,channel-mode=dual,blocks=16,subbands=8,bitpool=25' ! queue ! fdsink | ./play.py
To get device name u can use
pacmd list-sources | grep -e device.string -e 'name:'
Great! Do you know if there is a way to control the volume?
Yes in last script version have variables volume_l, volume_speaker.
And also I found, only left channel playing by DS
I have mine plugged in via USB without ds4drv running
dmesg shows the controller as /dev/hidraw5 and the script is set to use it
name: <alsa_output.pci-0000_00_1b.0.analog-stereo.monitor>
gst-launch-1.0 -q pulsesrc device="alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" ! queue ! audioresample ! 'audio/x-raw,rate=32000' ! audioconvert ! sbcenc ! 'audio/x-sbc,channels=2,rate=32000,channel-mode=dual,blocks=16,subbands=8,bitpool=25' ! queue ! fdsink | ./play.py
Without the play.py, fddsink outputs data to the terminal correctly. With play.py the controller vibrates sporadically and has no sound coming from the speaker.
Arch x86_64
EDIT: Is this supposed to only work via Bluetooth?
Hmm... It's strange.
You can test
gst-launch-1.0 -q audiotestsrc is-live=true ! sbcenc ! 'audio/x-sbc,channels=2,rate=32000,channel-mode=dual,blocks=16,subbands=8,bitpool=25' ! queue ! fdsink | ./play.py
And what Kernel version you have?
uname -a
I test on last ubuntu 16.04
audiotestsrc is also silent
Linux e73 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
EDIT: Is this supposed to only work via Bluetooth?
Yes only Bluetooth
This is working for me. I used pactl load-module module-null-sink sink_name=ds4 to set up a nicer looking pulseaudio sink, which audio outputs can be selectively output to from pavucontrol. The pulseaudio-dlna project uses something like this quite nicely by adding some extra stuff to the pactl options.
The stuttering seems to go away for me if I use an encoding rate of 16000 instead. Play.py seems to crash every once on a while on pf.write though.
What did you pass to gstreamer to make it use the new sink?
@parkerlreed You can use this to get the names:
pacmd list-sources | grep -e device.string -e 'name:'
So if your named sink is ds4 then you can probably use this:
gst-launch-1.0 -q pulsesrc device="ds4.monitor"
Ahh thanks.
If you open pavucontrol, under the "playback" tab, you can select the "Null Output" output from a dropdown menu once you have something playing.
The 16000 does sound a lot crappier though.
You also can try always send _17_report instead _14_report. For the 32kHz, works better.
So report 17 and 14 are the same except for the amount of audio data? I'm getting much better playback having replaced everything with report 17.
The hidraw writing freezing every once in a while is still a problem for me though. Is anyone else having that problem?
I'm sort of getting around it by setting a SIGALRM timeout as described at http://stackoverflow.com/a/22348885/445799 . Not the nicest option though.
So report 17 and 14 are the same except for the amount of audio data?
Yes. Also 19 same as 15 except for the amount of audio data.
And first part of 15 and 19 same as 11
Nice. Any info on the timing between reports? I'm finding I have better sound with a slight delay between packets. For me, it's better when I print a bunch of garbage to the terminal than when I don't.
Any info on the timing between reports?
No, but http://eleccelerator.com/files/ds4_uart_hci_cap_playroom_needs_sorting.pcap.gz may be help.
You cant filter packet from PS4 using bthid[0] == 0xa2 img
Any recommendations on programs to use to look at that file? I'm not too familiar with hardware stuff, so I've not touched something like this before.
Ok, I'm having better luck setting up a SIGALRM timeout in a multiprocessing.Process. I was using a threading.Thread, but performance wasn't good enough. Setting the timeout to somewhere around 2*448/32000 seconds is working well enough to allow for a dropped packet or two. There must be a better solution though.
Moving controllers in ds4drv out to processes might be a good idea anyway.
I've added the changes to your play.py with the timeout process here
Wireshark can open file. You can see on screenshot. Before open you need ungzip.
Woops, forgot about the encoding. Testing with dd suggests data is coming in at about 27.9 kB/s when encoding a 32 kB/s stream.
I'm getting some good results putting the timeout around pf.write on a fairly short timeout value. I've updated the gist to match.
I think I've found the volume balance. In b'\x02'+ audo_data of the reports, it's that \x02 value.
I think I've found the volume balance
What means "volume balance". For what purpose use \x02 before audio_data?
When playing stereo audio, only one channel was coming through and my right earphone was very quiet.
Setting it to different values changes the relative loudness of the two earphones. So it seems there might not be a left volume / right volume, but instead a total volume and relative volume.
When playing stereo audio, only one channel was coming through and my right earphone was very quiet.
I ran into the same problem, but take earphone with microphone on the jack I get right sound good.
It seems that only supports mono.
This seems to be working for me:
header = bytes([int('00100011', 2)]), with header in place of \x02.
I was looking at https://tools.ietf.org/html/draft-ietf-avt-rtp-sbc-01#section-6.3
Looks like 00100100 should be the right header for report 17 for the sbcenc settings from gstreamer.
No. Gstreamer generate sbc header. 0x02 - it's not SBC header SBC header is 0x9c, 0x75, 0x19, 0x24 0x9c - sync 0x75 - 0b1110101 0x19 - bitpool ...