changeset 7:353276611036

Move pitch wheel range into a central location in MidiKeyboardSegment, eliminating local copies in OscMidiConverter etc. Also suppress some unneeded debugging messages in TouchkeyDevice.
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Sun, 17 Nov 2013 13:53:21 +0000
parents 36fe60d0aadb
children 2832beb744bb
files Builds/MacOSX/TouchKeys.xcodeproj/project.xcworkspace/xcuserdata/apm.xcuserdatad/UserInterfaceState.xcuserstate Source/MainApplicationController.cpp Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.h Source/Mappings/PitchBend/TouchkeyPitchBendMapping.cpp Source/Mappings/PitchBend/TouchkeyPitchBendMappingFactory.cpp Source/Mappings/PitchBend/TouchkeyPitchBendMappingFactory.h Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.cpp Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.h Source/TouchKeys/MidiOutputController.cpp Source/TouchKeys/OscMidiConverter.cpp Source/TouchKeys/OscMidiConverter.h Source/TouchKeys/TouchkeyDevice.cpp
diffstat 13 files changed, 107 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
Binary file Builds/MacOSX/TouchKeys.xcodeproj/project.xcworkspace/xcuserdata/apm.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- a/Source/MainApplicationController.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/MainApplicationController.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -37,12 +37,12 @@
 MainApplicationController::MainApplicationController()
 : midiInputController_(keyboardController_),
   touchkeyController_(keyboardController_),
-  oscReceiveEnabled_(false),
   oscReceiver_(0, ""),
   touchkeyErrorOccurred_(false),
   touchkeyErrorMessage_(""),
   touchkeyAutodetecting_(false),
   touchkeyStandaloneModeEnabled_(false),
+  oscReceiveEnabled_(false),
   oscReceivePort_(kDefaultOscReceivePort),
   experimentalMappingsEnabled_(false),
 #ifndef TOUCHKEYS_NO_GUI
@@ -62,9 +62,6 @@
     keyboardController_.setGUI(&keyboardDisplay_);
 	midiInputController_.setMidiOutputController(&midiOutputController_);
     
-	// Set the initial verbosity level of the TouchKeys devices
-	touchkeyController_.setVerboseLevel(2);
-    
     // Set up an initial OSC transmit host/port
     oscTransmitter_.addAddress(kDefaultOscTransmitHost, kDefaultOscTransmitPort);
 
--- a/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -24,8 +24,6 @@
 
 #include "TouchkeyKeyDivisionMappingFactory.h"
 
-const float TouchkeyKeyDivisionMappingFactory::kDefaultPitchWheelRangeSemitones = 2.0;
-
 // Yarman-24 Turkish microtonal tuning:
 /*      1/1	RAST		C
  84.360	Nim Zengule	C#/Db
@@ -116,7 +114,6 @@
 
 TouchkeyKeyDivisionMappingFactory::TouchkeyKeyDivisionMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment)
 : TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>(keyboard, segment),
-  pitchWheelRangeSemitones_(kDefaultPitchWheelRangeSemitones),
   numSegmentsPerKey_(TouchkeyKeyDivisionMapping::kDefaultNumberOfSegments),
   timeout_(TouchkeyKeyDivisionMapping::kDefaultDetectionTimeout),
   detectionParameter_(TouchkeyKeyDivisionMapping::kDefaultDetectionParameter),
@@ -129,14 +126,6 @@
     setBendParameters();
 }
 
-void TouchkeyKeyDivisionMappingFactory::setMIDIPitchWheelRange(float maxBendSemitones) {
-    if(maxBendSemitones <= 0)
-        return;
-    pitchWheelRangeSemitones_ = maxBendSemitones;
-    
-    setBendParameters();
-}
-
 void TouchkeyKeyDivisionMappingFactory::setName(const string& name) {
     TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>::setName(name);
     setBendParameters();
@@ -167,10 +156,10 @@
 }
 
 void TouchkeyKeyDivisionMappingFactory::setBendParameters() {
-    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, -pitchWheelRangeSemitones_, pitchWheelRangeSemitones_, 0.0);
+    // Range of 0 indicates special case of using global pitch wheel range
+    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, 0.0, 0.0, 0.0);
     
     if(midiConverter_ != 0) {
-        midiConverter_->setMidiPitchWheelRange(pitchWheelRangeSemitones_);
         midiConverter_->listenToIncomingControl(MidiKeyboardSegment::kControlPitchWheel);
     }
 }
\ No newline at end of file
--- a/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.h	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.h	Sun Nov 17 13:53:21 2013 +0000
@@ -30,7 +30,6 @@
 
 class TouchkeyKeyDivisionMappingFactory : public TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping> {
 private:
-    static const float kDefaultPitchWheelRangeSemitones;
     static const float kDefaultTuningsCents[];
     
 public:
@@ -47,7 +46,6 @@
     
     virtual const std::string factoryTypeName() { return "Split\nKeys"; }
 
-    void setMIDIPitchWheelRange(float maxBendSemitones); // Set the range for the MIDI pitch wheel
     void setName(const string& name);
     
     // ***** Specific Methods *****
@@ -92,7 +90,6 @@
     void initializeMappingParameters(int noteNumber, TouchkeyKeyDivisionMapping *mapping);
     void setBendParameters();
     
-    float pitchWheelRangeSemitones_;                    // Range of the MIDI pitch wheel (different than vibrato range)
     int numSegmentsPerKey_;                             // How many segments per key
     timestamp_diff_type timeout_;                       // How long before timeout activates default segment
     int detectionParameter_;                            // Which parameter separates it into segments
--- a/Source/Mappings/PitchBend/TouchkeyPitchBendMapping.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/PitchBend/TouchkeyPitchBendMapping.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -34,7 +34,7 @@
 const int TouchkeyPitchBendMapping::kDefaultMIDIChannel = 0;
 const int TouchkeyPitchBendMapping::kDefaultFilterBufferLength = 30;
 
-const float TouchkeyPitchBendMapping::kDefaultBendRangeSemitones = 7.0;
+const float TouchkeyPitchBendMapping::kDefaultBendRangeSemitones = 2.0;
 const float TouchkeyPitchBendMapping::kDefaultBendThresholdSemitones = 0.4;
 const float TouchkeyPitchBendMapping::kDefaultBendThresholdKeyLength = 0.1;
 const float TouchkeyPitchBendMapping::kDefaultSnapZoneSemitones = 0.5;
--- a/Source/Mappings/PitchBend/TouchkeyPitchBendMappingFactory.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/PitchBend/TouchkeyPitchBendMappingFactory.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -24,14 +24,10 @@
 #include "TouchkeyPitchBendMappingFactory.h"
 #include "TouchkeyPitchBendMappingShortEditor.h"
 
-// Class constants
-const float TouchkeyPitchBendMappingFactory::kDefaultPitchWheelRangeSemitones = 12.0;
-
 // Default constructor, containing a reference to the PianoKeyboard class.
 
 TouchkeyPitchBendMappingFactory::TouchkeyPitchBendMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) :
 TouchkeyBaseMappingFactory<TouchkeyPitchBendMapping>(keyboard, segment),
-pitchWheelRangeSemitones_(kDefaultPitchWheelRangeSemitones),
 bendRangeSemitones_(TouchkeyPitchBendMapping::kDefaultBendRangeSemitones),
 bendThresholdSemitones_(TouchkeyPitchBendMapping::kDefaultBendThresholdSemitones),
 bendThresholdKeyLength_(TouchkeyPitchBendMapping::kDefaultBendThresholdKeyLength),
@@ -54,20 +50,6 @@
 
 // ***** Accessors / Modifiers *****
 
-void TouchkeyPitchBendMappingFactory::setMIDIPitchWheelRange(float maxBendSemitones) {
-    if(maxBendSemitones <= 0)
-        return;
-    pitchWheelRangeSemitones_ = maxBendSemitones;
-    
-    // Update the OSC-MIDI converter
-    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, -pitchWheelRangeSemitones_, pitchWheelRangeSemitones_, 0.0);
-    
-    if(midiConverter_ != 0) {
-        midiConverter_->setMidiPitchWheelRange(pitchWheelRangeSemitones_);
-        midiConverter_->listenToIncomingControl(MidiKeyboardSegment::kControlPitchWheel);
-    }
-}
-
 void TouchkeyPitchBendMappingFactory::setName(const string& name) {
     TouchkeyBaseMappingFactory<TouchkeyPitchBendMapping>::setName(name);
     setBendParameters();
@@ -159,10 +141,10 @@
 }
 
 void TouchkeyPitchBendMappingFactory::setBendParameters() {
-    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, -pitchWheelRangeSemitones_, pitchWheelRangeSemitones_, 0.0);
+    // Range of 0 indicates special case of using global pitch wheel range
+    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, 0.0, 0.0, 0.0);
     
     if(midiConverter_ != 0) {
-        midiConverter_->setMidiPitchWheelRange(pitchWheelRangeSemitones_);
         midiConverter_->listenToIncomingControl(MidiKeyboardSegment::kControlPitchWheel);
     }
 }
--- a/Source/Mappings/PitchBend/TouchkeyPitchBendMappingFactory.h	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/PitchBend/TouchkeyPitchBendMappingFactory.h	Sun Nov 17 13:53:21 2013 +0000
@@ -36,10 +36,6 @@
 // whenever touches or notes begin or end
 
 class TouchkeyPitchBendMappingFactory : public TouchkeyBaseMappingFactory<TouchkeyPitchBendMapping> {
-private:
-    //typedef std::pair<TouchkeyVibratoMapping*, TouchkeyPitchBendMapping*> mapping_pair;
-    //const float kDefaultPitchWheelRangeSemitones = 12.0;
-    static const float kDefaultPitchWheelRangeSemitones;
     
 public:
     // ***** Constructor *****
@@ -55,7 +51,6 @@
     
     virtual const std::string factoryTypeName() { return "Pitch\nBend"; }
     
-    void setMIDIPitchWheelRange(float maxBendSemitones); // Set the range for the MIDI pitch wheel
     void setName(const string& name);
     
     // ***** Bend-Specific Methods *****
@@ -84,8 +79,6 @@
     void initializeMappingParameters(int noteNumber, TouchkeyPitchBendMapping *mapping);
     void setBendParameters();
     
-    float pitchWheelRangeSemitones_;                    // Range of the MIDI pitch wheel (different than vibrato range)
-    
     float bendRangeSemitones_;                          // Range of the pitch bend component
     float bendThresholdSemitones_;                      // Threshold for engaging pitch bend
     float bendThresholdKeyLength_;                      // Threshold in key length for engaging pitch bend
--- a/Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -26,13 +26,12 @@
 #include "TouchkeyVibratoMappingShortEditor.h"
 
 // Class constants
-const float TouchkeyVibratoMappingFactory::kDefaultPitchWheelRangeSemitones = 12.0;
 const int TouchkeyVibratoMappingFactory::kDefaultVibratoControl = MidiKeyboardSegment::kControlPitchWheel;
 
 // Default constructor, containing a reference to the PianoKeyboard class.
 
 TouchkeyVibratoMappingFactory::TouchkeyVibratoMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) :
-TouchkeyBaseMappingFactory<TouchkeyVibratoMapping>(keyboard, segment), pitchWheelRangeSemitones_(kDefaultPitchWheelRangeSemitones),
+TouchkeyBaseMappingFactory<TouchkeyVibratoMapping>(keyboard, segment),
 vibratoControl_(kDefaultVibratoControl),
 vibratoRange_(TouchkeyVibratoMapping::kDefaultVibratoRangeSemitones),
 vibratoPrescaler_(TouchkeyVibratoMapping::kDefaultVibratoPrescaler),
@@ -54,16 +53,6 @@
 
 // ***** Accessors / Modifiers *****
 
-void TouchkeyVibratoMappingFactory::setMIDIPitchWheelRange(float maxBendSemitones) {
-    if(maxBendSemitones <= 0)
-        return;
-    pitchWheelRangeSemitones_ = maxBendSemitones;
-    
-    if(vibratoControl_ != MidiKeyboardSegment::kControlPitchWheel)
-        return;
-    configurePitchWheelVibrato();
-}
-
 void TouchkeyVibratoMappingFactory::setName(const string& name) {
     TouchkeyBaseMappingFactory<TouchkeyVibratoMapping>::setName(name);
     setVibratoControl(vibratoControl_);
@@ -184,10 +173,10 @@
 
 // Configure the OSC-MIDI converter to handle pitchwheel vibrato
 void TouchkeyVibratoMappingFactory::configurePitchWheelVibrato() {
-    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, -pitchWheelRangeSemitones_, pitchWheelRangeSemitones_, 0.0);
+    // Range of 0 indicates special case of using global pitch wheel range
+    setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, 0.0, 0.0, 0.0);
     
     if(midiConverter_ != 0) {
-        midiConverter_->setMidiPitchWheelRange(pitchWheelRangeSemitones_);
         midiConverter_->listenToIncomingControl(MidiKeyboardSegment::kControlPitchWheel);
     }
 }
--- a/Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.h	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.h	Sun Nov 17 13:53:21 2013 +0000
@@ -36,7 +36,6 @@
 
 class TouchkeyVibratoMappingFactory : public TouchkeyBaseMappingFactory<TouchkeyVibratoMapping> {
 private:
-    static const float kDefaultPitchWheelRangeSemitones;
     static const int kDefaultVibratoControl;
 
 public:
@@ -53,9 +52,7 @@
     // ***** Accessors / Modifiers *****
     
     virtual const std::string factoryTypeName() { return "Vibrato"; }
-    
-    void setMIDIPitchWheelRange(float maxBendSemitones); // Set the range for the MIDI pitch wheel
-    
+
     void setName(const string& name);
     
     // ***** Vibrato-Specific Methods *****
@@ -87,7 +84,6 @@
     void configurePitchWheelVibrato();
     void configureControlChangeVibrato();
     
-    float pitchWheelRangeSemitones_;                    // Range of the MIDI pitch wheel (different than vibrato range)
     int vibratoControl_;                                // Controller to use with vibrato
     float vibratoRange_;                                // Range that the vibrato should use, in semitones or CC values
     float vibratoPrescaler_;                            // Prescaler value to use before nonlinear vibrato mapping
--- a/Source/TouchKeys/MidiOutputController.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/TouchKeys/MidiOutputController.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -23,7 +23,7 @@
 
 #include "MidiOutputController.h"
 
-#define MIDI_OUTPUT_CONTROLLER_DEBUG_RAW
+#undef MIDI_OUTPUT_CONTROLLER_DEBUG_RAW
 
 // Constructor
 MidiOutputController::MidiOutputController()
--- a/Source/TouchKeys/OscMidiConverter.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/TouchKeys/OscMidiConverter.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -29,7 +29,7 @@
 OscMidiConverter::OscMidiConverter(PianoKeyboard& keyboard, MidiKeyboardSegment& segment, int controllerId) :
   keyboard_(keyboard), keyboardSegment_(segment), midiOutputController_(0),
   controller_(controllerId), lastUniqueId_(0),
-  pitchWheelRange_(2.0), incomingController_(MidiKeyboardSegment::kControlDisabled)
+  incomingController_(MidiKeyboardSegment::kControlDisabled)
 {
 	setOscController(&keyboard_);
     
@@ -155,7 +155,7 @@
         defaultValue += keyboardSegment_.controllerValue(incomingController_) - incomingControllerCenterValue_;
     
     if(controller_ == MidiKeyboardSegment::kControlPitchWheel) {
-        sendPitchWheelRange(keyboardSegment_.outputPort(), channel);
+        //sendPitchWheelRange(keyboardSegment_.outputPort(), channel);
         midiOutputController_->sendPitchWheel(keyboardSegment_.outputPort(), channel, defaultValue);
     }
     else if(controller_ == MidiKeyboardSegment::kControlChannelAftertouch) {
@@ -176,12 +176,19 @@
     float controlValue = (float)controlCenterValue_ + (float)controlMinValue_
     + currentValue_[channel]*(float)(controlMaxValue_ - controlMinValue_);
     
-    if(incomingController_ != MidiKeyboardSegment::kControlDisabled)
+    if(incomingController_ != MidiKeyboardSegment::kControlDisabled) {
         controlValue += keyboardSegment_.controllerValue(incomingController_) - incomingControllerCenterValue_;
+#ifdef DEBUG_OSC_MIDI_CONVERTER
+        std::cout << "current value " << currentValue_[channel] << " corresponds to " << controlValue;
+        std::cout << " including incoming value " << (keyboardSegment_.controllerValue(incomingController_) - incomingControllerCenterValue_) << std::endl;
+#endif
+    }
+    else {
+#ifdef DEBUG_OSC_MIDI_CONVERTER
+        std::cout << "current value " << currentValue_[channel] << " corresponds to " << controlValue << std::endl;
+#endif
+    }
     
-#ifdef DEBUG_OSC_MIDI_CONVERTER
-    std::cout << "current value " << currentValue_[channel] << " corresponds to " << controlValue << std::endl;
-#endif
     int roundedControlValue = (int)roundf(controlValue);
     if(roundedControlValue > controlMaxValue_)
         roundedControlValue = controlMaxValue_;
@@ -211,7 +218,7 @@
     // Calculate the normalized center value which will be subtracted
     // from the scaled input. Do this once now to save computation.
     if(oscMinValue == oscMaxValue)
-        input.oscScaledCenterValue = 0;
+        input.oscScaledCenterValue = 0.5;
     else {
         input.oscScaledCenterValue = (oscCenterValue - oscMinValue) / (oscMaxValue - oscMinValue);
         if(input.oscScaledCenterValue < 0)
@@ -294,7 +301,10 @@
     minValue = inputs_[oscPath].oscMinValue;
     maxValue = inputs_[oscPath].oscMaxValue;
     
-    scaledCenterValue = (newValue - minValue) / (maxValue - minValue);
+    if(minValue == maxValue)
+        scaledCenterValue = 0.0;
+    else
+        scaledCenterValue = (newValue - minValue) / (maxValue - minValue);
     if(scaledCenterValue < 0)
         scaledCenterValue = 0;
     if(scaledCenterValue > 1.0)
@@ -384,8 +394,17 @@
     else
         return false;
     
-    // Scale input to a 0-1 range, the to the output range
-    float scaledValue = (oscParamValue - input.oscMinValue) / (input.oscMaxValue - input.oscMinValue);
+    // Scale input to a 0-1 range, then to the output range. There's a special case for MIDI pitch wheel,
+    // where if the range is set to 0, it means to use the segment-wide pitch wheel range. This is done so
+    // we don't have to cache multiple copies of the pitch wheel range in every OSC-MIDI converter.
+    float scaledValue;
+    if(controller_ == MidiKeyboardSegment::kControlPitchWheel &&
+       input.oscMaxValue == 0 && input.oscMinValue == 0) {
+        float pitchWheelRange = keyboardSegment_.midiPitchWheelRange();
+        scaledValue = (oscParamValue + pitchWheelRange) / (2.0 * pitchWheelRange);
+    }
+    else
+        scaledValue = (oscParamValue - input.oscMinValue) / (input.oscMaxValue - input.oscMinValue);
 
 #ifdef DEBUG_OSC_MIDI_CONVERTER
     std::cout << "port " << keyboardSegment_.outputPort() << " received input " << oscParamValue << " which scales to " << scaledValue << std::endl;
@@ -437,28 +456,6 @@
 	return true;
 }
 
-// Send a MIDI RPN message to set the pitch wheel range
-void OscMidiConverter::sendPitchWheelRange(int port, int channel) {
-    if(midiOutputController_ == 0)
-        return;
-    
-    // KLUDGE: fix by using MidiKeyboardSegment version
-    
-    // Find number of semitones and cents
-    int majorRange = (int)floorf(pitchWheelRange_);
-    int minorRange = (int)(100.0 * (pitchWheelRange_ - floorf(pitchWheelRange_)));
-    
-    // Set RPN controller = 0
-    midiOutputController_->sendControlChange(port, channel, 101, 0);
-    midiOutputController_->sendControlChange(port, channel, 100, 0);
-    // Set data value MSB/LSB for bend range in semitones
-    midiOutputController_->sendControlChange(port, channel, 6, majorRange);
-    midiOutputController_->sendControlChange(port, channel, 38, minorRange);
-    // Set RPN controller back to 16383
-    midiOutputController_->sendControlChange(port, channel, 101, 127);
-    midiOutputController_->sendControlChange(port, channel, 100, 127);
-}
-
 // Send the current sum value of all OSC inputs as a MIDI message
 void OscMidiConverter::sendCurrentValue(int port, int channel, int note, bool force) {
     if(midiOutputController_ == 0 || channel < 0 || channel > 15)
--- a/Source/TouchKeys/OscMidiConverter.h	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/TouchKeys/OscMidiConverter.h	Sun Nov 17 13:53:21 2013 +0000
@@ -75,10 +75,6 @@
     void setMidiMessageType(int defaultValue = -1, int minValue = -1,
                             int maxValue = -1, int centerValue = -1, bool use14BitControl = false);
     
-    // Specifically when MIDI Pitch Wheel is used as the destination, this sets the range
-    // in semitones which requires a separate MIDI RPN message to be sent to each channel.
-    void setMidiPitchWheelRange(float semitones) { pitchWheelRange_ = semitones; }
-    
     // Set whether this converter passes through incoming CC messages from the MIDI input,
     // and if so, which one. Doesn't need to be the same CC coming in as going out.
     void listenToIncomingControl(int controller, int centerValue = -1, bool use14BitControl = false);
@@ -120,7 +116,6 @@
 private:
     // ***** Private Methods *****
     int idWithChannel(int channel, int inputId) { return (inputId << 4) + channel; }
-    void sendPitchWheelRange(int port, int channel);
     void sendCurrentValue(int port, int channel, int note, bool force);
     
 	// ***** Member Variables *****
@@ -136,7 +131,6 @@
     int controlDefaultValue_;                       // Default value for the control on new notes
 
     int lastUniqueId_;                              // Global unique ID for input messages
-    float pitchWheelRange_;                         // Range of MIDI pitch wheel (if used)
     
     int incomingController_;                         // Which controller we listen to from the MIDI input
     bool incomingControllerIs14Bit_;                // Whether the input controller is 14 bit
--- a/Source/TouchKeys/TouchkeyDevice.cpp	Wed Nov 13 23:40:53 2013 +0000
+++ b/Source/TouchKeys/TouchkeyDevice.cpp	Sun Nov 17 13:53:21 2013 +0000
@@ -25,7 +25,6 @@
 #include <stdlib.h>
 #include "TouchkeyDevice.h"
 
-
 const char* kKeyNames[13] = {"C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B ", "c "};
 
 // Constructor
@@ -35,7 +34,7 @@
 ioThread_(boost::bind(&TouchkeyDevice::runLoop, this, _1), "TouchKeyDevice::ioThread"),
 rawDataThread_(boost::bind(&TouchkeyDevice::rawDataRunLoop, this, _1), "TouchKeyDevice::rawDataThread"),
 autoGathering_(false), shouldStop_(false), sendRawOscMessages_(false),
-verbose_(4), numOctaves_(0), lowestMidiNote_(12), lowestKeyPresentMidiNote_(12),
+verbose_(0), numOctaves_(0), lowestMidiNote_(12), lowestKeyPresentMidiNote_(12),
 updatedLowestMidiNote_(12), deviceSoftwareVersion_(-1), deviceHardwareVersion_(-1),
 expectedLengthWhite_(kTransmissionLengthWhiteNewHardware),
 expectedLengthBlack_(kTransmissionLengthBlackNewHardware), deviceHasRGBLEDs_(false),
@@ -155,7 +154,8 @@
 		return false;
 	tcflush(device_, TCIFLUSH);							// Flush device input
 	if(write(device_, (char*)kCommandStatus, 5) < 0) {	// Write status command
-		cout << "ERROR: unable to write status command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write status command.  errno = " << errno << endl;
 		return false;
 	}	
 	tcdrain(device_);									// Force output reach device
@@ -169,7 +169,8 @@
 
 		if(count < 0) {				// Check if an error occurred on read
 			if(errno != EAGAIN) {
-				cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
+                if(verbose_ >= 1)
+                    cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
 				return false;
 			}
 		}
@@ -204,7 +205,8 @@
 								continue;
 							if(count < 0) {
 								if(errno != EAGAIN && verbose_ >= 1) {	// EAGAIN just means no data was available
-									cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
+                                    if(verbose_ >= 1)
+                                        cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
 									return false;
 								}
 								
@@ -263,6 +265,7 @@
 								cout << " Software Version " << status.softwareVersionMajor << "." << status.softwareVersionMinor;
 								cout << endl << "  " << status.octaves << " octaves connected" << endl;
 							}
+                            
 							for(int i = 0; i < status.octaves; i++) {
 								bool foundKey = false;
 								
@@ -281,7 +284,7 @@
 
 								}
 
-								cout << endl;
+								if(verbose_ >= 1) cout << endl;
 							}
                             
                             // Hardware version determines whether all keys have XY or not
@@ -358,7 +361,8 @@
     
     // Tell the device to start scanning for new data
 	if(write(device_, (char*)kCommandStartScanning, 5) < 0) {
-		cout << "ERROR: unable to write startAutoGather command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write startAutoGather command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -386,7 +390,8 @@
     
     // Tell device to stop scanning
 	if(write(device_, (char*)kCommandStopScanning, 5) < 0) {
-		cout << "ERROR: unable to write stopAutoGather command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write stopAutoGather command.  errno = " << errno << endl;
 	}		
 	tcdrain(device_);
 	
@@ -432,14 +437,10 @@
 // Begin raw data collection from a given single key
 
 bool TouchkeyDevice::startRawDataCollection(int octave, int key, int mode, int scaler) {
-    cout << "startRawDataCollection()\n";
-    
 	if(!isOpen())
 		return false;
 	
 	stopAutoGathering();	// Stop the thread if it's running	
-	
-    cout << "preparing\n";
     
 	//unsigned char command[] = {ESCAPE_CHARACTER, kControlCharacterFrameBegin,
 	//	kFrameTypeMonitorRawFromKey, (unsigned char)octave, (unsigned char)key,
@@ -455,7 +456,8 @@
         ESCAPE_CHARACTER, kControlCharacterFrameEnd};
 	
 	if(write(device_, (char*)commandSetMode, 12) < 0) {
-		cout << "ERROR: unable to write setMode command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setMode command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
     
@@ -468,7 +470,8 @@
         ESCAPE_CHARACTER, kControlCharacterFrameEnd};
 	
 	if(write(device_, (char*)commandSetScaler, 12) < 0) {
-		cout << "ERROR: unable to write setMode command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setMode command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
     
@@ -480,7 +483,8 @@
         ESCAPE_CHARACTER, kControlCharacterFrameEnd};
     
 	if(write(device_, (char*)commandPrepareRead, 10) < 0) {
-		cout << "ERROR: unable to write prepareRead command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write prepareRead command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
     
@@ -497,7 +501,6 @@
 	
 	autoGathering_ = true;
     
-    cout << "running\n";
 	/*if(write(device_, (char*)command, 9) < 0) {
 		cout << "ERROR: unable to write startRawDataCollection command.  errno = " << errno << endl;
 	}
@@ -522,7 +525,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 6) < 0) {
-		cout << "ERROR: unable to write startRawDataCollection command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write startRawDataCollection command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -563,7 +567,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 8) < 0) {
-		cout << "ERROR: unable to write setKeySensitivity command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setKeySensitivity command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -602,7 +607,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 8) < 0) {
-		cout << "ERROR: unable to write setKeyCentroidScaler command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setKeyCentroidScaler command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -642,7 +648,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 9) < 0) {
-		cout << "ERROR: unable to write setKeyMinimumCentroidSize command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setKeyMinimumCentroidSize command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -679,7 +686,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 8) < 0) {
-		cout << "ERROR: unable to write setKeyNoiseThreshold command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setKeyNoiseThreshold command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -697,7 +705,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 5) < 0) {
-		cout << "ERROR: unable to write jumpToBootloader command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write jumpToBootloader command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 }
@@ -835,7 +844,8 @@
     
 	// Send command
 	if(write(device_, (char*)command, location) < 0) {
-		cout << "ERROR: unable to write setRGBLEDColor command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setRGBLEDColor command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -863,7 +873,8 @@
 	
 	// Send command
 	if(write(device_, (char*)command, 5) < 0) {
-		cout << "ERROR: unable to write setRGBLEDAllOff command.  errno = " << errno << endl;
+        if(verbose_ >= 1)
+            cout << "ERROR: unable to write setRGBLEDAllOff command.  errno = " << errno << endl;
 	}
 	tcdrain(device_);
 	
@@ -1215,7 +1226,8 @@
 		}
 		if(count < 0) {
 			if(errno != EAGAIN) {	// EAGAIN just means no data was available
-				cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
+                if(verbose_ >= 1)
+                    cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
 				shouldStop_ = true;
 			}
 			
@@ -1321,10 +1333,10 @@
             lastTime = currentTime;
             // Request data
             if(write(device_, (char*)gatherDataCommand, 9) < 0) {
-                cout << "ERROR: unable to write setMode command.  errno = " << errno << endl;
+                if(verbose_ >= 1)
+                    cout << "ERROR: unable to write setMode command.  errno = " << errno << endl;
             }
             tcdrain(device_);
-            cout << "wrote to device\n";
         }
         
  		long count = read(device_, (char *)buffer, 1024);
@@ -1335,7 +1347,8 @@
 		}
 		if(count < 0) {
 			if(errno != EAGAIN) {	// EAGAIN just means no data was available
-				cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
+                if(verbose_ >= 1)
+                    cout << "Unable to read from device (error " << errno << ").  Aborting.\n";
 				shouldStop_ = true;
 			}
 			
@@ -1581,7 +1594,8 @@
 	// since it will never be part of a valid centroid.
 	
 	if(buffer[0] == 0x88) {
-		cout << "Warning: octave " << octave << " key " << key << " data is not ready.  Check scan rate.\n";
+        if(verbose_ >= 1)
+            cout << "Warning: octave " << octave << " key " << key << " data is not ready.  Check scan rate.\n";
         if(deviceSoftwareVersion_ >= 1)
             return white ? expectedLengthWhite_ : expectedLengthBlack_;
         else
@@ -1697,7 +1711,8 @@
 	// Sanity check: do we have the PianoKey structure available to receive this data?
 	// If not, no need to proceed further.
 	if(keyboard_.key(midiNote) == 0) {
-		cout << "Warning: No PianoKey available for touchkey MIDI note " << midiNote << endl;
+        if(verbose_ >= 1)
+            cout << "Warning: No PianoKey available for touchkey MIDI note " << midiNote << endl;
 		return bytesParsed;
 	}
     
@@ -1823,10 +1838,12 @@
         
         // Check the timestamp against the last frame from this board to see if any frames have been dropped
         if(frame > analogLastFrame_[board] + 1) {
-            cout << "WARNING: dropped frame(s) on board " << board << " at " << frame << " (last was " << analogLastFrame_[board] << ")" << endl;
+            if(verbose_ >= 1)
+                cout << "WARNING: dropped frame(s) on board " << board << " at " << frame << " (last was " << analogLastFrame_[board] << ")" << endl;
         }
         else if(frame < analogLastFrame_[board] + 1) {
-            cout << "WARNING: repeat frame(s) on board " << board << " at " << frame << " (last was " << analogLastFrame_[board] << ")" << endl;            
+            if(verbose_ >= 1)
+                cout << "WARNING: repeat frame(s) on board " << board << " at " << frame << " (last was " << analogLastFrame_[board] << ")" << endl;
         }
         analogLastFrame_[board] = frame;
         
@@ -1871,8 +1888,10 @@
                 // Update the GUI but don't actually save the value since it's uncalibrated
                 keyboard_.gui()->setAnalogValueForKey(midiNote, (float)value / kTouchkeyAnalogValueMax);
                 
-                if(keyCalibrators_[octave*12 + key]->calibrationStatus() == kPianoKeyCalibrated)
-                    cout << "key " << midiNote << " calibrated but missing (raw value " << value << ")\n";
+                if(keyCalibrators_[octave*12 + key]->calibrationStatus() == kPianoKeyCalibrated) {
+                    if(verbose_ >= 1)
+                        cout << "key " << midiNote << " calibrated but missing (raw value " << value << ")\n";
+                }
             }
         }
         
@@ -1894,7 +1913,8 @@
     
     // Error on error message frame!
     if(bufferLength < 5) {
-        cout << "Warning: received error message frame of " << bufferLength << " bytes, less than minimum 5\n";
+        if(verbose_ >= 1)
+            cout << "Warning: received error message frame of " << bufferLength << " bytes, less than minimum 5\n";
         return;
     }
     
@@ -1905,7 +1925,8 @@
     msg[len - 1] = '\0';
     
     // Print the error
-    cout << "Error frame received: " << msg << endl;
+    if(verbose_ >= 1)
+        cout << "Error frame received: " << msg << endl;
     
     // Dump the buffer containing error coding information
     if(verbose_ >= 2) {
@@ -1921,7 +1942,8 @@
     // Format: [octave] [key] [length] <data>
     
     if(bufferLength < 3) {
-        cout << "Warning: received I2C response frame of " << bufferLength << " bytes, less than minimum 3\n";
+        if(verbose_ >= 1)
+            cout << "Warning: received I2C response frame of " << bufferLength << " bytes, less than minimum 3\n";
         return;
     }
     
@@ -1930,8 +1952,10 @@
     int responseLength = buffer[2];
     
     if(bufferLength < responseLength + 3) {
-        cout << "Warning: received malformed I2C response (octave " << octave << ", key " << key << ", length " << responseLength;
-        cout << ") but only " << bufferLength - 3 << " bytes of data\n";
+        if(verbose_ >= 1) {
+            cout << "Warning: received malformed I2C response (octave " << octave << ", key " << key << ", length " << responseLength;
+            cout << ") but only " << bufferLength - 3 << " bytes of data\n";
+        }
         
         responseLength = bufferLength - 3;
     }
@@ -2025,7 +2049,8 @@
 		
 		if(count < 0) {				// Check if an error occurred on read
 			if(errno != EAGAIN) {
-				cout << "Unable to read from device while waiting for ACK (error " << errno << ").  Aborting.\n";
+                if(verbose_ >= 1)
+                    cout << "Unable to read from device while waiting for ACK (error " << errno << ").  Aborting.\n";
 				return false;
 			}
 		}
@@ -2051,7 +2076,8 @@
 		currentTime = Time::getMillisecondCounterHiRes();
 	}
 	
-	cout << "Error: timeout waiting for ACK\n";
+    if(verbose_ >= 1)
+        cout << "Error: timeout waiting for ACK\n";
 	return false;
 }