editing note volume and hearing clicked on notes is implemented more cleanly, editing note volume only affects selected notes (or all notes if none selected), when "scribbling" note volumes, if there is a chord, it will play all 3 notes, rather than just the first one
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1909 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
@@ -44,6 +44,7 @@ note::note( const midiTime & _length, const midiTime & _pos,
|
||||
m_oldKey( tLimit( _key, 0, NumKeys ) ),
|
||||
m_oldPos( _pos ),
|
||||
m_oldLength( _length ),
|
||||
m_isPlaying( false ),
|
||||
m_key( tLimit( _key, 0, NumKeys ) ),
|
||||
m_volume( tLimit( _volume, MinVolume, MaxVolume ) ),
|
||||
m_panning( tLimit( _panning, PanningLeft, PanningRight ) ),
|
||||
@@ -72,6 +73,7 @@ note::note( const note & _note ) :
|
||||
m_oldKey( _note.m_oldKey ),
|
||||
m_oldPos( _note.m_oldPos ),
|
||||
m_oldLength( _note.m_oldLength ),
|
||||
m_isPlaying( _note.m_isPlaying ),
|
||||
m_key( _note.m_key),
|
||||
m_volume( _note.m_volume ),
|
||||
m_panning( _note.m_panning ),
|
||||
|
||||
@@ -1081,7 +1081,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
|
||||
if( _me->y() > PR_TOP_MARGIN )
|
||||
{
|
||||
bool play_note = ! engine::getSong()->isPlaying();
|
||||
volume vol = DefaultVolume;
|
||||
|
||||
bool edit_note = ( _me->y() > height() -
|
||||
@@ -1169,10 +1168,9 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
m_currentNote = *it;
|
||||
m_action = ActionChangeNoteVolume;
|
||||
key_num = ( *it )->key();
|
||||
}
|
||||
else
|
||||
{
|
||||
play_note = false;
|
||||
|
||||
testPlayNote( *it );
|
||||
|
||||
}
|
||||
}
|
||||
// left button??
|
||||
@@ -1280,17 +1278,12 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
// set resize-cursor
|
||||
QCursor c( Qt::SizeHorCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
play_note = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise move it
|
||||
m_action = ActionMoveNote;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// set move-cursor
|
||||
QCursor c( Qt::SizeAllCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
@@ -1328,6 +1321,9 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
engine::getSongEditor()->update();
|
||||
}
|
||||
}
|
||||
|
||||
// play the note
|
||||
testPlayNote( m_currentNote );
|
||||
}
|
||||
|
||||
|
||||
@@ -1346,7 +1342,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
// erase single note
|
||||
m_mouseDownRight = true;
|
||||
play_note = false;
|
||||
if( it != notes.end() )
|
||||
{
|
||||
if( ( *it )->length() > 0 )
|
||||
@@ -1372,36 +1367,35 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
m_selectedKeys = 1;
|
||||
m_action = ActionSelectNotes;
|
||||
|
||||
play_note = false;
|
||||
|
||||
// call mousemove to fix glitch where selection
|
||||
// appears in wrong spot on mousedown
|
||||
mouseMoveEvent( _me );
|
||||
}
|
||||
else if( _me->button() == Qt::RightButton &&
|
||||
m_editMode == ModeMove )
|
||||
{
|
||||
// when clicking right in select-move, we
|
||||
// switch to draw-mode
|
||||
m_drawButton->setChecked( true );
|
||||
play_note = false;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
// was there an action where should be played the note?
|
||||
if( play_note == true && m_recording == false )
|
||||
{
|
||||
m_lastKey = key_num;
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOn, 0, key_num,
|
||||
vol * 127 / 100 ),
|
||||
midiTime() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pianoRoll::testPlayNote( note * n )
|
||||
{
|
||||
m_lastKey = n->key();
|
||||
|
||||
if(! n->isPlaying() && ! m_recording && ! engine::getSong()->isPlaying() )
|
||||
{
|
||||
n->setIsPlaying( true );
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOn, 0, n->key(),
|
||||
n->getVolume() * 127 / 100 ), midiTime() );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pianoRoll::computeSelectedNotes(bool shift)
|
||||
{
|
||||
if( m_selectStartTick == 0 &&
|
||||
@@ -1512,17 +1506,21 @@ void pianoRoll::mouseReleaseEvent( QMouseEvent * _me )
|
||||
|
||||
if( validPattern() == true )
|
||||
{
|
||||
if( m_action == ActionChangeNoteVolume && m_currentNote != NULL )
|
||||
// turn off all notes that are playing
|
||||
const noteVector & notes = m_pattern->notes();
|
||||
|
||||
noteVector::const_iterator it = notes.begin();
|
||||
while( it != notes.end() )
|
||||
{
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOff, 0,
|
||||
m_currentNote->key(), 0 ), midiTime() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOff, 0, m_lastKey, 0 ),
|
||||
midiTime() );
|
||||
if( ( *it )->isPlaying() )
|
||||
{
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOff, 0, ( *it )->key(), 0 ),
|
||||
midiTime() );
|
||||
( *it )->setIsPlaying( false );
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1566,8 +1564,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me )
|
||||
// (could be the user just moved the cursor one pixel up/down
|
||||
// but is still on the same key)
|
||||
if( key_num != m_lastKey &&
|
||||
m_action != ActionChangeNoteVolume &&
|
||||
m_action != ActionMoveSelection &&
|
||||
( m_action == ActionMoveNote || m_action == ActionMoveSelection ) &&
|
||||
edit_note == false &&
|
||||
_me->buttons() & Qt::LeftButton )
|
||||
{
|
||||
@@ -1606,96 +1603,66 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
// Volume Bars
|
||||
|
||||
// Use nearest-note when changing volume so the bars can
|
||||
// be "scribbled"
|
||||
int pos_ticks = ( x * midiTime::ticksPerTact() ) /
|
||||
m_ppt + m_currentPosition;
|
||||
// Change notes within a certain pixel range of where
|
||||
// the mouse cursor is
|
||||
int pixel_range = 20;
|
||||
|
||||
// convert to ticks so that we can check which notes
|
||||
// are in the range
|
||||
int ticks_start = (x-pixel_range/2) *
|
||||
midiTime::ticksPerTact() / m_ppt + m_currentPosition;
|
||||
int ticks_end = (x+pixel_range/2) *
|
||||
midiTime::ticksPerTact() / m_ppt + m_currentPosition;
|
||||
|
||||
// get note-vector of current pattern
|
||||
const noteVector & notes = m_pattern->notes();
|
||||
|
||||
note * shortNote = NULL;
|
||||
|
||||
// Max "snap length" 1/8 note on either side
|
||||
int shortDistance = DefaultTicksPerTact/8;
|
||||
|
||||
// loop through vector to find nearest note
|
||||
noteVector::const_iterator it = notes.begin();
|
||||
while( it != notes.end() )
|
||||
{
|
||||
int tmp = abs( pos_ticks - (int)( (*it)->pos() ) );
|
||||
|
||||
if( tmp <= shortDistance && (*it)->length().getTicks() > 0 )
|
||||
{
|
||||
shortDistance = tmp;
|
||||
shortNote = *it ;
|
||||
|
||||
}
|
||||
++it;
|
||||
|
||||
}
|
||||
|
||||
// determine what volume to set note to
|
||||
volume vol = tLimit<int>( 2 * ( -_me->y() +
|
||||
height() -
|
||||
PR_BOTTOM_MARGIN ),
|
||||
MinVolume,
|
||||
MaxVolume );
|
||||
|
||||
if( shortNote )
|
||||
|
||||
// loop through vector
|
||||
bool use_selection = isSelection();
|
||||
noteVector::const_iterator it = notes.begin();
|
||||
while( it != notes.end() )
|
||||
{
|
||||
// have short length - now check for volume difference and currentNote
|
||||
it = notes.begin();
|
||||
|
||||
int shortNotePos = shortNote->pos();
|
||||
int shortVolumeDiff = MaxVolume-MinVolume;
|
||||
|
||||
while( it != notes.end() )
|
||||
if( ( *it )->pos().getTicks() >= ticks_start
|
||||
&& ( *it )->pos().getTicks() <= ticks_end
|
||||
&& ( *it )->length().getTicks() > 0
|
||||
&& ( ( *it )->selected() || ! use_selection ) )
|
||||
{
|
||||
if( (*it)->pos() == shortNotePos && (*it)->length().getTicks() > 0 )
|
||||
{
|
||||
if( *it == m_currentNote )
|
||||
{
|
||||
shortNote = m_currentNote;
|
||||
break;
|
||||
}
|
||||
|
||||
int volDiff = abs( vol - (*it)->getVolume() );
|
||||
if( volDiff <= shortVolumeDiff )
|
||||
{
|
||||
shortVolumeDiff = volDiff;
|
||||
shortNote = *it;
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if( shortNote != m_currentNote &&
|
||||
engine::getSong()->isPlaying() == false )
|
||||
{
|
||||
if( m_currentNote != NULL ) {
|
||||
( *it )->setVolume( vol );
|
||||
m_pattern->dataChanged();
|
||||
|
||||
// play the note so that the user can tell how loud it is
|
||||
testPlayNote( *it );
|
||||
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOff, 0,
|
||||
m_currentNote->key(), 0 ), midiTime() );
|
||||
midiEvent(
|
||||
MidiKeyPressure,
|
||||
0,
|
||||
( *it )->key(),
|
||||
vol * 127 / 100 ),
|
||||
midiTime() );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( *it )->isPlaying() )
|
||||
{
|
||||
// mouse not over this note, stop playing it.
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOff, 0,
|
||||
( *it )->key(), 0 ), midiTime() );
|
||||
|
||||
( *it )->setIsPlaying( false );
|
||||
}
|
||||
}
|
||||
|
||||
if( shortNote != NULL ) {
|
||||
m_lastKey = shortNote->key();
|
||||
++it;
|
||||
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiNoteOn, 0,
|
||||
shortNote->key(), shortNote->getVolume() ), midiTime() );
|
||||
}
|
||||
}
|
||||
m_currentNote = shortNote;
|
||||
|
||||
if( m_currentNote != NULL ) {
|
||||
m_currentNote->setVolume( vol );
|
||||
m_pattern->dataChanged();
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( MidiKeyPressure, 0, m_lastKey,
|
||||
vol * 127 / 100 ),
|
||||
midiTime() );
|
||||
}
|
||||
}
|
||||
else if( _me->buttons() == Qt::NoButton && m_editMode == ModeDraw )
|
||||
|
||||
Reference in New Issue
Block a user