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

refactor: use higher-level std::span based logic #13654

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Swiftb0y
Copy link
Member

This is daschuer#97 rebased on main with the primary goal of making the logic easier to understand.

@Swiftb0y Swiftb0y force-pushed the review/daschauer/gh13611-metronome-effect-fix branch from 8db09c9 to b5c78c6 Compare September 15, 2024 14:30
@Swiftb0y
Copy link
Member Author

Swiftb0y commented Oct 4, 2024

noticed recently that the there was no use of the metaparameter within the metronome (and the gain always having the same volume being annoying), so I added a little simple gain knob in the newest commit.

@daschuer
Copy link
Member

daschuer commented Oct 9, 2024

Unfortunately the non synced mode does not produce a stady click. It sounds more like as rhythm.


template<class T>
std::span<T> subspan_clamped(std::span<T> in, typename std::span<T>::size_type offset) {
// TODO (Swiftb0y): should we instead create a wrapper type that implements
Copy link
Member

Choose a reason for hiding this comment

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

I think we should remove this function altogether.
It does not make sense to replace here an illformated span with an empty one and than check for it in the outer scope. Avoid the empty span as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't follow you. There is no ill-formed span (any operation that would produce one is already UB).

Copy link
Member

Choose a reason for hiding this comment

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

I see UB as anything can happen, but most likely there are no boundary checks to keep subspan() blazing fast, leading to a size_t overflow or such.

In our case not using the subspan_clamped() will speed up the code, because we can skip the empty span creation and the later isEmpty() check, if we will check for offset < size() in our business logic.

Copy link
Member Author

Choose a reason for hiding this comment

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

right, but offset < size() should not be part of the businesslogic. Explicit bounds checks are about as low level you can get so it doesn't make sense to have in high-level business logic. Thats explicitly why I put it into a utility function. From a high level perspective there is now only span. Either it has some sample content to play, or its empty and has none. This is a clear and intuitive API separation thats well worth paying two instructions for.

@Swiftb0y Swiftb0y force-pushed the review/daschauer/gh13611-metronome-effect-fix branch from 01b2a5f to b10d4b1 Compare October 10, 2024 14:04
@Swiftb0y
Copy link
Member Author

Unfortunately the non synced mode does not produce a stady click. It sounds more like as rhythm.

Fixed. mistakenly used kMaxEngineChannelInputCount instead of kEngineChannelOutputCount.

double framesPerBeat(mixxx::audio::SampleRate sampleRate, double bpm) {
double framesPerMinute = sampleRate * 60;
return framesPerMinute / bpm;
std::size_t samplesPerBeat(mixxx::audio::SampleRate sampleRate, double bpm) {
Copy link
Member

Choose a reason for hiding this comment

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

The old name was better, because mixxx::audio::SampleRate is actually frame rate. We used the name sample rate because this is more common for audio and also used in external libraries. In a second step it can be than converted to monoSmaples whith the same value.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, are you sure? I wasn't aware of that.

Copy link
Member Author

Choose a reason for hiding this comment

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

yup, confirmed. fixed in fixup

Comment on lines 169 to 173
std::size_t samplesSinceLastClick =
gs->framesSinceLastClick * mixxx::kEngineChannelOutputCount;
std::size_t offset = samplesSinceLastClick %
samplesPerBeat(engineParameters.sampleRate(),
m_pBpmParameter->value());
Copy link
Member

Choose a reason for hiding this comment

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

Here is somewhere a 2x issue.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in fixup.

playMonoSamplesWithGain(subspan_clamped(click, gs->framesSinceLastClick), output, gain);
gs->framesSinceLastClick += engineParameters.framesPerBuffer();

std::span<CSAMPLE> outputBufferOffset = [&] {
Copy link
Member

Choose a reason for hiding this comment

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

Can't we keep the original logic? It is hard to check if all conditions are still considered.

Copy link
Member Author

Choose a reason for hiding this comment

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

No. That is the point of this PR. Independent of the std::span usage, this was the part I wanted to improve because I very much struggled with understanding the logic you came up with here. So I rewrote it in a way I found more intuitive.
I'm confident that all the logic is still there (except #13733 because I couldn't reproduce that here). It just has been disentangled into smaller functions.

We're at an impasse now because we simply disagree about what is more readable. I don't understand your code, you don't understand mine. So I suggest we ask other team members to evaluate what solution they prefer and decide based on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants