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

Kicker - Glitch on key off #7225

Closed
1 task done
zonkmachine opened this issue Apr 25, 2024 · 7 comments · Fixed by #7226
Closed
1 task done

Kicker - Glitch on key off #7225

zonkmachine opened this issue Apr 25, 2024 · 7 comments · Fixed by #7226
Labels

Comments

@zonkmachine
Copy link
Member

zonkmachine commented Apr 25, 2024

System Information

Ubuntu 22.04

LMMS Version(s)

Tested on 1.2.2 up to 71dd300

Bug Summary

Kicker has a glitch around the time where key off is without the envelope engaged. You see a glitch below 2/3 into the sample.

Steps To Reproduce

Project that demonstrates the issue: KickerGlitch.mmp.txt <-- remove .txt

Screenshots / Minimum Reproducible Project

KickerGlitch

Please search the issue tracker for existing bug reports before submitting your own.

  • I have searched all existing issues and confirmed that this is not a duplicate.
@michaelgregorius
Copy link
Contributor

If I comment out the line

so->update( _working_buffer + offset, frames, Engine::audioEngine()->processingSampleRate() );

in KickerInstrument::playNote and change the code in the release section to output the attenuation factor

_working_buffer[f+offset][0] = fac;
_working_buffer[f+offset][1] = fac;

then I get the following output:

7225-Kicker-ReleaseAttenuation

I assume that there's either a jump with regards to releaseFramesDone in the note or with regards to desiredReleaseFrames in the release section.

@zonkmachine
Copy link
Member Author

I assume that there's either a jump with regards to releaseFramesDone in the note or with regards to desiredReleaseFrames in the release section.

Yeah, it looks like one of them lacks the offset.

@michaelgregorius
Copy link
Contributor

I have checked this some more and I think the problem is that done is not incrementing in full number of frames at the beginning of the release but that the for-loop processes a full number of frames each time. Outputting done and desired in the for-loop gives the following output:

Done: 0. Desired: 530
Done: 190. Desired: 530
Done: 446. Desired: 530

The value of frames is 256 each time. So the first jump is 190 frames (0 -> 190) and the second one 256 frames (190 -> 446). At the end of the first phase the value of fac has been processed for 256 samples though and has the value 0.51886791. At the start of the second phase it is calculated using done = 190 and the value is calculated as 0.641509414 which is larger than the value at the end of the first phase.

I am not really sure yet if the problem is within Kicker itself or even outside of it.

@michaelgregorius
Copy link
Contributor

I assume that there's either a jump with regards to releaseFramesDone in the note or with regards to desiredReleaseFrames in the release section.

Yeah, it looks like one of them lacks the offset.

To be frank I don't really know that the offset is and I find it insane that every plugin has to juggle around with all these values and has to do all the calculations for itself. Code like that is repeated over and over throughout the code base which gives a large potential for bugs like the one reported here. Ideally the calculations should be implemented correctly in one place and that code should be reused by every plugin. The current state is really ridiculous. ☹️

@zonkmachine
Copy link
Member Author

The tests above were present on a buffer size of 256. The glitch seem to disappear completely at a buffer size of 32. There's a hint of it on the second kick at buffer size 128.

@michaelgregorius
Copy link
Contributor

Hi @zonkmachine, it's definitively related to the buffer size. I think the problem is that the outside "framework code" and Kicker have a different understanding on how many release frames have already been applied on the buffer(s).

In my example above the frame size was 256. Kicker applies the release as soon as _n->isReleased() is true and then applies a release on the full buffer, i.e. 256 frames, instead of on only the number of frames that are associated with the the release phase. The framework code (or the note) however assumes that only 190 frames of release have been applied and reports this via releaseFramesDone. This leads to the discrepancy of 66 frames when the second buffer of the release is processed.

Smaller buffer sizes just seem to reduce the potential discrepancy because the difference between what the note thinks was applied and what Kicker thinks can at most be the buffer size.

In my opinion each plugin should keep track of the state because that's also how it's done in most other plugin formats (VST, CLAP, etc.). With these formats the plugin is only informed that a "(MIDI) Note Off" event has occurred at frame x and it can then interpret this however it wants. In many cases an internal ADSR would be informed to switch to its release stage but it could also do something completely different, e.g. open or close a gate.

The assumption of the Note class that a certain number of release frames are processed is already quite limiting in LMMS. And the fact that there is no clear separation of responsibilities leads to the problems like in this issue.

I assume that LMMS' "strange" architecture where each note is processed independently and where the same note can sound several times is one of the reasons why the known plugin formats are so hard to integrate as "natively" as they are integrated in other DAWs.

Ok, I'll end my rant here. 😅 It's just sad because the current architecture, the code that's repeated over and over again, etc. is holding the software back.

michaelgregorius added a commit to michaelgregorius/lmms that referenced this issue Apr 27, 2024
When applying its release stage Kicker did not take the frames before the release into account but instead always applied the release to the full buffer. This potentially lead to a jump in the attenuation values instead of a clean linear decay.

See LMMS#7225 for more details.
@michaelgregorius
Copy link
Contributor

@zonkmachine: Fixed by #7226.

michaelgregorius added a commit that referenced this issue Apr 27, 2024
When applying its release stage Kicker did not take the frames before the release into account but instead always applied the release to the full buffer. This potentially lead to a jump in the attenuation values instead of a clean linear decay.

See #7225 for more details.
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 a pull request may close this issue.

2 participants