Skip to content

sync echo effect to BPM#1256

Merged
daschuer merged 23 commits intomixxxdj:masterfrom
Be-ing:tempo_sync_echo
Sep 25, 2017
Merged

sync echo effect to BPM#1256
daschuer merged 23 commits intomixxxdj:masterfrom
Be-ing:tempo_sync_echo

Conversation

@Be-ing
Copy link
Copy Markdown
Contributor

@Be-ing Be-ing commented May 10, 2017

make Delay knob range from 0 to 2 beats

make Delay knob range from 0 to 2 beats
@ronso0
Copy link
Copy Markdown
Member

ronso0 commented May 10, 2017

Cool, thanks for working on this and #1254 and #1255!!
So the knob would be linear, meaning center position would be 1 beat?

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 10, 2017

So the knob would be linear, meaning center position would be 1 beat?

Kinda but not exactly. The minimum is not 0, so the exact center of the knob is approximately 1 beat but not exactly 1 beat. I'll try implementing a workaround for that.

@ronso0
Copy link
Copy Markdown
Member

ronso0 commented May 10, 2017

Okay. But the default (right-clicking the knob) can be set to 1 beat, right?

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 10, 2017

Okay. But the default (right-clicking the knob) can be set to 1 beat, right?

I have the default set as 1/2 beat. Try it, I think you'll find it makes sense.

@daschuer
Copy link
Copy Markdown
Member

We cannot just replace delay by beats. Echo is a typical mic effect without any beat information.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 10, 2017

We cannot just replace delay by beats. Echo is a typical mic effect without any beat information.

As explained by the comment in the code, a tempo of 100 BPM is assumed if there is no tempo information available. Do you have any ideas for how to handle that case better? Previously the delay value was random, so assuming 100 BPM isn't much better or worse.

Comment thread src/effects/native/echoeffect.cpp Outdated
delay->setName(QObject::tr("Time"));
delay->setDescription(QObject::tr("Delay time\n"
"0 - 2 beats if tempo is detected (decks and samplers) \n"
"0 - 2 seconds if no tempo is detected (mic & aux inputs, master mix, headphone mix)."));
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@esbrandt is this a good way to handle the tooltip?

@ronso0
Copy link
Copy Markdown
Member

ronso0 commented May 12, 2017

I tested this together with #1254 (which works great with Echo!) but somehow the default delay is always a bit higher than twice the BPM.
To test I played 2-beat loops with clear high hats or bass drums, Time knob I left at default position (1/2 beat?). For a 160 BPM track the echo had around 180 BPM, and for a 100 BPM track I got someting like 108.

@ronso0
Copy link
Copy Markdown
Member

ronso0 commented May 12, 2017

And Sent was full On after start although Meta knob was a lower limit.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 12, 2017

I tested this together with #1254 (which works great with Echo!) but somehow the default delay is always a bit higher than twice the BPM.
To test I played 2-beat loops with clear high hats or bass drums, Time knob I left at default position (1/2 beat?). For a 160 BPM track the echo had around 180 BPM, and for a 100 BPM track I got someting like 108.

Maybe you're getting confused by the feedback? Try playing with the feedback parameter. And yes, the default time is 1/2 beat.

@ronso0
Copy link
Copy Markdown
Member

ronso0 commented May 13, 2017

Maybe you're getting confused by the feedback? Try playing with the feedback parameter.

May be, but I don't see how feedback affects timing. This sounded odd that's why I measured it.
Will test again.

In case someone does not want it to synchronize to the tempo
@Be-ing Be-ing mentioned this pull request May 15, 2017
1 task
@Be-ing Be-ing force-pushed the tempo_sync_echo branch from e816e4e to 1c9c5a1 Compare May 17, 2017 01:37
@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 26, 2017

Do you like the new scaling for the Time parameter? It ranges from 1/4 to 2 beats and the value is floored to the nearest 1/4 beat. If we like this, I'll adopt it for the other temporal effects after merging this. I think flooring to the nearest 1/2 beat might be more appropriate for flanger and phaser.

Comment thread src/effects/native/echoeffect.cpp Outdated
delay->setDescription(QObject::tr("Delay time (seconds)"));
delay->setName(QObject::tr("Time"));
delay->setDescription(QObject::tr("Delay time\n"
"1/4 - 2 beats rounded down to nearest 1/4 beat if sync parameter is enabled and tempo is detected (decks and samplers) \n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

1/4 - 2 beats, snapping to the nearest 1/4 beat step if ...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is a pity that the current value is only part of the debug tooltip. In this case it would be handy to have this in normal mode as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is visible without running in developer mode.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I mean the "current value of the CO like "1.5". This is not visible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, yeah that is a shame. But let's leave that issue for after 2.1.


EffectManifestParameter* delay = manifest.addParameter();
delay->setId("delay_time");
delay->setName(QObject::tr("Delay"));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Delay is IMHO the correct name for this parameter and should be kept. Time is only the physical quantity, without further meaning.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think "Delay" is confusing because that often refers to a more complex effect:

The term “echo” was used more often in the early days, and is sometimes used today to refer to the distinct and distant repeats of a signal, while “delay” refers to anything from the same, to the short repeats heard as reverb, to the complex, long, manipulated repeats of an intricate digital delay line.

http://www.gibson.com/News-Lifestyle/Features/en-us/effects-explained-echo-delay.aspx

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK.In this case "Time" is OK.

delay->setName(QObject::tr("Delay"));
delay->setDescription(QObject::tr("Delay time (seconds)"));
delay->setName(QObject::tr("Time"));
delay->setDescription(QObject::tr("Delay time\n"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

"Delay time", is redundant, because a delay is always a time.

@daschuer
Copy link
Copy Markdown
Member

I have just tested this on top of master.
It looks like the echo still saves its buffer over a enabled/disabled cycles. Haven't we fixed this earlier?

Comment thread src/effects/native/echoeffect.cpp Outdated
feedback->setMaximum(1.0);
feedback->setMinimum(0.25);
feedback->setDefault(0.75);
feedback->setMaximum(0.90);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should stay on 1.0. This allows to cycle a echo until infinity, after we have no input anymore.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think there is also a use-case for feedback 0.0. this allows to fade the effect out or in from zero.

Copy link
Copy Markdown
Contributor Author

@Be-ing Be-ing May 28, 2017

Choose a reason for hiding this comment

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

I think there is also a use-case for feedback 0.0. this allows to fade the effect out or in from zero.

That is what the send knob is for.

Copy link
Copy Markdown
Contributor Author

@Be-ing Be-ing May 28, 2017

Choose a reason for hiding this comment

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

This should stay on 1.0. This allows to cycle a echo until infinity, after we have no input anymore.

This is an echo effect, not a looper. The effect should not be able to continue forever without input. I tried setting the maximum feedback to 0.99 and it prevents the output level from continuously escalating and getting out of hand until the deck clips, but the output continues for a very long time and effectively acts as a loop.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we have any complains about it? I think not, so this is not a required change for this PR and for me a undesired regression.

Clipping can happen anyway with electronic music and an exact beat loop.
We should consider to replace the clipper with a tanh clipper to make it sound more natural (more analog).
https://github.com/mixxxdj/mixxx/blob/master/src/effects/native/phasereffect.cpp#L147
or better the fast approximation:

inline float tanh_approx(float input) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we have any complains about it?

I am complaining about it. The effect's buffer clipping isn't the issue; the ease of clipping the deck with feedback at 1, send at 1, and dry/wet at 1 is the issue.

Copy link
Copy Markdown
Member

@daschuer daschuer May 28, 2017

Choose a reason for hiding this comment

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

That seems to be a known issue of an echo/delay effect, and sometimes a desired feature.

Each one of these repetitions will gradually fade out as new ones are created, unless you have the feedback cranked up full, in which case the signal will keep compounding until it reaches a deafening squall.

http://www.musicradar.com/tuition/tech/the-ultimate-guide-to-effects-delay-457920

I have just read some stompbox manuals and there is no other feedback range than 0 .. 100 % implemented.

I think we have an other issue here with our gain leveling. If we play a track with RG loudness, the digital level is likely at 50 %, our delay buffer clamper on the other hand, clamps on digital full level, which is most likely much louder than the source signal and will clip the soundcard output with any tiny other signal added.

If we use a tanh clipper this would be better because it kicks in somhow earlier. We can also add a gain to the clipping value to let et clip even earlier and may also make this a parameter which is default to a value that matches the input level.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That seems to be a known issue of an echo/delay effect, and sometimes a desired feature.

Hmm, if it's the standard way I could revert it. Anyone else have an opinion?

I think we have an other issue here with our gain leveling. If we play a track with RG loudness, the digital level is likely at 50 %, our delay buffer clamper on the other hand, clamps on digital full level, which is most likely much louder than the source signal and will clip the soundcard output with any tiny other signal added.
If we use a tanh clipper this would be better because it kicks in somhow earlier. We can also add a gain to the clipping value to let et clip even earlier and may also make this a parameter which is default to a value that matches the input level.

That's an interesting idea. The output of the effect is divided by 2 before mixing with the dry signal. Let's not delay merging this PR for that though. If you have ideas for improving that, let's merge this first, then you can open a new PR for that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did a bit more research, and you are right, a restricted range for the feedback parameter is not normal on an echo effect. I have restored it to the 0 - 1 range with 0.75 as default. I came up with an interesting alternate metaknob linking that somewhat approximates a beatmasher effect: link both the Time and Feedback parameters to the metaknob, invert the link for the Time parameter, unlink the Send parameter and turn it all the way up.

@daschuer
Copy link
Copy Markdown
Member

It look like there is something wrong with the Echo effect.
Test: play just one beat from a track, using a feedback of one and a delay of 2 beats.
Expected behavior: The beat should loop at halve tracks bpm.
Actual behavior: I hear two beats with different tempos cycling arround.

Does the beat go back to 2 s after the track has stopped? I think this should stick to the current track bpm as it were playing.
In an earlier version, it is possible to change the BPM of the single beat by the delay knob. This is now somehow broken as well.

Comment thread src/util/math.h
return power;
}

inline double roundToFraction(double value, int denominator) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we should round to the nearest value, otherwise all values have a "snaping region", but not the topmost value,
2 in this case, is only adopted on the very maximum.

@daschuer
Copy link
Copy Markdown
Member

daschuer commented May 28, 2017 via email

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 28, 2017

Does the beat go back to 2 s after the track has stopped? I think this should stick to the current track bpm as it were playing.

No, it does not. I tested adding a qDebug() << groupFeatures.beat_length and watching the debugging output. The beat length is still reported to the effect correctly when the deck reaches the end of the track.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented May 28, 2017

I have just tested this on top of master.

I suggest testing it with #1254. It's a lot of fun :D

It looks like the echo still saves its buffer over a enabled/disabled cycles. Haven't we fixed this earlier?

I cannot reproduce this. I merged the fix in master into this branch.

@ronso0
Copy link
Copy Markdown
Member

ronso0 commented Sep 18, 2017

Anyone else care to test? @ronso0?

Sure, if I find time to compile this week

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 18, 2017

Ardour ships with a set of LV2 plugins including a delay which has the desired effect when adjusting its time parameter. For reference, the code of the effect is here: https://github.com/Ardour/ardour/blob/0b6e2d1e46b9dfe72fe879d2ddddafeafda07023/libs/plugins/a-delay.lv2/a-delay.c#L448

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 18, 2017

I copied the algorithm from Ardour's a-Delay plugin. It seems to work, but I don't fully understand all the details. There may still be room for improvement.

Comment thread src/effects/native/echoeffect.cpp Outdated
}

gs.wet_sample_left = SampleUtil::clampSample(
(gs.wet_sample_left + gs.delay_buffer[read_position_left]) / 2.0);
Copy link
Copy Markdown
Contributor Author

@Be-ing Be-ing Sep 18, 2017

Choose a reason for hiding this comment

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

a-Delay does some curious crossfading between the samples here using 1 / numSamples, but I don't understand the reasoning behind that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Without fully understanding the code, that might be for the pitch effect, of e real tape delay if you change the delay time. Without it we might here click sounds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There are some minor click sounds when changing the Time parameter quickly but I am not sure of their source. I tried the crossfading with 1/numSamples technique that a-Delay uses but it does not solve the issue. The size of the engine's buffer is an artifact of the software's configuration and shouldn't have any impact on the sound of an effect.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Emulating the pitch shifting of an analog delay would be fun, but I don't know how to implement that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Guitarix has a nice sounding tape delay LV2 plugin but it is written in Faust and does some complicated modeling of tape including wow & flutter. I checked a-Delay again and adjusting its Time parameter does not have the popping sound this does. I'm not sure what is different that is causing the popping here.

Comment thread src/effects/native/echoeffect.cpp Outdated
// period is a number of beats
if (m_pTripletParameter->toBool()) {
if (period <= 0.125) {
period = 0.041666666666666664; // 1/8 / 3
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use her directly "1/8 / 3". The preprocessor is able to calculate that at compile time.

@daschuer
Copy link
Copy Markdown
Member

The parameter interface is nice now.
Did you consider to reduce the quantization points on the delay knob?

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 18, 2017

Do you mean to round to 1/8 beats or to 1/2 beats?

@daschuer
Copy link
Copy Markdown
Member

The range is OK. I originally thought to halve the delay on every step, like we do with the looping controls.
The real issue is, that we have no visual feedback if we run in non developer mode.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 18, 2017

Yes, that is definitely an issue. But solving the visual feedback issue would require quite some more work to make a new skin widget, update the skins, and create a way for the effect to show a nicely formatted value (like 1/4 instead of 0.25223134). IMO that can wait for the following release.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 18, 2017

Although we do not have visual feedback of the current value of parameters, we can at least specify the ranges in the descriptions so the user can have a clue what is going on by reading the tooltip.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 19, 2017

If you would prefer, I can split the last commit off to a new branch so we can merge this now.

@daschuer
Copy link
Copy Markdown
Member

daschuer commented Sep 22, 2017

Yes good idea.The interface is nice now, so the buffering changes are more easy to review in a separate PR.
Can you fix the looong decimals issues in this PR?

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 25, 2017

Ready for merge?

@daschuer
Copy link
Copy Markdown
Member

Thank you, this is a real fun effect now.
LGTM.

@daschuer daschuer merged commit 7946a80 into mixxxdj:master Sep 25, 2017
@Be-ing Be-ing deleted the tempo_sync_echo branch September 25, 2017 12:30
@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Sep 25, 2017

Great! I will test the syncing with flanger and phaser again. I am not sure if the Quantize and Triplet parameters make sense for those effects like they do for Echo.

@ronso0
Copy link
Copy Markdown
Member

ronso0 commented Oct 8, 2017

Is it intended that echo fades out much faster with Triplets enabled?
Would be handy to have the same fade time like without it.

@Be-ing
Copy link
Copy Markdown
Contributor Author

Be-ing commented Oct 8, 2017

Yeah, the echo time is divided by 3. If you want to extend the fade out, you could turn up the feedback.

@daschuer
Copy link
Copy Markdown
Member

daschuer commented Oct 8, 2017

Adopting the normal fade out time for triplets is IMHO a valid request. Unfortunately the feedback gain behaviour might be unexpected in case it is adopted for triplets.
Mmm, what is the most expected behaviour?

@sohet sohet mentioned this pull request Oct 15, 2017
This was referenced Aug 22, 2022
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.

3 participants