2 Copyright (C) 2014 Paul Davis
3 Author: David Robillard
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2 of the License, or (at your option)
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <boost/algorithm/string.hpp>
22 #include "pbd/control_math.h"
24 #include "ardour/amp.h"
25 #include "ardour/dB.h"
26 #include "ardour/parameter_descriptor.h"
27 #include "ardour/rc_configuration.h"
28 #include "ardour/types.h"
29 #include "ardour/utils.h"
35 ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
36 : Evoral::ParameterDescriptor()
38 , datatype(Variant::NOTHING)
39 , type((AutomationType)parameter.type())
44 , integer_step(parameter.type() >= MidiCCAutomation &&
45 parameter.type() <= MidiChannelPressureAutomation)
53 switch((AutomationType)parameter.type()) {
55 upper = Config->get_max_gain();
59 upper = Config->get_max_gain ();
71 case PanAzimuthAutomation:
72 normal = 0.5f; // there really is no _normal but this works for stereo, sort of
75 case PanWidthAutomation:
80 case RecEnableAutomation:
81 case RecSafeAutomation:
86 case PluginAutomation:
87 case FadeInAutomation:
88 case FadeOutAutomation:
89 case EnvelopeAutomation:
99 case MidiCCAutomation:
100 case MidiPgmChangeAutomation:
101 case MidiChannelPressureAutomation:
102 case MidiNotePressureAutomation:
107 case MidiPitchBenderAutomation:
112 case PhaseAutomation:
115 case MonitoringAutomation:
119 upper = MonitorDisk; /* XXX bump when we add MonitorCue */
121 case SoloIsolateAutomation:
124 case SoloSafeAutomation:
134 ParameterDescriptor::ParameterDescriptor()
135 : Evoral::ParameterDescriptor()
137 , datatype(Variant::NOTHING)
138 , type(NullAutomation)
143 , integer_step(false)
144 , sr_dependent(false)
151 ParameterDescriptor::update_steps()
153 if (unit == ParameterDescriptor::MIDI_NOTE) {
154 step = smallstep = 1; // semitone
155 largestep = 12; // octave
156 } else if (type == GainAutomation || type == TrimAutomation) {
157 /* dB_coeff_step gives a step normalized for [0, max_gain]. This is
158 like "slider position", so we convert from "slider position" to gain
159 to have the correct unit here. */
160 largestep = position_to_gain (dB_coeff_step(upper));
161 step = position_to_gain (largestep / 10.0);
164 /* note that LV2Plugin::get_parameter_descriptor ()
165 * overrides this is lv2:rangeStep is set for a port.
167 const float delta = upper - lower;
169 /* 30 happens to be the total number of steps for a fader with default
170 max gain of 2.0 (6 dB), so we use 30 here too for consistency. */
171 step = smallstep = (delta / 300.0f);
172 largestep = (delta / 30.0f);
175 /* Steps are linear, but we map them with pow like values (in
176 internal_to_interface). Thus, they are applied exponentially,
177 which means too few steps. So, divide to get roughly the
178 desired number of steps (30). This is not mathematically
179 precise but seems to be about right for the controls I tried.
180 If you're reading this, you've probably found a case where that
181 isn't true, and somebody needs to sit down with a piece of paper
182 and actually do the math. */
183 smallstep = smallstep / logf(30.0f);
184 step = step / logf(30.0f);
185 largestep = largestep / logf(30.0f);
186 } else if (integer_step) {
188 step = std::max(1.f, rintf (step));
189 largestep = std::max(1.f, rintf (largestep));
195 ParameterDescriptor::midi_note_name (const uint8_t b, bool translate)
199 snprintf(buf, sizeof(buf), "%d", b);
203 static const char* en_notes[] = {
204 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
207 static const char* notes[] = {
222 /* MIDI note 0 is in octave -1 (in scientific pitch notation) */
223 const int octave = b / 12 - 1;
224 const size_t p = b % 12;
225 snprintf (buf, sizeof (buf), "%s%d", translate ? notes[p] : en_notes[p], octave);
230 ParameterDescriptor::normalize_note_name(const std::string& name)
232 // Remove whitespaces and convert to lower case for a more resilient parser
233 return boost::to_lower_copy(boost::erase_all_copy(name, " "));
236 ParameterDescriptor::NameNumMap
237 ParameterDescriptor::build_midi_name2num()
240 for (uint8_t num = 0; num < 128; num++) {
241 name2num[normalize_note_name(midi_note_name(num))] = num;
247 ParameterDescriptor::midi_note_num (const std::string& name)
249 static NameNumMap name2num = build_midi_name2num();
251 uint8_t num = -1; // -1 (or 255) is returned in case of failure
253 NameNumMap::const_iterator it = name2num.find(normalize_note_name(name));
254 if (it != name2num.end())
260 } // namespace ARDOUR