2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2016 by Heikki Tauriainen <g034737@welho.com>.
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "audio-item.hh"
22 #include "international.hh"
23 #include "libc-extension.hh"
24 #include "midi-cc-announcer.hh"
27 Context properties for setting MIDI controls. Each MIDI control
28 specification has the following components:
29 1. The name of the LilyPond context property used to change the value of
31 2. The lower bound for the numeric range of the LilyPond context property.
32 3. The upper bound for the numeric range of the LilyPond context property.
33 4. The MIDI control number for setting the most significant 7 bits of the
35 5. The MIDI control number for setting the least significant 7 bits of the
36 control value, if the control supports 14-bit ("fine") resolution. If
37 the control supports only 7-bit ("coarse") resolution, the LSB control
38 number should be negative.
40 const Midi_control_change_announcer::Control_spec
41 Midi_control_change_announcer::controls_[]
44 { "midiBalance", -1.0, 1.0, 8, 40 },
45 { "midiPanPosition", -1.0, 1.0, 10, 42 },
46 { "midiExpression", 0.0, 1.0, 11, 43 },
47 { "midiReverbLevel", 0.0, 1.0, 91, -1 },
48 { "midiChorusLevel", 0.0, 1.0, 93, -1 },
49 // This element should be kept last in the array.
53 Midi_control_change_announcer::Midi_control_change_announcer (Input *origin)
58 Midi_control_change_announcer::~Midi_control_change_announcer ()
62 void Midi_control_change_announcer::announce_control_changes ()
64 for (const Control_spec *spec = controls_; spec->context_property_name_;
67 SCM value = get_property_value (spec->context_property_name_);
68 if (!scm_is_number (value))
70 Real val = scm_to_double (value);
71 if (val >= spec->range_min_ && val <= spec->range_max_)
73 // Normalize the value to the 0.0 to 1.0 range.
74 val = ((val - spec->range_min_)
75 / (spec->range_max_ - spec->range_min_));
76 // Transform the normalized context property value into a 14-bit or
77 // a 7-bit (non-negative) integer depending on the MIDI control's
78 // resolution. For directional value changes, #CENTER will
79 // correspond to 0.5 exactly, and my_round rounds upwards when in
80 // case of doubt. That means that center position will round to
81 // 0x40 or 0x2000 by a hair's breadth.
82 const Real full_fine_scale = 0x3FFF;
83 const Real full_coarse_scale = 0x7F;
84 const bool fine_resolution = (spec->lsb_control_number_ >= 0);
85 const int v = (int) (my_round (val * (fine_resolution
87 : full_coarse_scale)));
88 // Announce a control change for the most significant 7 bits of the
89 // control value (and, if the control supports fine resolution, for
90 // the least significant 7 bits as well).
91 do_announce (new Audio_control_change (spec->msb_control_number_,
95 do_announce (new Audio_control_change (spec->lsb_control_number_,
99 warn (_f ("ignoring out-of-range value change for MIDI property `%s'",
100 spec->context_property_name_));
104 void Midi_control_change_announcer::warn (const string &message)
107 origin_->warning (message);