Skip to content
This repository has been archived by the owner. It is now read-only.

record / pre level calculations during crossfade #4

Closed
catfact opened this issue Nov 12, 2018 · 5 comments
Closed

record / pre level calculations during crossfade #4

catfact opened this issue Nov 12, 2018 · 5 comments

Comments

@catfact
Copy link
Owner

@catfact catfact commented Nov 12, 2018

it's clear that the record and pre levels need to be modulated during the crossfade, along with the playback level.

the requirements are also pretty clear:

    1. at the end of the xfade, should have rec == 0, pre == 1.
    1. rec/pre curves should be "smooth," possibly with continuous derivative.
    1. there should never be perceived volume drops or volume spikes after repeated passes over the same material
  1. and 2) are pretty easy, but 3) is not so obvious. we've tried a few different ad-hoc combinationss of both linear and sinusoidal curves but have not yet hit on the right rec/pre relationship.

here's what we have now (the linear case for simplicity):

recprefade-linear-bump

the waterfall image shows successive states of the looped portion of a buffer (including a long crossfade,) which is first recorded with white noise, and subsequently overdubbed with silence. the rec/pre fade curves (shown at the top) produce a "bump" in the recorded level around the fade point, where the pre-level is too high compared to the record level level.

as the picture suggests, one way to interpret what we're doing here is: at each point in the crossfade, we're applying a different recursive filter to the level of the (old+new) signal, with one feedback term: if r(i) is the record value at a given point in the fade, and p(i) is the pre-level, then the filter difference equation is y(n) = r(i)*x(n) + p(i)*y(n-1); since p(i) > 0, this is a one-pole lowpass.

more specifically, p(i) determines the corner frequency of the lowpass, and r(i) is the gain factor.

question is: can we somehow keep the perceived cutoff freq constant while varying the rec level?

one proposal was waiting to change the pre level until the rec level is fully down. i don't think this is the answer - it keeps the decay constant during the xfade all right, but produces the opposite problem of a dip in volume while the pre-level ramps up.

@catfact
Copy link
Owner Author

@catfact catfact commented Nov 15, 2018

after trying many things, some new opinions:

  • trying to dynamically equalize the characteristics of the filter described above, using only the gain coefficient (record level), seems like a losing proposition. it's too dependent on the characteristics of past inputs.

  • i've come full circle to considering the "original" strategy where there was an adjustable coefficient for the amount by which xfade envelope modulated pre level:

    • when looping in one position, the optimal behavior is for the pre level to simply stay exactly the same throughout the fade.
    • but if we always do that, then moving the loop region such that it covers an old crossfade will reveal a click.

so, building on that consideration, we can construct a new compromise:

  • the record fade starts a few samples late on fadein, and ends a few samples early on fadeout. call this late/early number the "record fade delay" or dR.
  • in the beginning of fadein/end of fadeout, the pre-level executes a transition between the "base level" and 1.0. call this perid "pre fade window" or wP.

by adjusting dR and wP (they may overlap) we can tune a three-way compromise:

  • when wP > 0, there is a "bump" in the decay time (analogous to the one shown in the figure above.) this is exacerbated by making dR smaller in proportion to wP.
  • when dR > 0, there is a "dip" in recorded volume during the crossfade, exacerbated by making dR larger.
  • as wP approaches zero, the transition is more likely to be perceived as a click when moving loop points.

here is a figure showing one possible compromise: wP= 1/8, dR= 1/128, as fractions of fade time.
this waterfall differs from the previous one for clarity; it shows the summed crossfade, and it uses a simple impulse input instead of a random impulse.

near-constant-pre

unfortunately, this doesn't show the third leg of the compromise: the click when changing loop points. (it's just too much PITA to build a matlab model for this.) setting dR and wP both to zero would make the curve above look perfect (no dips or bumps) but the click would be maximally bad.

i'll add a c++ implementation of this strategy (using LUTs) and we can do a trial by ear. (@tehn)

@tehn
Copy link

@tehn tehn commented Nov 15, 2018

this sounds very smart, looking forward to testing

@catfact catfact mentioned this issue Nov 16, 2018
@catfact
Copy link
Owner Author

@catfact catfact commented Nov 17, 2018

better after PR#5 and subsequent commits, but there are still definite problems:

  • glitch with some rate settings (0.47 is a good one)
  • wobbling artifacts when setting pre=1, rec=0
@catfact
Copy link
Owner Author

@catfact catfact commented Nov 17, 2018

ok:

glitch with some rate settings (0.47 is a good one)

this is not the fade at all, something about resampler / output pointer (needs reset on subhead activation ?)

wobbling artifacts when setting pre=1, rec=0

i think this is due to both parameters undergoing exponential slew. as they sweep across each other a lump/dip in the written signal amplitude is created. will try different interpolation curves for these

@catfact
Copy link
Owner Author

@catfact catfact commented Nov 18, 2018

i think this is ok now. opened issue #8 for treating punch in/out/over.

@catfact catfact closed this Nov 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants