-
-
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
[Bug #1299029] phaser effect #560
Conversation
I found a phaser here [0] which served as a starting point. I also used the formula from [1] which is also used in the phaser listed above. |
Thanks for working on this! In what way did you use the textbook's code? Like, as a base of c++ which you then edited to match Mixxx's API, or more just for how the phaser algorithm works? |
To be honest, I found the code useful in both ways. The implementation from that book is almost identical to the one here [ 0 ] also the ones in the comment section. What is different from the implementations from there is the "magical" formula which I put above. The recipe is the same: combining the original signal with a copy passed through several all-pass filters which only change the phase. [0] - http://musicdsp.org/showArchiveComment.php?ArchiveID=78 |
Should I try another implementation? |
Thank you for your great work. Just tested the phaser and it sounds crazy. ... You may look at stomp box phaser reviews on youtube to find nice knob scales/ranges. I do not like the the stereo phasing. As far as I know a classic phaser does not do this. |
|
||
if ((counter++) % updateCoef == 0) { | ||
for (int j = 0; j < stages; j++) { | ||
CSAMPLE delayLeft = 0.5 + 0.5 * sin(leftPhase); |
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 part of the code is confusing. What is delayLeft, really a sample value, or a time?
It changes the content though the function. It would be nice to use a new speaking name every time the content changes. (The compiler will throw them out anyway)
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.
What does sweepWidth?
Please add a lot more comments. The resonance circuit suffers clamping. This can be avoided by limit it with tanh. |
rightPhase = fmodf(freqSkip * pState->time + M_PI, 2.0 * M_PI); | ||
|
||
if ((counter++) % updateCoef == 0) { | ||
for (int j = 0; j < stages; j++) { |
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.
Why is this a loop? Didn't we use the same coefs for all stages?
Hey @daschuer , I'm working with @jercaianu to find another implementation that will be free of the licensing issues here. You can hold off on the review until we know what we're doing. |
What is exactly the license issue here? I cannot find a single line copied from the GPL 3 textbook source. The underlying knowledge is in the public domain and pretty much the same was discussed at the musicdsp mailing list, which is "for anyone who is interested". But again, @jercaianu has not just copied an existing implementation from there. |
That is what I was discussing with him specifically. I didn't look through the source myself. He seemed to agree that there could be an issue. |
|
||
EffectManifestParameter* stereo = manifest.addParameter(); | ||
stereo->setId("stereo"); | ||
stereo->setName(QObject::tr("Stereo")); |
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.
Thank you. This works for me for now. Maybe we can set the shift between L and R later by a knob.
Thank you for your reviews! I have reformatted the code and i think the sound ranges are ok. |
@jercaianu: The position of the effect parameters are decided by the skin. You can't put an effect parameter to the side of the effect rack. As far as I know, this is the order in the skin: Regarding the |
IMHO we have no license issues here (see my comment above) Since we can consider this as @jercaianu's work, we can merge it at any time. |
We need really MUCH more comments in this code to reduce the magical nature a bit. |
CSAMPLE depth = m_pDepthParameter->value(); | ||
CSAMPLE feedback = m_pFeedbackParameter->value(); | ||
CSAMPLE range = m_pRangeParameter->value(); | ||
int stages = 2 * m_pStagesParameter->value(); |
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.
You can use here a switch control like Nicu has proposed to get around the scaling issue.
Otherwise you need a region that snaps to a desired number of stages.
There is a crackling noise when turning the Stages knob. |
The resonance still suffers overshooting, we should avoid to break the users speakers ;-) |
The rate slider suffers bubbling noise when turned. Be sure the coefs do not jump. |
The range slider produces sample overshoot when at leftmost position. |
@daschuer Thank you for your feedback! I fixed the rate knob issue by using the old rate value until I have settled for a new one. Also, I added tanh to where I'm using the feedback value. I have used the knob Nicu proposed. Hopefully I added enough comments. |
The signal is clipped by tanh even though the depth parameter is 0. |
Yes, i included the input signal by mistake. I fixed the issue |
Thank you, the "noise" issues are gone now. :-) Negative range of the feedback ... OK, we have an effect in that range, but is this a phaser? LFO Rate: We should allow much faster rates like 50 or something, this would be no problem if we switch to a logarithmic knob. The stages knob is somehow broken. (not your fault) It switches to zero if you click on it. |
EffectManifestParameter* frequency = manifest.addParameter(); | ||
frequency->setId("lfo_frequency"); | ||
frequency->setName(QObject::tr("Rate")); | ||
frequency->setDescription("Controls the speed of the effect."); |
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.
"Controls the speed of the low frequency oscillator"
Regarding the negative feedback, I have used as a reference the phaser in Audacity, which also offers this option. Regarding the stages knob, I shall take a look into the problem. I feel that if the rate took higher values the output sound would be too chaotic. I also think that the max rate value I used is a bit higher than necessary. |
In order for the code to be good to merge, what else should I do? |
|
||
if (pState->change) { | ||
pState->wait++; | ||
if (pState->wait == pState->limit) { |
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 do not understand how it works. Playing with the rate knob it looks like it works sometimes.
If you move the knob continuously the new value seams to be not adopted.
It looks like the root issue is below. See below ...
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 intended this behaviour in order to avoid bubbling noises while changing the rate knob. The rate value updates when i settle for a certain value.
There should be nothing against merging this after the pending rate issue is fixed. |
I have looked for the issue in the widget folder. I think that is issue is somewhere located in weffectpushbutton or wpushbutton, but i havent exactly pinpointed the problem. |
Really nice fix for the rate knob issue. I guess that it would be alright for the moment to use the previous knob for 'Stages' until the toggle one is fixed. |
Filed a bug report for the knob issue |
LGTM! It works really nice now |
I tried to implement a phaser inspired by the one already done in Audacity. However the output does not sound well. I'm not sure whether this can be improved, or if i should start looking somewhere else. Thanks !