|
|
|
|
@@ -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,
|
|
|
|
|
@@ -78,8 +82,96 @@ bool Instrument::isFromTrack( const Track * _track ) const
|
|
|
|
|
return( m_instrumentTrack == _track );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helper function for Instrument::applyFadeIn
|
|
|
|
|
static int countZeroCrossings(sampleFrame *buf, fpp_t start, fpp_t frames)
|
|
|
|
|
{
|
|
|
|
|
// zero point crossing counts of all channels
|
|
|
|
|
int zeroCrossings[DEFAULT_CHANNELS] = {0};
|
|
|
|
|
// maximum zero point crossing of all channels
|
|
|
|
|
int maxZeroCrossings = 0;
|
|
|
|
|
|
|
|
|
|
// determine the zero point crossing counts
|
|
|
|
|
for (fpp_t f = start; f < frames; ++f)
|
|
|
|
|
{
|
|
|
|
|
for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch)
|
|
|
|
|
{
|
|
|
|
|
// we don't want to count [-1, 0, 1] as two crossings
|
|
|
|
|
if ((buf[f - 1][ch] <= 0.0 && buf[f][ch] > 0.0) ||
|
|
|
|
|
(buf[f - 1][ch] >= 0.0 && buf[f][ch] < 0.0))
|
|
|
|
|
{
|
|
|
|
|
++zeroCrossings[ch];
|
|
|
|
|
if (zeroCrossings[ch] > maxZeroCrossings)
|
|
|
|
|
{
|
|
|
|
|
maxZeroCrossings = zeroCrossings[ch];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return maxZeroCrossings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helper function for Instrument::applyFadeIn
|
|
|
|
|
fpp_t getFadeInLength(float maxLength, fpp_t frames, int zeroCrossings)
|
|
|
|
|
{
|
|
|
|
|
// calculate the length of the fade in
|
|
|
|
|
// Length is inversely proportional to the max of zeroCrossings,
|
|
|
|
|
// because for low frequencies, we need a longer fade in to
|
|
|
|
|
// prevent clicking.
|
|
|
|
|
return (fpp_t) (maxLength / ((float) zeroCrossings / ((float) frames / 128.0f) + 1.0f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Instrument::applyFadeIn(sampleFrame * buf, NotePlayHandle * n)
|
|
|
|
|
{
|
|
|
|
|
const static float MAX_FADE_IN_LENGTH = 85.0;
|
|
|
|
|
f_cnt_t total = n->totalFramesPlayed();
|
|
|
|
|
if (total == 0)
|
|
|
|
|
{
|
|
|
|
|
const fpp_t frames = n->framesLeftForCurrentPeriod();
|
|
|
|
|
const f_cnt_t offset = n->offset();
|
|
|
|
|
|
|
|
|
|
// We need to skip the first sample because it almost always
|
|
|
|
|
// produces a zero crossing; it's not helpful while
|
|
|
|
|
// determining the fade in length. Hence 1
|
|
|
|
|
int maxZeroCrossings = countZeroCrossings(buf, offset + 1, offset + frames);
|
|
|
|
|
|
|
|
|
|
fpp_t length = getFadeInLength(MAX_FADE_IN_LENGTH, frames, maxZeroCrossings);
|
|
|
|
|
n->m_fadeInLength = length;
|
|
|
|
|
|
|
|
|
|
// apply fade in
|
|
|
|
|
length = length < frames ? length : frames;
|
|
|
|
|
for (fpp_t f = 0; f < length; ++f)
|
|
|
|
|
{
|
|
|
|
|
for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch)
|
|
|
|
|
{
|
|
|
|
|
buf[offset + f][ch] *= 0.5 - 0.5 * cosf(F_PI * (float) f / (float) n->m_fadeInLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (total < n->m_fadeInLength)
|
|
|
|
|
{
|
|
|
|
|
const fpp_t frames = n->framesLeftForCurrentPeriod();
|
|
|
|
|
|
|
|
|
|
int new_zc = countZeroCrossings(buf, 1, frames);
|
|
|
|
|
fpp_t new_length = getFadeInLength(MAX_FADE_IN_LENGTH, frames, new_zc);
|
|
|
|
|
|
|
|
|
|
for (fpp_t f = 0; f < frames; ++f)
|
|
|
|
|
{
|
|
|
|
|
for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch)
|
|
|
|
|
{
|
|
|
|
|
float currentLength = n->m_fadeInLength * (1.0f - (float) f / frames) + new_length * ((float) f / frames);
|
|
|
|
|
buf[f][ch] *= 0.5 - 0.5 * cosf(F_PI * (float) (total + f) / currentLength);
|
|
|
|
|
if (total + f >= currentLength)
|
|
|
|
|
{
|
|
|
|
|
n->m_fadeInLength = currentLength;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
n->m_fadeInLength = new_length;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Instrument::applyRelease( sampleFrame * buf, const NotePlayHandle * _n )
|
|
|
|
|
{
|
|
|
|
|
@@ -109,6 +201,3 @@ QString Instrument::fullDisplayName() const
|
|
|
|
|
{
|
|
|
|
|
return instrumentTrack()->displayName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|