1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 05:17:35 +00:00

Piano: Add release

Notice that we are calculating release time according to the level when
the note is turned off rather than the sustain level. Naively using the
sustain level gives very long release times if you turn the note off
during attack, whereas this deterministically gives the same release
time.
This commit is contained in:
William McPherson 2020-02-05 18:00:16 +11:00 committed by Andreas Kling
parent ab9475a3f3
commit 59bde64ba6
5 changed files with 47 additions and 14 deletions

View file

@ -34,6 +34,7 @@ AudioEngine::AudioEngine()
set_sustain_impl(0);
set_attack(0);
set_decay(0);
set_release(0);
}
AudioEngine::~AudioEngine()
@ -62,6 +63,12 @@ void AudioEngine::fill_buffer(FixedArray<Sample>& buffer)
m_power[note] = m_sustain_level;
break;
case Release:
m_power[note] -= m_release_step[note];
if (m_power[note] <= 0) {
m_power[note] = 0;
m_envelope[note] = Done;
continue;
}
break;
default:
ASSERT_NOT_REACHED();
@ -158,6 +165,17 @@ double AudioEngine::noise() const
return w;
}
static inline double calculate_step(double distance, int milliseconds)
{
if (milliseconds == 0)
return distance;
constexpr double samples_per_millisecond = sample_rate / 1000.0;
double samples = milliseconds * samples_per_millisecond;
double step = distance / samples;
return step;
}
void AudioEngine::set_note(int note, Switch switch_note)
{
ASSERT(note >= 0 && note < note_count);
@ -171,8 +189,8 @@ void AudioEngine::set_note(int note, Switch switch_note)
} else {
if (m_note_on[note] >= 1) {
if (m_note_on[note] == 1) {
m_power[note] = 0;
m_envelope[note] = Done;
m_release_step[note] = calculate_step(m_power[note], m_release);
m_envelope[note] = Release;
}
--m_note_on[note];
}
@ -215,17 +233,6 @@ void AudioEngine::set_wave(Direction direction)
}
}
static inline double calculate_step(double distance, int milliseconds)
{
if (milliseconds == 0)
return distance;
constexpr double samples_per_millisecond = sample_rate / 1000.0;
double samples = milliseconds * samples_per_millisecond;
double step = distance / samples;
return step;
}
void AudioEngine::set_attack(int attack)
{
ASSERT(attack >= 0);
@ -253,6 +260,12 @@ void AudioEngine::set_sustain(int sustain)
set_decay(m_decay);
}
void AudioEngine::set_release(int release)
{
ASSERT(release >= 0);
m_release = release;
}
void AudioEngine::set_delay(int delay)
{
ASSERT(delay >= 0);