-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Optional network clock reference #894
Conversation
Conflicts: src/soundio/sounddevicenetwork.cpp src/soundio/sounddevicenetwork.h src/soundio/soundmanager.cpp src/waveform/visualplayposition.cpp
Since 2.0 we have no "steam is broken" reports, but instead "stream is crackling" reports. |
Ping! |
Conflicts: src/soundio/sounddeviceportaudio.cpp src/soundio/sounddeviceportaudio.h src/soundio/soundmanager.cpp
This works nice again. Who has fun to review? |
Conflicts: src/preferences/dialog/dlgprefsounddlg.ui src/soundio/sounddevicenetwork.cpp src/soundio/soundmanager.cpp src/soundio/soundmanager.h
Conflicts: src/preferences/dialog/dlgprefsounddlg.ui src/soundio/soundmanagerconfig.cpp
What are the use cases for this? Is it only helpful for broadcasting with USB microphones? Does there need to be a preference option? Could Mixxx automatically switch to the network clock if different sound cards are used for input and output? |
void DlgPrefSound::engineClockChanged(int index) { | ||
if (index == 0) { | ||
// "Soundcard Clock" | ||
m_config.setForceNetworkClock(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this take effect only after the Apply button is pressed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, or the OK button.
src/soundio/sounddevicenetwork.cpp
Outdated
m_inputFifo = new FIFO<CSAMPLE>( | ||
m_iNumInputChannels * m_framesPerBuffer * 2); | ||
} | ||
// Feet the network device buffer directly from the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Feet"? Do you mean "Feed"?
if (isClkRefDevice) { | ||
// Update the samplerate and latency ControlObjects, which allow the | ||
// waveform view to properly correct for the latency. | ||
ControlObject::set(ConfigKey("[Master]", "latency"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using ControlObjects for this feels like an ugly hack. Should there be a TODO to pass this information directly to the waveform renderers without requiring a ControlObject?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code was adopted from here:
mixxx/src/soundio/sounddeviceportaudio.cpp
Line 369 in 2b26c46
ControlObject::set(ConfigKey("[Master]", "latency"), currentLatencyMSec); |
And I do not think this is a bad solution, because this way, the controllers can use this info as well.
(Like LPD8RK)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Controller scripts should not need this information. The Akai LPD 8 script seems to use this to hack beatjumping in JS, but we have that in C++ now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can update the LPD 8 mapping to fix that. Thanks for the reminder about that controller.
<item row="4" column="1"> | ||
<widget class="QComboBox" name="engineClockComboBox"> | ||
<property name="toolTip"> | ||
<string>Use soundcard clock for low latency setups. Use network clock for broadcasting only setups.</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should explain better in what situations this option might be useful. What is a "broadcasting only setup"? When there is no soundcard in use at all? If a user selects this option while broadcasting and monitoring the Master output on a soundcard, is there a chance of audible artifacts on the Master output?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broadcasting is just the same as a second soundcard with an individual clock.
Normally, the master output is taken to drive the mixxx engine,which produces a bit perfect output on master, all other soundcards (hardware and broadcasting) suffer from stuffing or lost samples.
This is unbearable in case of a hardware soundcard, but can be heard in broadcasting, because the big buffer sizes.
If you use the Network clock from this PR master will suffer also from unhearable stuffing or lost samples, but Broadcasting is bit perfect then assuming that the receiver runs also on an NTP synced cock.
With broadcast only I mean, that the audience is listening to broadcast only. No one cares about the quality of the master output in this case.
Do you have a better tooltip in mind?
"Use the network clock if the primary output is broadcasting"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about: "Use soundcard clock for live audience setups. Use network clock for broadcasting without a live audience." In the manual we can explain the reasoning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An additional critical point is, that we need some extra latency for the syncing code.
On my system I suffer master crackling at <= 10 ms buffer size.
How about this:
"Use soundcard clock for live audience setups and lowest latency. Use network clock for broadcasting without a live audience."
src/soundio/sounddevicenetwork.cpp
Outdated
m_underflowHappened = 1; | ||
} else if (writeAvailable > readAvailable + outChunkSize / 2) { | ||
// try to keep PAs buffer filled up to 0.5 chunks | ||
// catch up by filling buffer until we are a halve buffer behind |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/halve/half/
qDebug() << "SSE: Denormals to zero mode is working"; | ||
} | ||
#else | ||
qWarning() << "No SSE: No denormals to zero mode available. EQs and effects may suffer high CPU load"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should explicitly document this in the manual. A user did recently run into an issue with this on an old computer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I have filed an issue: mixxxdj/manual#62
src/soundio/soundmanager.h
Outdated
@@ -111,6 +113,15 @@ class SoundManager : public QObject { | |||
return m_pNetworkStream; | |||
} | |||
|
|||
void underflowHappened(int code) { | |||
m_underflowHappened = 1; | |||
if (CmdlineArgs::Instance().getDeveloper()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we always write this to the log? It could help with user support if we could see that in the log.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would make the situation worse, because we are here in the engine code and a Logging is locking code. A small unhearable glitch can become hearable because of that.
I will drop a comment.
I have glanced through the code and left some general comments, but I am not familiar enough with the technical background of the issue or how the SoundDevices work to comment much on the technical details. |
Done. |
That is a good point. In that case I'm okay with merging it as-is, unless @Palakis would like to review it first. |
Thank you for reviewing. :-) |
@daschuer These changes might have caused a regression: I didn't have time for more testing and in depth analysis. Any ideas? |
Ups, that is odd. I hope I find time tonight. Do you have any more info, why do you think this one is the cause? That may help. Thanks. |
@daschuer A first retest with this branch didn't reveal any negative impact. We have another serious issue that I need to analyze: Hope I will be able to find and fix the cause soon :/ |
I am trying to finish the #1254 review and than I will also dig into this. |
I can reproduce the stuttering issues loading a track using the network clock reference, and low latencies (11 ms) in my case. The soundcard clock runs with no issues here. Lets see if we can improve the situation. |
@daschuer By doing a git bisect I was able to locate the cause of the buffer underflows in your networkclockref branch. Unfortunately the code does not compile or Mixxx crashes with this commit range, so I was not able to identify a single commit. |
Ok, good news. What was your setup? |
I cannot confirm this. :-/
I have compared current master 24028f2 I played a track in deck 1 and analyzed a track in deck 2. What is your test case? |
I have also found a segfault with invalid SoundDevice pointers. |
This PR attempts to fix a lot of issues of users with multiplicands and broadcast set-ups.
During my test, it turns out that the soundcard clock is not passed as stable as expected up to the Mixxx engine.
RJ has reported a const drift, that is compensated by a double callback in core audio.
I am experience a double callback in ALSA double pause pair when I use a soundcard in duplex mode.
While these issues are harmless with a single soundcard, there is an overflow risk with the second soundcards or broadcasting.
This PR introduces a new preference option "Engine Clock" = "Network Clock" or "Soundcard Clock".
This allows to run the Mixxx engine on the Network Clock, which removes all syncing artefacts from the broadcast stream. This clock runs much more stable and suits to feet the soundcards with real-time priority as well.
I was also able fixes also lot of tiny issues in the syncing code. These where probably the cause of crackling in USB Mic setups reported in the forums.
.. And not at least it fixes the long standing "no transport" issue if no soundcard is configured.