]> git.donarmstrong.com Git - lilypond.git/blob - lily/midi-cc-announcer.cc
Web-ja: update introduction
[lilypond.git] / lily / midi-cc-announcer.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2016 by Heikki Tauriainen <g034737@welho.com>.
5
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.
10
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.
15
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/>.
18 */
19
20 #include "audio-item.hh"
21 #include "input.hh"
22 #include "international.hh"
23 #include "libc-extension.hh"
24 #include "midi-cc-announcer.hh"
25
26 /*
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
30        the MIDI control.
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
34        control value.
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.
39 */
40 const Midi_control_change_announcer::Control_spec
41 Midi_control_change_announcer::controls_[]
42 =
43 {
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.
50   { 0, 0.0, 0.0, 0, 0 }
51 };
52
53 Midi_control_change_announcer::Midi_control_change_announcer (Input *origin)
54   : origin_ (origin)
55 {
56 }
57
58 Midi_control_change_announcer::~Midi_control_change_announcer ()
59 {
60 }
61
62 void Midi_control_change_announcer::announce_control_changes ()
63 {
64   for (const Control_spec *spec = controls_; spec->context_property_name_;
65        ++spec)
66     {
67       SCM value = get_property_value (spec->context_property_name_);
68       if (!scm_is_number (value))
69         continue;
70       Real val = scm_to_double (value);
71       if (val >= spec->range_min_ && val <= spec->range_max_)
72         {
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
86                                                 ? full_fine_scale
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_,
92                                                  fine_resolution
93                                                  ? (v >> 7) : v));
94           if (fine_resolution)
95             do_announce (new Audio_control_change (spec->lsb_control_number_,
96                                                    v & 0x7F));
97         }
98       else
99         warn (_f ("ignoring out-of-range value change for MIDI property `%s'",
100                   spec->context_property_name_));
101     }
102 }
103
104 void Midi_control_change_announcer::warn (const string &message)
105 {
106   if (origin_)
107     origin_->warning (message);
108   else
109     warning (message);
110 }