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

Release is abrupt during attack phase #265

Open
ngeiswei opened this issue Feb 22, 2019 · 8 comments
Open

Release is abrupt during attack phase #265

ngeiswei opened this issue Feb 22, 2019 · 8 comments

Comments

@ngeiswei
Copy link
Contributor

ngeiswei commented Feb 22, 2019

How to reproduce

  1. Create a new instrument with ADSR
ATK:3F
SUS:1F
DEC:00
REL:3F
  1. Press some key down to play a note
  2. In the middle of the attack phase release the note. The note volume decreases abruptly.
  3. Press again some key down, this time release only after a while once it has reached the sustain phase. The note volume decreases slowly as expected.

What should be expected

The note volume should decrease at the speed set to REL regardless of the ADSR phase.

@ngeiswei
Copy link
Contributor Author

For what I can gather from klystron/src/snd/cyd.c, adsr->envelope seems to be evolving as expected. Maybe the problem is in cyd->lookup_table...

@ngeiswei
Copy link
Contributor Author

ngeiswei commented Feb 22, 2019

I think I know! There is a discontinuity between the formula used to turn the envelope into amplifier factor during attack (see cyd_env_output of klystron/src/snd/cyd.c)

		if (adsr->envelope_state == ATTACK)
			return ((Sint64)input * ((Sint32)adsr->envelope / 0x10000) / 256) * (Sint32)(adsr->volume) / MAX_VOLUME;

and the formula used during release

		else
			return ((Sint64)input * (cyd->lookup_table[(adsr->envelope / (65536*256 / LUT_SIZE) ) & (LUT_SIZE - 1)]) / 65536) * (Sint32)(adsr->volume) / MAX_VOLUME;

When release occur right in the middle of the attack the amplifier factor suddenly jumps to another value!

I don't know what could be the proper fix, and I might not see the big picture well enough to find it.

@ngeiswei
Copy link
Contributor Author

It seems to me the simplest trick to solve that would be to re-ajust adsr->envelope right at release time so that the amplifier factor resulting from lookup_table would be close to the last amplifier factor calculated by the attack formula.

@ngeiswei
Copy link
Contributor Author

Given the way lookup_table is defined, the translation formula should be something like

new_env = sqrt(old_env) * alpha

where

  • old_env is the value of adsr->envelope right after releasing
  • new_env should be the new value assigned to adsr->envelope at transition (only need to do it once, at the start of the release)
  • alpha is some constant factor to determine.

@ngeiswei
Copy link
Contributor Author

If I'm correct the correct translation formula is

new_env = sqrt(old_env * 65536 * 256)

now time to try!

P.S: sorry for the multiplicity of posts. I prefer to update my progress frequently to not duplicate effort, in case someone else is looking at this too.

@kometbomb
Copy link
Owner

Multiple messages are fine, great that you are finding the solution!

@ngeiswei
Copy link
Contributor Author

It works! :-) :-) :-)

I still need a bit more time to create a proper PR but here comes the question, what to do about backward compatibility?

@kometbomb
Copy link
Owner

kometbomb commented Feb 23, 2019 via email

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

No branches or pull requests

2 participants