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.
(cherry picked from commit a9717c0cc3)
This commit is contained in:
Tobias Doerffel
2010-12-31 13:13:45 +01:00
parent 65c073ec63
commit 7b68713008
6 changed files with 90 additions and 74 deletions

View File

@@ -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,17 +135,17 @@ 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;
}
Piano * pianoModel()
Piano *pianoModel()
{
return &m_piano;
}

View File

@@ -56,8 +56,9 @@ public:
virtual ~notePlayHandle();
virtual void setVolume( const volume_t _volume = DefaultVolume );
int getMidiVelocity() const;
int midiVelocity() const;
int midiKey() const;
const float & frequency() const
{
@@ -84,7 +85,7 @@ public:
inline fpp_t framesLeftForCurrentPeriod() const
{
return (fpp_t) qMin<f_cnt_t>( framesLeft(),
engine::getMixer()->framesPerPeriod() );
engine::getMixer()->framesPerPeriod() );
}
@@ -130,16 +131,21 @@ public:
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
@@ -200,14 +206,14 @@ 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
@@ -224,38 +230,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;
} ;