1 /*! 2 * @file midilfo.h 3 * @brief Member definitions for the MidiLfo MIDI worker class. 4 * 5 * 6 * Copyright 2009 - 2017 <qmidiarp-devel@lists.sourceforge.net> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 * MA 02110-1301, USA. 22 * 23 */ 24 25 #ifndef MIDILFO_H 26 #define MIDILFO_H 27 28 #include <vector> 29 #include "midiworker.h" 30 31 32 /*! @brief MIDI worker class for the LFO Module. Implements a sequencer 33 * for controller data as a QObject. 34 * 35 * The parameters of MidiLfo are controlled by the LfoWidget class. 36 * The backend driver thread calls the Engine::echoCallback(), which will 37 * query each module, in this case via 38 * the MidiLfo::getNextFrame() method. MidiLfo will fill a frame from 39 * its internal MidiLfo::data buffer as a function of the position of 40 * the driver's transport. MidiLfo::frame is then accessed by Engine. It 41 * has size 1 except for resolution higher than 16th notes. 42 * The MidiLfo::data buffer is populated by the getData() function 43 * at each modification done via the LfoWidget. It can consist of 44 * a classic waveform calculation or a hand-drawn waveform. In all cases 45 * the waveform has resolution, offset and size attributes and single 46 * points can be tagged as muted, which will avoid data output at the 47 * corresponding position. 48 */ 49 class MidiLfo : public MidiWorker { 50 51 private: 52 int lastMouseLoc; /*!< The X location of the last modification of the wave, used for interpolation*/ 53 int lastMouseY; /*!< The Y location at the last modification of the wave, used for interpolation*/ 54 int recValue; 55 int lastSampleValue; 56 /*! @brief recalculates the MidiLfo::customWave as a function 57 * of a new offset value. 58 * 59 * It is called by MidiLfo::updateOffset() in case a custom wave is active. 60 * @param cwoffs New offset value 61 */ 62 void updateCustomWaveOffset(int cwoffs); 63 64 public: 65 bool recordMode, isRecording; 66 bool lastMute; /**< Contains the mute state of the last waveForm point modified by mouse click*/ 67 int old_res; 68 int freq, amp, offs; 69 int size; /*!< Size of the waveform in quarter notes */ 70 int res; /*!< Resolution of the waveform in ticks per quarter note */ 71 int frameSize; /*!< Current size of a vector returned by MidiLfo::getNextFrame() */ 72 int maxNPoints; /*!< Maximum number of steps that have been used in the session */ 73 int waveFormIndex; /*!< Index of the waveform to produce 74 @par 0: Sine 75 @par 1: Sawtooth Up 76 @par 2: Triangle 77 @par 3: Sawtooth Down 78 @par 4: Square 79 @par 5: Use Custom Wave */ 80 int cwmin; /*!< The minimum of MidiLfo::customWave */ 81 std::vector<Sample> customWave; /*!< Vector of Sample points holding the custom drawn wave */ 82 std::vector<bool> muteMask; /*!< Vector of booleans with mute state information for each wave point */ 83 std::vector<Sample> frame; /*!< Vector of Sample points holding the current frame for transfer */ 84 std::vector<Sample> data; 85 86 public: 87 MidiLfo(); ~MidiLfo()88 virtual ~MidiLfo() {} 89 void updateWaveForm(int val); 90 void updateFrequency(int); 91 void updateAmplitude(int); 92 void updateOffset(int); 93 void updateResolution(int); 94 void updateSize(int); 95 void updateLoop(int); 96 void record(int value); 97 void setRecordMode(bool on); 98 /*! @brief Called by LfoWidget::mouseEvent() 99 */ 100 int mouseEvent(double mouseX, double mouseY, int buttons, int pressed); 101 /*! 102 * @brief determines the minimum of the current waveform and 103 * sets the LfoWidget::offset slider accordingly. 104 * 105 * It also sets MidiLfo::cwmin. When a new waveform is drawn, its minimum 106 * offset from 0 changes and the offset controller has to be adapted in range. 107 * 108 */ 109 void newCustomOffset(); 110 111 /*! @brief sets the (controller) value of one point of the 112 * MidiLfo::customWave array. It is used for handling drawing functionality. 113 * 114 * It is called by the mouseEvent() function. 115 * The normalized mouse coordinates are scaled to the waveform size and 116 * resolution and to the controller range (0 ... 127). The function 117 * interpolates potentially missing waveform points between two events 118 * if the mouse buttons were not released. 119 * 120 * @returns index in the wave vector that has been set 121 * @param mouseX Normalized horizontal location of the mouse on the 122 * LfoScreen (0.0 ... 1.0) 123 * @param mouseY Normalized verical location of the mouse on the 124 * LfoScreen (0.0 ... 1.0) 125 * @param newpt Set to true if the mouse button was newly clicked before 126 * the move 127 * 128 * @see MidiLfo::toggleMutePoint(), MidiLfo::setMutePoint() 129 */ 130 int setCustomWavePoint(double mouseX, double mouseY, bool newpt); 131 /*! @brief sets the mute state of one point of the 132 * MidiLfo::muteMask array to the given state. 133 * 134 * The method is called when the right mouse button is clicked on the 135 * LfoScreen via the mouseEvent() function. 136 * If calculated waveforms are active, only the MidiLfo::muteMask is 137 * changed. If a custom waveform is active, the Sample.mute status 138 * at the given position is changed as well. 139 * 140 * @returns index in the wave vector that has been set 141 * @param mouseX Normalized Horizontal location of the mouse on the 142 * LfoScreen (0.0 ... 1.0) 143 * @param muted mute state to set for the given position 144 * 145 * @see MidiLfo::toggleMutePoint() 146 */ 147 int setMutePoint(double mouseX, bool muted); 148 /*! @brief recalculates the MidiLfo::customWave as a 149 * function of the current MidiLfo::res and MidiLfo::size values. 150 * 151 * It is called upon every change of MidiLfo::size and MidiLfo::res. It 152 * repeats the current MidiLfo::customWave periodically if the new values 153 * lead to a bigger size data array. 154 */ 155 void resizeAll(); 156 /*! @brief copies the current MidiLfo::data array into 157 * MidiLfo::customWave. 158 * 159 * It is called when a waveform modification by the user is attempted 160 * while in calculated waveform mode. (MidiLfo::waveFormIndex 1 ... 4). 161 */ 162 void copyToCustom(); 163 /*! @brief flips the MidiLfo::customWave array about its middle value 164 * 165 * It is called by LfoWidget when the vertical flip button is pressed. 166 */ 167 void flipWaveVertical(); 168 /*! @brief sets the MidiLfo::framePtr to the given value. 169 * 170 * It is called when the Transport starts. 171 * @param idx Index to which the framePtr is set 172 */ 173 void setFramePtr(int idx); 174 /** 175 * @brief does the actions related to a newly received event. 176 * 177 * It is called by Engine when a new event is received on the MIDI input port. 178 179 * @param inEv MidiEvent to check and process or not 180 * @param tick The time the event was received in internal ticks 181 * @return True if inEv is in not the input range of the module (event is unmatched) 182 */ 183 bool handleEvent(MidiEvent inEv, int tick); 184 /*! @brief is the main calculator for the data contained 185 * in a waveform. 186 * 187 * It is called upon every change of parameters in LfoWidget or upon 188 * input by mouse clicks on the LfoScreen. It fills the 189 * MidiLfo::data buffer with Sample points, which it either calculates 190 * or which it copies from the MidiLfo::customWave data. 191 * 192 * @param *data reference to an array the waveform is copied to 193 */ 194 void getData(std::vector<Sample> *data); 195 /*! @brief fills the MidiLfo::frame with Sample data points taken from 196 * the currently active waveform MidiLfo::data. 197 * 198 * MidiLfo::frame is then accessed by Engine::echoCallback() and sequenced 199 * to the driver backend. 200 * 201 * @param tick current tick 202 */ 203 void getNextFrame(int tick); 204 /*! @brief toggles the mute state of one point of the 205 * MidiLfo::muteMask array. 206 * 207 * The function is called when the right mouse button is clicked on the 208 * LfoScreen. 209 * If calculated waveforms are active, only the MidiLfo::muteMask is 210 * changed. If a custom waveform is active, the Sample.mute status 211 * at the given position is changed as well. 212 * 213 * @param mouseX Normalized Horizontal location of the mouse on the 214 * LfoScreen (0.0 ... 1.0) 215 * @see MidiLfo::setMutePoint 216 */ 217 bool toggleMutePoint(double mouseX); 218 219 /*! @brief Checks if deferred parameter changes are pending and applies 220 * them if so 221 */ 222 void applyPendingParChanges(); 223 /** 224 * @brief sets MidiLfo::nextTick and MidiLfo::framePtr position 225 * according to the specified tick. 226 * 227 * @param tick The current tick to which the module position should be 228 * aligned. 229 */ 230 void setNextTick(int tick); 231 }; 232 233 #endif 234