Michael Welsh Duggan <address@hidden> writes:
Mats Bengtsson <address@hidden> writes:
Michael Welsh Duggan wrote:
In the following fragment:
<< e1 \\ { c4 d e f } >>
When played by a pianist (which I should emphasize, I am not), the
e4
should interrupt the e1 so that it sounds like:
<< e2 \\ { c4 d e f } >>
What the midi output currently does is this:
<< e1 \\ { c4 d s f } >>
I would like to change Midi_walker::do_start_note to do the former
(fairly easy). The question is, should there be an option to do the
latter?
Probably! Imagine, for example, that you are typesetting an
orchestral piece and this particular music is played by two
flutes, for example. It's common to typeset two flute parts on
a common stave in a printed score and because of the limitation to
16 channels in MIDI, you will typically keep them in the same
stave also in the LilyPond \score{} for the MIDI output (each
Staff context is translated into a MIDI channel, by default).
How about a patch like the following? (Untested. I can't test until
I get home.) There are some things that could be moved around, but
this should provide a general idea.
Now that I have had a chance to go home and do some testing, I have
the following patch. Some things could probably be cleaned up, and I
welcome comments and criticisms. Here is an example score which
demonstrates the change:
\score{
\notes << e'1 \\ { c'4 c' e' f' } >>
\midi {
\context {
\StaffContext
midiSimultaneousInterrupt = ##t
}
}
}
And here is the patch:
Index: lily/audio-staff.cc
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/audio-staff.cc,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 audio-staff.cc
--- lily/audio-staff.cc 5 Feb 2004 14:55:17 -0000 1.19
+++ lily/audio-staff.cc 20 Apr 2004 03:46:51 -0000
@@ -12,6 +12,17 @@
#include "midi-stream.hh"
#include "midi-walker.hh"
+Audio_staff::Audio_staff (const Performer *performer)
+{
+ performer_ = performer;
+}
+
+SCM
+Audio_staff::internal_get_property (SCM sym) const
+{
+ return performer_->internal_get_property (sym);
+}
+
void
Audio_staff::add_audio_item (Audio_item* l)
{
Index: lily/midi-item.cc
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/midi-item.cc,v
retrieving revision 1.75
diff -u -p -u -p -r1.75 midi-item.cc
--- lily/midi-item.cc 7 Apr 2004 13:40:30 -0000 1.75
+++ lily/midi-item.cc 20 Apr 2004 03:46:52 -0000
@@ -239,6 +239,12 @@ Midi_note::get_length () const
return m;
}
+void
+Midi_note::set_length (Moment m)
+{
+ audio_->length_mom_ = m;
+}
+
int
Midi_note::get_fine_tuning () const
{
Index: lily/midi-walker.cc
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/midi-walker.cc,v
retrieving revision 1.43
diff -u -p -u -p -r1.43 midi-walker.cc
--- lily/midi-walker.cc 8 Mar 2004 16:17:40 -0000 1.43
+++ lily/midi-walker.cc 20 Apr 2004 03:46:52 -0000
@@ -38,6 +38,7 @@ Midi_walker::Midi_walker (Audio_staff* a
track_ = track;
index_= 0;
items_ = &audio_staff->audio_items_;
+ staff_ = audio_staff;
last_mom_ = 0;
}
@@ -60,13 +61,44 @@ Midi_walker::do_start_note (Midi_note* n
bool play_start = true;
for (int i=0; i < stop_note_queue.size (); i++)
{
- /* if this pith already in queue */
+ /* if this pitch already in queue */
if (stop_note_queue[i].val->get_pitch () == note->get_pitch ())
{
- if (stop_note_queue[i].key < stop_mom)
+ /* If the two notes do not start simultanously, but
+ intersect, and midiSimultaneousInterrupt is set, then the
+ later note should interrupt the first. */
+ if ((note->audio_->audio_column_->at_mom ()
+ != stop_note_queue[i].val->audio_->audio_column_->at_mom ())
+ && ly_scm2bool (staff_->internal_get_property
+ (ly_symbol2scm ("midiSimultaneousInterrupt"))))
+ {
+ /* Simultanous notes are handled by interruption */
+ if (stop_note_queue[i].key > ptr->audio_column_->at_mom ())
+ {
+ /* Change length of original note */
+ Moment new_length = stop_note_queue[i].val->get_length () -
+ (stop_note_queue[i].key -
+ ptr->audio_column_->at_mom ());
+ if (new_length == 0)
+ {
+ /* simultaneous notes.
+ don't play the start note */
+ delete note;
+ note = 0;
+ break;
+ }
+
+ stop_note_queue[i].val->set_length (new_length);
+ /* stop here instead */
+ output_event (ptr->audio_column_->at_mom (),
+ stop_note_queue[i].val);
+ break;
+ }
+ }
+ else if (stop_note_queue[i].key < stop_mom)
{
/* let stopnote in queue be ignored,
- new stop note wins */
+ new stop note wins */
stop_note_queue[i].ignore_b_ = true;
/* don't replay start note, */
play_start = false;
Index: lily/staff-performer.cc
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/staff-performer.cc,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 staff-performer.cc
--- lily/staff-performer.cc 12 Apr 2004 14:52:21 -0000 1.61
+++ lily/staff-performer.cc 20 Apr 2004 03:46:52 -0000
@@ -62,7 +62,7 @@ Staff_performer::~Staff_performer ()
void
Staff_performer::initialize ()
{
- audio_staff_ = new Audio_staff;
+ audio_staff_ = new Audio_staff (this);
announce_element (Audio_element_info (audio_staff_, 0));
name_ = new Audio_text (Audio_text::TRACK_NAME, context ()->id_string ());
Index: lily/include/audio-staff.hh
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/include/audio-staff.hh,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 audio-staff.hh
--- lily/include/audio-staff.hh 25 Mar 2004 01:45:15 -0000 1.18
+++ lily/include/audio-staff.hh 20 Apr 2004 03:46:52 -0000
@@ -9,15 +9,22 @@
#include "parray.hh"
#include "lily-proto.hh"
+#include "lily-guile.hh"
#include "audio-element.hh"
+#include "performer.hh"
struct Audio_staff : public Audio_element
{
+ Audio_staff (const Performer *performer);
+
+ SCM internal_get_property (SCM sym) const;
+
void add_audio_item (Audio_item* l);
void output (Midi_stream& midi_stream_r, int track_i);
Link_array<Audio_item> audio_items_;
int channel_;
+ const Performer *performer_;
};
#endif // AUDIO_STAFF_HH
Index: lily/include/midi-item.hh
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/include/midi-item.hh,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 midi-item.hh
--- lily/include/midi-item.hh 5 Feb 2004 14:55:37 -0000 1.34
+++ lily/include/midi-item.hh 20 Apr 2004 03:46:52 -0000
@@ -122,6 +122,7 @@ public:
Midi_note (Audio_note*);
Moment get_length () const;
+ void set_length (Moment m);
int get_pitch () const;
int get_fine_tuning () const;
virtual String to_string () const;
Index: ly/performer-init.ly
===================================================================
RCS file: /cvsroot/lilypond/lilypond/ly/performer-init.ly,v
retrieving revision 1.41
diff -u -p -u -p -r1.41 performer-init.ly
--- ly/performer-init.ly 11 Apr 2004 15:54:45 -0000 1.41
+++ ly/performer-init.ly 20 Apr 2004 03:46:52 -0000
@@ -109,6 +109,7 @@
dynamicAbsoluteVolumeFunction = #default-dynamic-absolute-volume
instrumentEqualizer = #default-instrument-equalizer
drumPitchTable = #(alist->hash-table midiDrumPitches)
+ midiSimultaneousInterrupt = ##f
}