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

Optional network clock reference #894

Merged
merged 29 commits into from
Nov 20, 2017
Merged

Conversation

daschuer
Copy link
Member

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.

@daschuer
Copy link
Member Author

Since 2.0 we have no "steam is broken" reports, but instead "stream is crackling" reports.
This PR may solve some of these errors.
Who is able to check this out or review this code?
Thank you.

@daschuer daschuer mentioned this pull request Mar 1, 2016
@daschuer
Copy link
Member Author

Ping!

Conflicts:
	src/soundio/sounddeviceportaudio.cpp
	src/soundio/sounddeviceportaudio.h
	src/soundio/soundmanager.cpp
@daschuer
Copy link
Member Author

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
@Be-ing
Copy link
Contributor

Be-ing commented Jul 27, 2017

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);
Copy link
Contributor

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?

Copy link
Member Author

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.

m_inputFifo = new FIFO<CSAMPLE>(
m_iNumInputChannels * m_framesPerBuffer * 2);
}
// Feet the network device buffer directly from the
Copy link
Contributor

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"),
Copy link
Contributor

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?

Copy link
Member Author

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:

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)

Copy link
Contributor

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.

Copy link
Contributor

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>
Copy link
Contributor

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?

Copy link
Member Author

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"

Copy link
Contributor

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.

Copy link
Member Author

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."

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
Copy link
Contributor

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";
Copy link
Contributor

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.

Copy link
Member Author

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

@@ -111,6 +113,15 @@ class SoundManager : public QObject {
return m_pNetworkStream;
}

void underflowHappened(int code) {
m_underflowHappened = 1;
if (CmdlineArgs::Instance().getDeveloper()) {
Copy link
Contributor

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.

Copy link
Member Author

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.

@Be-ing
Copy link
Contributor

Be-ing commented Nov 19, 2017

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.

@daschuer
Copy link
Member Author

Done.
The good thing with this PR is that it is optional.
If we discover bugs after Mixxx is release, the user can just switch back to the souncards clock

@Be-ing
Copy link
Contributor

Be-ing commented Nov 19, 2017

That is a good point. In that case I'm okay with merging it as-is, unless @Palakis would like to review it first.

@Palakis
Copy link
Contributor

Palakis commented Nov 20, 2017

@Be-ing Looking at the code, no comments to make so far. One thing though: I believe this should be merged before #1300, as SoundDeviceNetwork was modified here and there.

@daschuer
Copy link
Member Author

Thank you for reviewing. :-)

@daschuer daschuer merged commit f76d5c7 into mixxxdj:master Nov 20, 2017
@uklotzde
Copy link
Contributor

@daschuer These changes might have caused a regression:
https://bugs.launchpad.net/mixxx/+bug/1738028

I didn't have time for more testing and in depth analysis. Any ideas?

@daschuer
Copy link
Member Author

Ups, that is odd. I hope I find time tonight.
As a band aid we have to revert this commit if we have no solution in time.

Do you have any more info, why do you think this one is the cause? That may help. Thanks.

@uklotzde
Copy link
Contributor

@daschuer A first retest with this branch didn't reveal any negative impact.

We have another serious issue that I need to analyze:
https://bugs.launchpad.net/mixxx/+bug/1738227

Hope I will be able to find and fix the cause soon :/

@daschuer
Copy link
Member Author

I am trying to finish the #1254 review and than I will also dig into this.

@daschuer
Copy link
Member Author

I can reproduce the stuttering issues loading a track using the network clock reference, and low latencies (11 ms) in my case.
I consider this as just too short fort the internal clock. Probably m_pThread->start(QThread::TimeCriticalPriority); i

The soundcard clock runs with no issues here.

Lets see if we can improve the situation.

@uklotzde
Copy link
Contributor

uklotzde commented Dec 16, 2017

@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.

@daschuer
Copy link
Member Author

Ok, good news. What was your setup?
Was it with --developer flag? What was the final effected commit range?

@daschuer
Copy link
Member Author

I cannot confirm this. :-/
My Setup:

  • Ubuntu Trusty, ALSA
  • internal Souncard: Master
  • USB Soundcard: Headpones
  • 48000 kHz 5,33 ms
  • Multi Souncard = Default

I have compared current master 24028f2
with the commit just before merging this f76d5c7

I played a track in deck 1 and analyzed a track in deck 2.
No overflows in both version.
I only notice a cpu usage peak in the old version when analysis starts.

What is your test case?

@daschuer
Copy link
Member Author

I have also found a segfault with invalid SoundDevice pointers.
I am working on a share pointer solution

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.

5 participants