Syncs using PTP and pyaudio callback#1
Open
glmnet wants to merge 21 commits intosystemcrash:masterfrom
Open
Conversation
Addresses the reconnect issue and 100% CPU consumption after disconnect
-AAC -ALAC -OPUS -PCM (may need tweaking) This commit programmatically constructs the appropriate QuickTime atom extradata chunk for ALAC to suit sample-size/rate/channels. It also dynamically determines the correct playback clock rates, instead of the static 44100.
which is a smidge faster than struct.
-increment_index -decrement_index -get_fullness Refactor find_seq from linear to binary search Bin = O(log n) vs linear O(n) - binary iterates max several times vs linear (up to) thousands
This commit adds a stable latency calculation which accounts for: -default playback device latency -pyaudio buffers and ensures that this receiver falls into synchronization with other playing devices. May need to pause/unpause play when a new device joins. Admittedly, the output is not phase locked, but PTP may help to take care of that. We actually *want* the play-head to be offset and ahead. This way, it synchronizes with other Airplay players (this is why Airplay clients stream a bunch of RTP in advance). In my tests with other Sonos endpoints - this latency calculation puts everything in sync to within a millisecond. Idea: dynamically announce output device latency into the plist sent to the sender.
This commit implements PTPv2 Slave in Python3.
It will listen and slave to other Masters. There is no code to run as
Master yet. Everything necessary for Airplayv2. Import this file and:
if "timingProtocol" in plist:
if plist['timingProtocol'] == 'PTP':
print('PTP Startup')
mac = int((ifen[ni.AF_LINK][0]["addr"]).replace(":", ""), 16)
self.ptp_proc, self.ptp_link = PTP.spawn(mac)
Bitshifting is an expensive operation in python. It's possible that
for every new byte shifted to the left, a new object is created to hold
the data.
int.from_bytes appears to be the most efficient binary unpacking method
(without requiring imports) - sometimes unpack is a smidge faster:
--
data = bytes.fromhex('1b02005400000608000000000000000000000000'\
'010203040506000583bf017905fe00000000000000000000000000f8f8fe4'\
'36af8010203fffe0405060001a000080010010203fffe0405060202030405060005')
--
def test3():
correctionNanoseconds = int.from_bytes(data[8:16], byteorder='big')
print(timeit.timeit("test3()", globals=locals(), number=100000000))
>>> 26.746907015000033
--
import struct
def test2():
correctionNanoseconds = struct.unpack(">Q", data[8:16])[0]
print(timeit.timeit("test2()", globals=locals(), number=100000000) )
>>> 26.19966978500088
--
def test():
correctionNanoseconds = \
data[8] <<40|data[9] <<32|data[10]<<24| \
data[11]<<16|data[12]<< 8|data[13]
print(timeit.timeit("test()", globals=locals(), number=100000000) )
>>> 43.50181922199772
--
Owner
|
Like! One potential issue: does everything still work the same/as well as before, in case, e.g., someone turns off PTP in the Flags? We're going to lint and clean up the code, (I will rebase my master also) and once those are in, you can rebase and tidy up the PR. 😄 Unless you want to rebase from the main repo? |
Author
|
Yeah. I can apply changes in a clean master. This is a mess since I formatted with black |
Author
|
Then I'm gonna PR against openairplay directly |
systemcrash
pushed a commit
that referenced
this pull request
Jul 14, 2021
windows set volume by pid
b88bcc6 to
57e4a3b
Compare
5810460 to
445a3b3
Compare
6ab566c to
ca4db5c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hey there,
Though better create another thread to share my findings.
No noticeable audio skips now!!
This one I'm using the callback, this way we know more precisely when data is going to be played. It needs more love though
I applied a filter to the PTP, in my findings the PTP sync is quite ugly, i.e. it just jumps a few msec back and forth quite often which causes the stream to do skips.
The RTP buffer needs to be able to track back and forth, added a new
previous()method to go back, however it might be interesting to get the frame we need directly instead of advancing / going back.Pause, seek, and track skip is not working well