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

Implement fade in to prevent Triple Osc from clicking #5199

Merged
merged 12 commits into from
May 19, 2020
3 changes: 3 additions & 0 deletions include/Instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ class LMMS_EXPORT Instrument : public Plugin


protected:
// fade in to prevent clicks
void applyFadeIn(sampleFrame * buf, const NotePlayHandle * _n);
necrashter marked this conversation as resolved.
Show resolved Hide resolved

// instruments may use this to apply a soft fade out at the end of
// notes - method does this only if really less or equal
// desiredReleaseFrames() frames are left
Expand Down
1 change: 1 addition & 0 deletions plugins/triple_oscillator/TripleOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ void TripleOscillator::playNote( NotePlayHandle * _n,
osc_l->update( _working_buffer + offset, frames, 0 );
osc_r->update( _working_buffer + offset, frames, 1 );

applyFadeIn(_working_buffer, _n);
applyRelease( _working_buffer, _n );

instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
Expand Down
49 changes: 48 additions & 1 deletion src/core/Instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
*/

#include "Instrument.h"
#include "InstrumentTrack.h"

#include <cmath>

#include "DummyInstrument.h"
#include "InstrumentTrack.h"
#include "lmms_constants.h"


Instrument::Instrument(InstrumentTrack * _instrument_track,
Expand Down Expand Up @@ -79,7 +83,50 @@ bool Instrument::isFromTrack( const Track * _track ) const
}


void Instrument::applyFadeIn(sampleFrame * buf, const NotePlayHandle * n)
{
// apply only if it's the start of the note
if (n->totalFramesPlayed() == 0)
{
const fpp_t frames = n->framesLeftForCurrentPeriod();

// zero point crossing counts of all channels
int zero_crossings[DEFAULT_CHANNELS] = {0};
// maximum zero point crossing of all channels
int max_zc = 0;

// determine the zero point crossing counts
for (fpp_t f = 0; f < frames; ++f)
{
for (ch_cnt_t ch=0; ch < DEFAULT_CHANNELS; ++ch)
{
if ((buf[f-1][ch] < 0.0 && buf[f][ch] > 0.0) ||
(buf[f-1][ch] > 0.0 && buf[f][ch] < 0.0))
{
++zero_crossings[ch];
if (zero_crossings[ch] > max_zc)
{
max_zc = zero_crossings[ch];
}
}
}
}

// calculate the length of the fade in
fpp_t length = (fpp_t) (
((float)frames - 1) /
((float)max_zc / 2.0f + 1.0f) / 3.0f);

// apply fade in
for (fpp_t f = 0; f < length; ++f)
{
for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch)
{
buf[f][ch] *= 0.5 - 0.5 * cosf(F_PI * (float) f / (float) length);
}
}
}
}

void Instrument::applyRelease( sampleFrame * buf, const NotePlayHandle * _n )
{
Expand Down