diff options
Diffstat (limited to 'libs/surfaces/us2400/meter.cc')
-rw-r--r-- | libs/surfaces/us2400/meter.cc | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/libs/surfaces/us2400/meter.cc b/libs/surfaces/us2400/meter.cc new file mode 100644 index 0000000000..dd08724ff5 --- /dev/null +++ b/libs/surfaces/us2400/meter.cc @@ -0,0 +1,137 @@ +/* + Copyright (C) 2006,2007 John Anderson + Copyright (C) 2012 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <cmath> + +#include "pbd/compose.h" +#include "ardour/debug.h" + +#include "meter.h" +#include "surface.h" +#include "surface_port.h" +#include "control_group.h" +#include "us2400_control_protocol.h" + +using namespace PBD; +using namespace ArdourSurface; +using namespace US2400; + +Control* +Meter::factory (Surface& surface, int id, const char* name, Group& group) +{ + Meter* m = new Meter (id, name, group); + surface.meters[id] = m; + surface.controls.push_back (m); + group.add (*m); + return m; +} + +void +Meter::notify_metering_state_changed(Surface& surface, bool transport_is_rolling, bool metering_active) +{ +return; + + MidiByteArray msg; + + // sysex header + msg << surface.sysex_hdr(); + + // code for Channel Meter Enable Message + msg << 0x20; + + // Channel identification + msg << id(); + + // Enable (0x07) / Disable (0x00) level meter on LCD, peak hold display on horizontal meter and signal LED + _enabled = ((surface.mcp().device_info().has_separate_meters() || transport_is_rolling) && metering_active); + msg << (_enabled ? 0x07 : 0x00); + + // sysex trailer + msg << MIDI::eox; + + surface.write (msg); +} + +void +Meter::send_update (Surface& surface, float dB) +{ + + float def = 0.0f; /* Meter deflection %age */ + + // DEBUG_TRACE (DEBUG::US2400, string_compose ("Meter ID %1 dB %2\n", id(), dB)); + + if (dB < -70.0f) { + def = 0.0f; + } else if (dB < -60.0f) { + def = (dB + 70.0f) * 0.25f; + } else if (dB < -50.0f) { + def = (dB + 60.0f) * 0.5f + 2.5f; + } else if (dB < -40.0f) { + def = (dB + 50.0f) * 0.75f + 7.5f; + } else if (dB < -30.0f) { + def = (dB + 40.0f) * 1.5f + 15.0f; + } else if (dB < -20.0f) { + def = (dB + 30.0f) * 2.0f + 30.0f; + } else if (dB < 6.0f) { + def = (dB + 20.0f) * 2.5f + 50.0f; + } else { + def = 115.0f; + } + + /* 115 is the deflection %age that would be + when dB=6.0. this is an arbitrary + endpoint for our scaling. + */ + + MidiByteArray msg; + + if (def > 100.0f) { + if (!overload_on) { + overload_on = true; + surface.write (MidiByteArray (2, 0xd0, (id() << 4) | 0xe)); + } + } else { + if (overload_on) { + overload_on = false; + surface.write (MidiByteArray (2, 0xd0, (id() << 4) | 0xf)); + } + } + + /* we can use up to 13 segments */ + + int segment = lrintf ((def/115.0) * 13.0); + + //only send an update 'twice' + if (segment == last_update_segment) { + if (segment == llast_update_segment) { + return; + } + } + llast_update_segment = last_update_segment; + last_update_segment = segment; + + + surface.write (MidiByteArray (2, 0xd0, (id()<<4) | segment)); +} + +MidiByteArray +Meter::zero () +{ + return MidiByteArray (2, 0xD0, (id()<<4 | 0)); +} |