This fixes a long standing weirdness in MIDI output, with voices being
all merged into one channel with channel number equalling track
number.
With voices mapped to channels, midi2ly can neatly recreate voices
without needing to do tricky guessing.
}
Audio_item::Audio_item ()
}
Audio_item::Audio_item ()
+ : audio_column_ (0)
+ , channel_ (0)
}
Audio_note::Audio_note (Pitch p, Moment m, bool tie_event, Pitch transposing)
}
Audio_note::Audio_note (Pitch p, Moment m, bool tie_event, Pitch transposing)
#include "midi-walker.hh"
void
#include "midi-walker.hh"
void
-Audio_staff::add_audio_item (Audio_item *l)
+Audio_staff::add_audio_item (Audio_item *ai)
- audio_items_.push_back (l);
+ audio_items_.push_back (ai);
}
Audio_staff::Audio_staff ()
}
Audio_staff::Audio_staff ()
-Audio_staff::output (Midi_stream &midi_stream, int channel)
+Audio_staff::output (Midi_stream &midi_stream, int track)
- midi_track.number_ = channel;
+ midi_track.number_ = track;
- Midi_walker i (this, &midi_track, channel);
+ Midi_walker i (this, &midi_track);
for (; i.ok (); i++)
i.process ();
for (; i.ok (); i++)
i.process ();
class Audio_item : public Audio_element
{
public:
class Audio_item : public Audio_element
{
public:
Audio_column *audio_column_;
Audio_column *audio_column_;
+ int channel_;
+
+ Audio_item ();
Audio_column *get_column () const;
virtual void render ();
Audio_column *get_column () const;
virtual void render ();
struct Audio_staff : public Audio_element
{
struct Audio_staff : public Audio_element
{
- void add_audio_item (Audio_item *l);
+ void add_audio_item (Audio_item *ai);
void output (Midi_stream &midi_stream_r, int track);
Audio_staff ();
void output (Midi_stream &midi_stream_r, int track);
Audio_staff ();
vector<Audio_item*> audio_items_;
vector<Audio_item*> audio_items_;
};
#endif // AUDIO_STAFF_HH
};
#endif // AUDIO_STAFF_HH
class Midi_item
{
public:
class Midi_item
{
public:
- DECLARE_CLASSNAME(Midi_item);
+ DECLARE_CLASSNAME (Midi_item);
Midi_item ();
virtual ~Midi_item ();
virtual char const *name () const;
Midi_item ();
virtual ~Midi_item ();
virtual char const *name () const;
- DECLARE_CLASSNAME(Midi_channel_item);
- Midi_channel_item ();
+ DECLARE_CLASSNAME (Midi_channel_item);
+ Midi_channel_item (Audio_item *ai);
};
class Midi_duration : public Midi_item
};
class Midi_duration : public Midi_item
public:
Midi_instrument (Audio_instrument *);
public:
Midi_instrument (Audio_instrument *);
- DECLARE_CLASSNAME(Midi_instrument);
+ DECLARE_CLASSNAME (Midi_instrument);
virtual string to_string () const;
Audio_instrument *audio_;
virtual string to_string () const;
Audio_instrument *audio_;
{
public:
Midi_key (Audio_key *);
{
public:
Midi_key (Audio_key *);
- DECLARE_CLASSNAME(Midi_key);
+ DECLARE_CLASSNAME (Midi_key);
virtual string to_string () const;
virtual string to_string () const;
{
public:
Midi_time_signature (Audio_time_signature *);
{
public:
Midi_time_signature (Audio_time_signature *);
- DECLARE_CLASSNAME(Midi_time_signature);
+ DECLARE_CLASSNAME (Midi_time_signature);
virtual string to_string () const;
virtual string to_string () const;
{
public:
Midi_note (Audio_note *);
{
public:
Midi_note (Audio_note *);
- DECLARE_CLASSNAME(Midi_note);
+ DECLARE_CLASSNAME (Midi_note);
int get_semitone_pitch () const;
int get_fine_tuning () const;
int get_semitone_pitch () const;
int get_fine_tuning () const;
{
public:
Midi_note_off (Midi_note *);
{
public:
Midi_note_off (Midi_note *);
- DECLARE_CLASSNAME(Midi_note_off);
+ DECLARE_CLASSNAME (Midi_note_off);
virtual string to_string () const;
virtual string to_string () const;
TEXT = 1, COPYRIGHT, TRACK_NAME, INSTRUMENT_NAME, LYRIC,
MARKER, CUE_POINT
};
TEXT = 1, COPYRIGHT, TRACK_NAME, INSTRUMENT_NAME, LYRIC,
MARKER, CUE_POINT
};
- DECLARE_CLASSNAME(Midi_text);
+ DECLARE_CLASSNAME (Midi_text);
Midi_text (Audio_text *);
Midi_text (Audio_text *);
{
public:
Midi_dynamic (Audio_dynamic *);
{
public:
Midi_dynamic (Audio_dynamic *);
- DECLARE_CLASSNAME(Midi_dynamic);
+ DECLARE_CLASSNAME (Midi_dynamic);
virtual string to_string () const;
virtual string to_string () const;
{
public:
Midi_piano_pedal (Audio_piano_pedal *);
{
public:
Midi_piano_pedal (Audio_piano_pedal *);
- DECLARE_CLASSNAME(Midi_piano_pedal);
+ DECLARE_CLASSNAME (Midi_piano_pedal);
virtual string to_string () const;
virtual string to_string () const;
{
public:
Midi_tempo (Audio_tempo *);
{
public:
Midi_tempo (Audio_tempo *);
- DECLARE_CLASSNAME(Midi_tempo);
+ DECLARE_CLASSNAME (Midi_tempo);
virtual string to_string () const;
Audio_tempo *audio_;
};
virtual string to_string () const;
Audio_tempo *audio_;
};
class Midi_walker
{
public:
class Midi_walker
{
public:
- Midi_walker (Audio_staff *audio_staff, Midi_track *midi_track,
- int channel);
+ Midi_walker (Audio_staff *audio_staff, Midi_track *midi_track);
~Midi_walker ();
void process ();
void operator ++ (int);
bool ok () const;
void finalize ();
~Midi_walker ();
void process ();
void operator ++ (int);
bool ok () const;
void finalize ();
private:
void do_start_note (Midi_note *note);
void do_stop_notes (int);
void output_event (int, Midi_item *l);
Midi_item *get_midi (Audio_item*);
private:
void do_start_note (Midi_note *note);
void do_stop_notes (int);
void output_event (int, Midi_item *l);
Midi_item *get_midi (Audio_item*);
Midi_track *track_;
Audio_staff *staff_;
Midi_track *track_;
Audio_staff *staff_;
vsize index_;
vector<Audio_item*> items_;
PQueue<Midi_note_event> stop_note_queue;
vsize index_;
vector<Audio_item*> items_;
PQueue<Midi_note_event> stop_note_queue;
}
Midi_instrument::Midi_instrument (Audio_instrument *a)
}
Midi_instrument::Midi_instrument (Audio_instrument *a)
+ : Midi_channel_item (a)
+ , audio_ (a)
audio_->str_ = String_convert::to_lower (audio_->str_);
}
audio_->str_ = String_convert::to_lower (audio_->str_);
}
-Midi_channel_item::Midi_channel_item ()
+Midi_channel_item::Midi_channel_item (Audio_item *ai)
+ : channel_ (ai->channel_)
}
Midi_item::~Midi_item ()
}
Midi_item::~Midi_item ()
}
Midi_key::Midi_key (Audio_key *a)
}
Midi_key::Midi_key (Audio_key *a)
}
Midi_time_signature::Midi_time_signature (Audio_time_signature *a)
}
Midi_time_signature::Midi_time_signature (Audio_time_signature *a)
+ : audio_ (a)
+ , clocks_per_1_ (18)
- audio_ = a;
- clocks_per_1_ = 18;
}
Midi_note::Midi_note (Audio_note *a)
}
Midi_note::Midi_note (Audio_note *a)
+ : Midi_channel_item (a)
+ , audio_ (a)
+ , dynamic_byte_ (0x5a)
- audio_ = a;
- dynamic_byte_ = 0x5a;
int
Midi_note::get_fine_tuning () const
{
int
Midi_note::get_fine_tuning () const
{
}
Midi_dynamic::Midi_dynamic (Audio_dynamic *a)
}
Midi_dynamic::Midi_dynamic (Audio_dynamic *a)
+ : Midi_channel_item (a)
+ , audio_ (a)
}
Midi_piano_pedal::Midi_piano_pedal (Audio_piano_pedal *a)
}
Midi_piano_pedal::Midi_piano_pedal (Audio_piano_pedal *a)
+ : Midi_channel_item (a)
+ , audio_ (a)
}
Midi_tempo::Midi_tempo (Audio_tempo *a)
}
Midi_tempo::Midi_tempo (Audio_tempo *a)
}
Midi_text::Midi_text (Audio_text *a)
}
Midi_text::Midi_text (Audio_text *a)
return a->get_column ()->when_ < b->get_column ()->when_;
}
return a->get_column ()->when_ < b->get_column ()->when_;
}
-Midi_walker::Midi_walker (Audio_staff *audio_staff, Midi_track *track,
- int channel)
+Midi_walker::Midi_walker (Audio_staff *audio_staff, Midi_track *track)
track_ = track;
index_ = 0;
items_ = audio_staff->audio_items_;
vector_sort (items_, audio_item_less);
last_tick_ = 0;
track_ = track;
index_ = 0;
items_ = audio_staff->audio_items_;
vector_sort (items_, audio_item_less);
last_tick_ = 0;
+ percussion_ = audio_staff->percussion_;
}
Midi_walker::~Midi_walker ()
}
Midi_walker::~Midi_walker ()
if (Midi_item *midi = get_midi (audio))
{
if (Midi_item *midi = get_midi (audio))
{
- if (Midi_channel_item *mci = dynamic_cast<Midi_channel_item*> (midi))
- mci->channel_ = channel_;
-
if (Midi_note *note = dynamic_cast<Midi_note *> (midi))
{
if (note->audio_->length_mom_.to_bool ())
if (Midi_note *note = dynamic_cast<Midi_note *> (midi))
{
if (note->audio_->length_mom_.to_bool ())
Midi_walker::get_midi (Audio_item *i)
{
Midi_item *mi = Midi_item::get_midi (i);
Midi_walker::get_midi (Audio_item *i)
{
Midi_item *mi = Midi_item::get_midi (i);
+
+ if (percussion_)
+ if (Midi_channel_item *mci = dynamic_cast<Midi_channel_item*> (mi))
+ mci->channel_ = 9;
+
midi_events_.push_back (mi);
return mi;
}
midi_events_.push_back (mi);
return mi;
}
if (be_verbose_global)
progress_indication (_ ("Track...") + " ");
if (be_verbose_global)
progress_indication (_ ("Track...") + " ");
for (vsize i = 0; i < audio_staffs_.size (); i++)
{
Audio_staff *s = audio_staffs_[i];
if (be_verbose_global)
progress_indication ("[" + to_string (i));
for (vsize i = 0; i < audio_staffs_.size (); i++)
{
Audio_staff *s = audio_staffs_[i];
if (be_verbose_global)
progress_indication ("[" + to_string (i));
-
- int midi_channel = s->channel_;
-
- if (midi_channel < 0)
- {
- midi_channel = channel;
- channel ++;
- /*
- MIDI players tend to ignore instrument settings on
- channel 10, the percussion channel.
- */
- if (channel % 16 == 9)
- channel ++;
- }
-
- /*
- Huh? Why does each staff also have a separate channel? We
- should map channels to voices, not staves. --hwn.
- */
- if (midi_channel > 15)
- {
- warning (_ ("MIDI channel wrapped around"));
- warning (_ ("remapping modulo 16"));
-
- midi_channel = midi_channel % 16;
- }
-
- s->output (midi_stream, midi_channel);
+ s->output (midi_stream, i);
if (be_verbose_global)
progress_indication ("]");
}
}
if (be_verbose_global)
progress_indication ("]");
}
}
void
Performance::add_element (Audio_element *p)
{
void
Performance::add_element (Audio_element *p)
{
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
#include "warn.hh"
#include "audio-column.hh"
#include "audio-item.hh"
#include "warn.hh"
#include "audio-column.hh"
#include "audio-item.hh"
Audio_text *instrument_name_;
Audio_text *name_;
Audio_tempo *tempo_;
Audio_text *instrument_name_;
Audio_text *name_;
Audio_tempo *tempo_;
+ map<string, int> channel_map_;
};
#include "translator.icc"
};
#include "translator.icc"
Staff_performer::stop_translation_timestep ()
{
SCM proc = ly_lily_module_constant ("percussion?");
Staff_performer::stop_translation_timestep ()
{
SCM proc = ly_lily_module_constant ("percussion?");
SCM drums = scm_call_1 (proc, ly_symbol2scm (instrument_string_.c_str ()));
SCM drums = scm_call_1 (proc, ly_symbol2scm (instrument_string_.c_str ()));
- audio_staff_->channel_ = (drums == SCM_BOOL_T ? 9 : -1);
+ audio_staff_->percussion_ = (drums == SCM_BOOL_T);
+
instrument_name_ = 0;
instrument_ = 0;
}
instrument_name_ = 0;
instrument_ = 0;
}
Staff_performer::acknowledge_audio_element (Audio_element_info inf)
{
if (Audio_item *ai = dynamic_cast<Audio_item *> (inf.elem_))
Staff_performer::acknowledge_audio_element (Audio_element_info inf)
{
if (Audio_item *ai = dynamic_cast<Audio_item *> (inf.elem_))
- audio_staff_->add_audio_item (ai);
+ {
+ /* map each context (voice) to its own channel */
+ Context *c = inf.origin_contexts (this)[0];
+ string id = c->id_string ();
+ int channel = channel_map_.size ();
+ /* MIDI players tend to ignore instrument settings on channel
+ 10, the percussion channel. */
+ if (channel % 16 == 9)
+ channel_map_[""] = channel++;
+
+ map<string, int>::const_iterator i = channel_map_.find (id);
+ if (i != channel_map_.end ())
+ channel = i->second;
+ else
+ channel_map_[id] = channel;
+
+ audio_staff_->add_audio_item (ai);
+ }