NotePlayHandle: send correct MidiNoteOff events if base note changed
When changing an InstrumentTrack's base note while NotePlayHandles are active, they will send a wrong MidiNoteOff event due to the masterKey() translation in InstrumentTrack::processOutEvent(). Therefore in NotePlayHandle remember the original base note value and add the difference between original and current base note to the value returned by NotePlayHandle::key(). Fixes hanging notes in MIDI-based instruments such as ZynAddSubFX. Furthermore some coding style improvements. Closes #3146975.
This commit is contained in:
@@ -88,12 +88,12 @@ public:
|
||||
void playNote( notePlayHandle * _n, sampleFrame * _working_buffer );
|
||||
|
||||
QString instrumentName() const;
|
||||
inline const Instrument * instrument() const
|
||||
const Instrument *instrument() const
|
||||
{
|
||||
return m_instrument;
|
||||
}
|
||||
|
||||
inline Instrument * instrument()
|
||||
Instrument *instrument()
|
||||
{
|
||||
return m_instrument;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
int masterKey( int _midi_key ) const;
|
||||
|
||||
// translate pitch to midi-pitch [0,16383]
|
||||
inline int midiPitch() const
|
||||
int midiPitch() const
|
||||
{
|
||||
return (int)( ( m_pitchModel.value()+100 ) * 16383 ) / 200;
|
||||
}
|
||||
@@ -135,22 +135,27 @@ public:
|
||||
// load instrument whose name matches given one
|
||||
Instrument * loadInstrument( const QString & _instrument_name );
|
||||
|
||||
inline AudioPort * audioPort()
|
||||
AudioPort * audioPort()
|
||||
{
|
||||
return &m_audioPort;
|
||||
}
|
||||
|
||||
inline MidiPort * midiPort()
|
||||
MidiPort * midiPort()
|
||||
{
|
||||
return &m_midiPort;
|
||||
}
|
||||
|
||||
IntModel * baseNoteModel()
|
||||
const IntModel *baseNoteModel() const
|
||||
{
|
||||
return &m_baseNoteModel;
|
||||
}
|
||||
|
||||
Piano * getPiano()
|
||||
IntModel *baseNoteModel()
|
||||
{
|
||||
return &m_baseNoteModel;
|
||||
}
|
||||
|
||||
Piano *pianoModel()
|
||||
{
|
||||
return &m_piano;
|
||||
}
|
||||
|
||||
@@ -57,11 +57,12 @@ public:
|
||||
|
||||
virtual void setVolume( const volume_t _volume = DefaultVolume );
|
||||
|
||||
int getMidiVelocity() const;
|
||||
int midiVelocity() const;
|
||||
int midiKey() const;
|
||||
|
||||
const float & frequency() const
|
||||
{
|
||||
return( m_frequency );
|
||||
return m_frequency;
|
||||
}
|
||||
|
||||
void updateFrequency();
|
||||
@@ -69,22 +70,22 @@ public:
|
||||
// returns frequency without pitch-wheel influence
|
||||
float unpitchedFrequency() const
|
||||
{
|
||||
return( m_unpitchedFrequency );
|
||||
return m_unpitchedFrequency;
|
||||
}
|
||||
|
||||
virtual void play( sampleFrame * _working_buffer );
|
||||
|
||||
virtual inline bool done() const
|
||||
{
|
||||
return( m_released && framesLeft() <= 0 );
|
||||
return m_released && framesLeft() <= 0;
|
||||
}
|
||||
|
||||
f_cnt_t framesLeft() const;
|
||||
|
||||
inline fpp_t framesLeftForCurrentPeriod() const
|
||||
{
|
||||
return( (fpp_t) qMin<f_cnt_t>( framesLeft(),
|
||||
engine::getMixer()->framesPerPeriod() ) );
|
||||
return (fpp_t) qMin<f_cnt_t>( framesLeft(),
|
||||
engine::getMixer()->framesPerPeriod() );
|
||||
}
|
||||
|
||||
|
||||
@@ -95,12 +96,12 @@ public:
|
||||
|
||||
inline f_cnt_t framesBeforeRelease() const
|
||||
{
|
||||
return( m_framesBeforeRelease );
|
||||
return m_framesBeforeRelease;
|
||||
}
|
||||
|
||||
inline f_cnt_t releaseFramesDone() const
|
||||
{
|
||||
return( m_releaseFramesDone );
|
||||
return m_releaseFramesDone;
|
||||
}
|
||||
|
||||
f_cnt_t actualReleaseFramesToDo() const;
|
||||
@@ -109,7 +110,7 @@ public:
|
||||
// returns total numbers of frames to play
|
||||
inline f_cnt_t frames() const
|
||||
{
|
||||
return( m_frames );
|
||||
return m_frames;
|
||||
}
|
||||
|
||||
void setFrames( const f_cnt_t _frames );
|
||||
@@ -117,34 +118,39 @@ public:
|
||||
// returns whether note was released
|
||||
inline bool released() const
|
||||
{
|
||||
return( m_released );
|
||||
return m_released;
|
||||
}
|
||||
|
||||
// returns total numbers of played frames
|
||||
inline f_cnt_t totalFramesPlayed() const
|
||||
{
|
||||
return( m_totalFramesPlayed );
|
||||
return m_totalFramesPlayed;
|
||||
}
|
||||
|
||||
// returns volume-level at frame _frame (envelope/LFO)
|
||||
float volumeLevel( const f_cnt_t _frame );
|
||||
|
||||
// returns instrument-track this note-play-handle plays
|
||||
inline InstrumentTrack * instrumentTrack()
|
||||
const InstrumentTrack *instrumentTrack() const
|
||||
{
|
||||
return m_instrumentTrack;
|
||||
}
|
||||
|
||||
// returns whether note is a base-note, e.g. is not part of an arpeggio
|
||||
// or a chord
|
||||
inline bool isBaseNote() const
|
||||
InstrumentTrack *instrumentTrack()
|
||||
{
|
||||
return( m_baseNote );
|
||||
return m_instrumentTrack;
|
||||
}
|
||||
|
||||
// returns whether note is a top note, e.g. is not part of an arpeggio
|
||||
// or a chord
|
||||
inline bool isTopNote() const
|
||||
{
|
||||
return m_topNote;
|
||||
}
|
||||
|
||||
inline bool isPartOfArpeggio() const
|
||||
{
|
||||
return( m_partOfArpeggio );
|
||||
return m_partOfArpeggio;
|
||||
}
|
||||
|
||||
inline void setPartOfArpeggio( const bool _on )
|
||||
@@ -157,7 +163,7 @@ public:
|
||||
|
||||
inline bool isMuted() const
|
||||
{
|
||||
return( m_muted );
|
||||
return m_muted;
|
||||
}
|
||||
|
||||
void mute();
|
||||
@@ -176,7 +182,7 @@ public:
|
||||
|
||||
inline bool bbTrackMuted()
|
||||
{
|
||||
return( m_bbTrack && m_bbTrack->isMuted() );
|
||||
return m_bbTrack && m_bbTrack->isMuted();
|
||||
}
|
||||
void setBBTrack( track * _bb_track )
|
||||
{
|
||||
@@ -189,7 +195,7 @@ public:
|
||||
#ifdef LMMS_SINGERBOT_SUPPORT
|
||||
int patternIndex()
|
||||
{
|
||||
return( m_patternIndex );
|
||||
return m_patternIndex;
|
||||
}
|
||||
|
||||
void setPatternIndex( int _i )
|
||||
@@ -200,19 +206,19 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
class baseDetuning
|
||||
class BaseDetuning
|
||||
{
|
||||
public:
|
||||
baseDetuning( DetuningHelper * _detuning );
|
||||
BaseDetuning( DetuningHelper *detuning );
|
||||
|
||||
void setValue( float _val )
|
||||
void setValue( float val )
|
||||
{
|
||||
m_value = _val;
|
||||
m_value = val;
|
||||
}
|
||||
|
||||
float value() const
|
||||
{
|
||||
return( m_value );
|
||||
return m_value;
|
||||
}
|
||||
|
||||
|
||||
@@ -223,38 +229,40 @@ private:
|
||||
} ;
|
||||
|
||||
InstrumentTrack * m_instrumentTrack; // needed for calling
|
||||
// InstrumentTrack::playNote
|
||||
f_cnt_t m_frames; // total frames to play
|
||||
f_cnt_t m_totalFramesPlayed; // total frame-counter - used for
|
||||
// figuring out whether a whole note
|
||||
// has been played
|
||||
f_cnt_t m_framesBeforeRelease; // number of frames after which note
|
||||
// is released
|
||||
f_cnt_t m_releaseFramesToDo; // total numbers of frames to be
|
||||
// played after release
|
||||
f_cnt_t m_releaseFramesDone; // number of frames done after
|
||||
// release of note
|
||||
NotePlayHandleList m_subNotes; // used for chords and arpeggios
|
||||
volatile bool m_released; // indicates whether note is released
|
||||
bool m_baseNote; // indicates whether note is a
|
||||
// base-note (i.e. no sub-note)
|
||||
bool m_partOfArpeggio; // indicates whether note is part of
|
||||
// an arpeggio (either base-note or
|
||||
// sub-note)
|
||||
bool m_muted; // indicates whether note is muted
|
||||
track * m_bbTrack; // related BB track
|
||||
// InstrumentTrack::playNote
|
||||
f_cnt_t m_frames; // total frames to play
|
||||
f_cnt_t m_totalFramesPlayed; // total frame-counter - used for
|
||||
// figuring out whether a whole note
|
||||
// has been played
|
||||
f_cnt_t m_framesBeforeRelease; // number of frames after which note
|
||||
// is released
|
||||
f_cnt_t m_releaseFramesToDo; // total numbers of frames to be
|
||||
// played after release
|
||||
f_cnt_t m_releaseFramesDone; // number of frames done after
|
||||
// release of note
|
||||
NotePlayHandleList m_subNotes; // used for chords and arpeggios
|
||||
volatile bool m_released; // indicates whether note is released
|
||||
bool m_topNote; // indicates whether note is a
|
||||
// base-note (i.e. no sub-note)
|
||||
bool m_partOfArpeggio; // indicates whether note is part of
|
||||
// an arpeggio (either base-note or
|
||||
// sub-note)
|
||||
bool m_muted; // indicates whether note is muted
|
||||
track * m_bbTrack; // related BB track
|
||||
#ifdef LMMS_SINGERBOT_SUPPORT
|
||||
int m_patternIndex; // position among relevant notes
|
||||
int m_patternIndex; // position among relevant notes
|
||||
#endif
|
||||
|
||||
// tempo reaction
|
||||
bpm_t m_origTempo; // original tempo
|
||||
f_cnt_t m_origFrames; // original m_frames
|
||||
bpm_t m_origTempo; // original tempo
|
||||
f_cnt_t m_origFrames; // original m_frames
|
||||
|
||||
int m_origBaseNote;
|
||||
|
||||
float m_frequency;
|
||||
float m_unpitchedFrequency;
|
||||
|
||||
baseDetuning * m_baseDetuning;
|
||||
BaseDetuning * m_baseDetuning;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user