]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 3581: New data types for adjusting MIDI control functions
authorHeikki Tauriainen <g034737@welho.com>
Sat, 19 Oct 2013 06:56:37 +0000 (09:56 +0300)
committerDavid Kastrup <dak@gnu.org>
Sat, 19 Oct 2013 09:19:06 +0000 (11:19 +0200)
Signed-off-by: David Kastrup <dak@gnu.org>
lily/audio-item.cc
lily/include/audio-item.hh
lily/include/lily-proto.hh
lily/include/midi-item.hh
lily/midi-item.cc

index b7a5ef21112c5decf3189fb48238dd85399a3ad7..a41357b28f296239350e38e770af2c01b7df7d21 100644 (file)
@@ -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 }
+};
index 544dd8378d74c743d6db59797e42a09ac9b7834a..43ed2e05a91e6fd8ccb80b8ff351354be927fb02 100644 (file)
@@ -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);
index 53e863c2a9e9f9d32a3a8137dad8631c28448450..80240d5923830edf35de5e3250161ffea4d1bbd0 100644 (file)
@@ -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;
index c5a9cc9fddce90dcee66b6fe84cd95f1acc8afda..492e2e9fc83eb4a831c7e6cba230687e34d44650 100644 (file)
@@ -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:
index 0d0edbb4c7fc904a8f4526ecc6389799587e558b..c17c369dcaf5d42df096f0691be196b4e5413e66 100644 (file)
@@ -50,6 +50,9 @@ Midi_item::get_midi (Audio_item *a)
     return new Midi_time_signature (i);
   else if (Audio_text *i = dynamic_cast<Audio_text *> (a))
     return new Midi_text (i);
+  else if (Audio_control_function_value_change *i
+           = dynamic_cast<Audio_control_function_value_change *> (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
 {