Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework how drain stop the stream #529

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

achronop
Copy link
Contributor

This improves how we stop the stream when it is drained. Also, it addresses BMO 1572273. Unfortunately, I cannot verify that without the specific device mentioned there. @ChunMinChang can you please test it with your device? If the test passes we can land this one and skip #528 .

The logic for draining a stream was odd. After drain the AU stop was happening on the next callback. That could create race conditions especially when reinit is taking place at the same time. This patch triggers the stop of AU at the end of the same callback and set the shutdown flag in order to exit early any following callback.
@achronop
Copy link
Contributor Author

@kinetiknz
Copy link
Collaborator

From memory, we trigger the drain logic on the next callback to allow time for the buffer we just wrote to play out. With this change, I think we'll stop too early. It's probably quite hard to notice since we'd miss less than 11ms (default latency, could be lower) of audio in the typical case. It might be worth verifying with a higher latency stream/device (Bluetooth) and a short sound effect.

@ChunMinChang
Copy link
Member

I don't understand the problem the changes would solve here. If it's a solution for a different problem from #528, the changes can be tested without my devices. If the changes are for the same problem, I'll appreciate if you can state your opinions in the review comments.

@achronop
Copy link
Contributor Author

achronop commented Sep 3, 2019

From memory, we trigger the drain logic on the next callback to allow time for the buffer we just wrote to play out. With this change, I think we'll stop too early.

I did an experiment that the stream was drained on the first callback. This produced a very small (in terms of duration) sound effect. I guess that was the one filled buffer. I could try to hack the latency to something larger and try again.

Can you recall if you had a specific problem that made you call the stop on the next callback or it was a "better safe than sorry" decision?

@achronop
Copy link
Contributor Author

achronop commented Sep 3, 2019

I don't understand the problem the changes would solve here. If it's a solution for a different problem from #528, the changes can be tested without my devices. If the changes are for the same problem, I'll appreciate if you can state your opinions in the review comments.

The changes here include a fix for the problem in #528. I thought a patch would be a faster explanation of my idea. Sorry about that I will comment on #528. Nevertheless, I would appreciate if you can test it with your device and tell me what you see. Thank you in advance.

@achronop
Copy link
Contributor Author

achronop commented Sep 4, 2019

I could try to hack the latency to something larger and try again.

I did an experiment similar to the above with a modified version of the backend that allowed big latency. Again, the stream drained at first callback. I verified that audio data of length equal to latency is written in the output. I started with a latency of 441 and ended with a latency of 4410 (for a rate of 44100). Further increase of the latency had no effect.

@kinetiknz
Copy link
Collaborator

Thanks for testing! Maybe there's no issue, and I don't remember any other details now. https://lists.apple.com/archives/coreaudio-api/2005/Dec/msg00049.html seems to suggest it works as you've observed, so I assume we waited an extra callback cycle just to be safe.

@kinetiknz
Copy link
Collaborator

Also https://lists.apple.com/archives/coreaudio-api/2005/Dec/msg00055.html, in particular:

When AudioDeviceStop() is called on the IO thread, things are different. The HAL will not call the IOProc that was stopped again after the AudioDeviceStop() call completes, but the buffer provided by that IOProc will get played (and nothing after that from that IOProc).

@achronop
Copy link
Contributor Author

achronop commented Sep 5, 2019

Thanks for the links! That was a very interesting thread!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants