/* * Copyright (C) 2017 Ben Loftis * * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #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)); }