>From 5cf487c93861c600c1cb9ea8fdc9345d7967db93 Mon Sep 17 00:00:00 2001 From: Heikki Tauriainen Date: Sat, 19 Oct 2013 09:56:37 +0300 Subject: [PATCH 1/5] Issue 3581: New data types for adjusting MIDI control functions --- lily/audio-item.cc | 16 ++++++++++ lily/include/audio-item.hh | 32 ++++++++++++++++++++ lily/include/lily-proto.hh | 2 ++ lily/include/midi-item.hh | 15 ++++++++++ lily/midi-item.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+) diff --git a/lily/audio-item.cc b/lily/audio-item.cc index b7a5ef2..a41357b 100644 --- a/lily/audio-item.cc +++ b/lily/audio-item.cc @@ -204,3 +204,19 @@ Audio_text::Audio_text (Audio_text::Type type, const string &text_string) type_ = type; } +Audio_control_function_value_change +::Audio_control_function_value_change (Control control, Real value) + : control_ (control), value_ (value) +{ +} + +const Audio_control_function_value_change::Context_property +Audio_control_function_value_change::context_properties_[] = { + // property name, enum constant, lower bound for range, upper bound for range + { "midiBalance", BALANCE, -1.0, 1.0 }, + { "midiPanPosition", PAN_POSITION, -1.0, 1.0 }, + { "midiReverbLevel", REVERB_LEVEL, 0.0, 1.0 }, + { "midiChorusLevel", CHORUS_LEVEL, 0.0, 1.0 }, + // extra element to signify the end of the mapping, must be kept last + { 0, NUM_CONTROLS, 0.0, 0.0 } +}; diff --git a/lily/include/audio-item.hh b/lily/include/audio-item.hh index 544dd83..43ed2e0 100644 --- a/lily/include/audio-item.hh +++ b/lily/include/audio-item.hh @@ -137,6 +137,38 @@ public: int one_beat_; }; +class Audio_control_function_value_change : public Audio_item +{ +public: + // Supported control functions. + enum Control + { + BALANCE = 0, PAN_POSITION, REVERB_LEVEL, CHORUS_LEVEL, + // pseudo value for representing the size of the enum; must be kept last + NUM_CONTROLS + }; + + Audio_control_function_value_change (Control control, Real value); + + // Information about a context property corresponding to a control function + // (name, the corresponding enumeration value, and the allowed range for the + // value of the context property). + struct Context_property + { + const char *name_; + Control control_; + Real range_min_; + Real range_max_; + }; + + // Mapping from supported control functions to the corresponding context + // properties. + static const Context_property context_properties_[]; + + Control control_; + Real value_; +}; + int moment_to_ticks (Moment); Real moment_to_real (Moment); Moment remap_grace_duration (Moment); diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index 53e863c..80240d5 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -24,6 +24,7 @@ class All_font_metrics; class Audio_column; +class Audio_control_function_value_change; class Audio_dynamic; class Audio_element; class Audio_instrument; @@ -104,6 +105,7 @@ class Lyric_performer; class Lyric_phrasing_engraver; class Mensural_ligature_engraver; class Midi_chunk; +class Midi_control_function_value_change; class Midi_duration; class Midi_dynamic; class Midi_event; diff --git a/lily/include/midi-item.hh b/lily/include/midi-item.hh index c5a9cc9..492e2e9 100644 --- a/lily/include/midi-item.hh +++ b/lily/include/midi-item.hh @@ -46,11 +46,26 @@ public: class Midi_channel_item : public Midi_item { public: + virtual ~Midi_channel_item (); int channel_; DECLARE_CLASSNAME (Midi_channel_item); Midi_channel_item (Audio_item *ai); }; +/** + Midi control function value changes. +*/ +class Midi_control_function_value_change : public Midi_channel_item +{ +public: + DECLARE_CLASSNAME (Midi_control_function_value_change); + Midi_control_function_value_change (Audio_control_function_value_change *ai); + virtual ~Midi_control_function_value_change (); + virtual string to_string () const; + Audio_control_function_value_change::Control control_; + Real value_; +}; + class Midi_duration : public Midi_item { public: diff --git a/lily/midi-item.cc b/lily/midi-item.cc index 0d0edbb..c17c369 100644 --- a/lily/midi-item.cc +++ b/lily/midi-item.cc @@ -50,6 +50,9 @@ Midi_item::get_midi (Audio_item *a) return new Midi_time_signature (i); else if (Audio_text *i = dynamic_cast (a)) return new Midi_text (i); + else if (Audio_control_function_value_change *i + = dynamic_cast (a)) + return new Midi_control_function_value_change (i); else assert (0); @@ -102,10 +105,24 @@ Midi_channel_item::Midi_channel_item (Audio_item *ai) { } +Midi_control_function_value_change +::Midi_control_function_value_change (Audio_control_function_value_change *ai) + : Midi_channel_item (ai), control_ (ai->control_), value_ (ai->value_) +{ +} + Midi_item::~Midi_item () { } +Midi_channel_item::~Midi_channel_item () +{ +} + +Midi_control_function_value_change::~Midi_control_function_value_change () +{ +} + string int2midi_varint_string (int i) { @@ -342,6 +359,62 @@ Midi_text::to_string () const return str; } +string +Midi_control_function_value_change::to_string () const +{ + // MIDI control function information. A MIDI control function may have one + // or two assigned control numbers depending on whether it supports coarse + // (7-bit) or fine (14-bit) resolution. If the control function supports + // fine resolution, the first (respectively, second) member of the structure + // represents the control number for setting the most (least) significant 7 + // bits of the control function's value. + struct Control_function + { + int msb_control_number_; + int lsb_control_number_; + }; + + // Mapping from supported control functions (enumeration values defined in + // Audio_controller_value_change::Control) to the corresponding MIDI control + // numbers. + static const Control_function control_functions[] = + { + // When adding support for new control functions, please note the + // following: + // - The order of the control number definitions should be kept + // consistent with the order of the enumeration values defined in + // Audio_control_function_value_change::Control. + // - If the control function has only coarse resolution, the function's + // control number should be stored in the MSB member of the array + // element, and the LSB member should be set to a negative value. + + { 8, 40 }, // balance + { 10, 42 }, // pan position + { 91, -1 }, // reverb level (only coarse resolution available) + { 93, -1 } // chorus level (only coarse resolution available) + }; + + string str; + const Control_function *control_function = &control_functions[control_]; + static const Real full_fine_scale = 0x3FFF; + static const Real full_coarse_scale = 0x7F; + bool fine_resolution = (control_function->lsb_control_number_ >= 0); + int value = lround (value_ * (fine_resolution ? + full_fine_scale : full_coarse_scale)); + Byte status_byte = (char) (0xB0 + channel_); + str += ::to_string ((char)status_byte); + str += ::to_string ((char)(control_function->msb_control_number_)); + str += ::to_string ((char)(fine_resolution ? (value >> 7) : value)); + if (fine_resolution) + { + str += ::to_string ((char)0x00); + str += ::to_string ((char)status_byte); + str += ::to_string ((char)(control_function->lsb_control_number_)); + str += ::to_string ((char)(value & 0x7F)); + } + return str; +} + char const * Midi_item::name () const { -- 1.8.4.rc3