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

Smoothly ramp changes in gain. #39

Merged
merged 40 commits into from
Jul 27, 2013
Merged

Smoothly ramp changes in gain. #39

merged 40 commits into from
Jul 27, 2013

Conversation

ywwg
Copy link
Member

@ywwg ywwg commented Jul 8, 2013

https://bugs.launchpad.net/mixxx/+bug/854082

Add copyWithRampingGain, applyRampingGain and addWithRampingGain methods to SampleUtil and use them to ramp changes in gain in various places:

  • deck EQs
  • deck pregain
  • channel volume
  • channel orientation
  • crossfader
  • master volume
  • headphone volume
  • head/mix

Still remaining to be done:

  • balance

// buffers must be the same length. pDest may be an alias of the source
// buffers. pSrc1 is the buffer that is fading out, pSrc2 is the buffer
// that is fading in.
static void crossfadeBuffers(CSAMPLE* pDest,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call it linearCrossfadeBuffers since it does linear crossfades.

@daschuer
Copy link
Member

daschuer commented Jul 8, 2013

Thank you for the fix. I just want to clarify that the result is Audio-buffer-size dependent, right?
But It looks suitable.

@rryan
Copy link
Member

rryan commented Jul 8, 2013

Yea, the crossfade step is dependent on the audio buffer size so depending on the magnitude of the change in gain we could still get clicks (as we talked about on the bug report).

@ywwg
Copy link
Member Author

ywwg commented Jul 9, 2013

The worst-case scenario I can imagine is 1ms latency at 44.1Khz, which is 44.1 samples per buffer. Even having that amount of space to interpolate is better than nothing. But also, as the buffer becomes smaller the delta gain will also become smaller because the user has less time to make the change. (Could a user twist a knob from 64 to 0 in 1ms? unlikely). So in practice I'd be surprised if it were possible to cause clicks.

@rryan
Copy link
Member

rryan commented Jul 9, 2013

An eq kill button or resetting an eq knob could take it from max value to 0 in one callback. There's really no perfect solution :). This one is a good one.

@ywwg
Copy link
Member Author

ywwg commented Jul 9, 2013

(the most recent changes are untested, but it builds. Do not merge until I've actually done testing)

@ywwg
Copy link
Member Author

ywwg commented Jul 11, 2013

the crossfader and gain knob additions are total fails. I will fix them.

@ywwg
Copy link
Member Author

ywwg commented Jul 11, 2013

Ok pregain and master are working now, but headphone is tougher because it has a bunch of moving pieces that aren't all together (balance, gain, master mix)

@ywwg
Copy link
Member Author

ywwg commented Jul 13, 2013

OK to merge?

private:
double m_dVolume, m_dLeftGain, m_dCenterGain, m_dRightGain;
QMap<ChannelInfo*, double> m_cache;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than use a QMap, can you keep the cached value in ChannelInfo? We already have ChannelInfo. It may be ugly but it avoids using a QMap in the callback.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, the problem with that is it becomes difficult to do the comparison of the current gains to the previous gains to see if we need to do a crossfade. With the map, I can see if the two maps are equal. But without it, I'll have to iterate through the list of pchannels.

@ywwg
Copy link
Member Author

ywwg commented Jul 14, 2013

notes addressed other than caching suggestion (see comment). (and I will squash some commits before merging so please let me do the final merge)

@@ -397,6 +403,20 @@ void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBuff
// Perform the master mix
mixChannels(masterOutput, maxChannels, m_pMaster, iBufferSize, &m_masterGain);

// Avoid soundwave discontinuties by interpolating from the old gains to new.
if (!m_masterGain.compare(m_prevMasterGain)) {
// We are reusing p_pPrevGainBuffer from above, but its data isn't needed
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of date comment

@ywwg
Copy link
Member Author

ywwg commented Jul 18, 2013

Rebased, merged in RJ's changes.

@ywwg
Copy link
Member Author

ywwg commented Jul 18, 2013

I will do some testing on this tonight before I commit the merge.

@rryan
Copy link
Member

rryan commented Jul 18, 2013

Cool -- thanks! There are still those outdated comments you marked to fix.

We should do some profiling. mixChannels is not an engine hot-spot (at least, it's nowhere near as hot as the EQs) -- it takes tens of microseconds last time I checked. But it would still be interesting to know the change ramping causes on various hardware.

@ywwg
Copy link
Member Author

ywwg commented Jul 18, 2013

performance testing:

I loaded a track, started playing it, and then wiggled the mid eq really fast with the mouse.

trunk:
Debug [Main]: Stat("EngineBuffer::process_pauselock","count=326,sum=1.5881e+07ns,average=48714.8ns,min=4987ns,max=200271ns,variance=1.08776e+09ns^2,stddev=32981.2ns")
Debug [Main]: Stat("EngineMaster::mixChannels_0active","count=650,sum=1.80178e+06ns,average=2771.96ns,min=678ns,max=23088ns,variance=5.54639e+06ns^2,stddev=2355.08ns")
Debug [Main]: Stat("EngineMaster::mixChannels_1active","count=326,sum=1.0642e+06ns,average=3264.41ns,min=1082ns,max=11261ns,variance=3.05933e+06ns^2,stddev=1749.09ns")
Debug [Main]: Stat("EngineMaster::process","count=488,sum=1.56157e+08ns,average=319993ns,min=29216ns,max=1.20952e+06ns,variance=5.92068e+10ns^2,stddev=243325ns")
Debug [Main]: Stat("EngineMaster::process channels","count=488,sum=5.39613e+10ns,average=1.10577e+08ns,min=-2.14373e+09ns,max=2.12896e+09ns,variance=1.56943e+18ns^2,stddev=1.25277e+09ns")

crossfade:
Debug [Main]: Stat("EngineBuffer::process_pauselock","count=274,sum=9.736e+06ns,average=35532.8ns,min=6704ns,max=146136ns,variance=3.20477e+08ns^2,stddev=17901.9ns")
Debug [Main]: Stat("EngineMaster::mixChannels_0active","count=738,sum=1.36968e+06ns,average=1855.94ns,min=673ns,max=18869ns,variance=1.56249e+06ns^2,stddev=1250ns")
Debug [Main]: Stat("EngineMaster::mixChannels_1active","count=274,sum=714816ns,average=2608.82ns,min=1332ns,max=13053ns,variance=1.54973e+06ns^2,stddev=1244.88ns")
Debug [Main]: Stat("EngineMaster::process","count=506,sum=8.55766e+07ns,average=169124ns,min=25801ns,max=654444ns,variance=1.49361e+10ns^2,stddev=122213ns")
Debug [Main]: Stat("EngineMaster::process channels","count=506,sum=6.00099e+10ns,average=1.18597e+08ns,min=-2.14136e+09ns,max=2.13266e+09ns,variance=1.52487e+18ns^2,stddev=1.23486e+09ns")
Debug [Main]: Stat("EngineSideChain:writeSamples","count=506,sum=1.63087e+06ns,average=3223.07ns,min=881ns,max=346295ns,variance=2.41958e+08ns^2,stddev=15555ns")

I think it's better? I'm surprised about that.

@ywwg
Copy link
Member Author

ywwg commented Jul 27, 2013

LGTM and stuff

ywwg added a commit that referenced this pull request Jul 27, 2013
Smoothly ramp changes in gain.
@ywwg ywwg merged commit 11f3c5a into mixxxdj:master Jul 27, 2013
@ywwg ywwg deleted the crossfade_util branch July 27, 2013 02:14
@kain88-de
Copy link
Member

Ok I tracked down the first commit that makes the enginemaster test fail, it is 6d5d02f

After this enginemaster changes the channel buffer. When you later also merge in all the changes of rryan everytest starts to fail. I guess it has something to do with the changes you made in the gain calculation but I'm not sure since I don't understand the code here.

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