Reftone.cpp (6187B)
1 2 #include "Reftone.hpp" 3 4 void Reftone::processAll(const ProcessArgs& args) { 5 // C4 -- the pitch.hpp reference frequency -- in knob values: 6 const float referencePitch = 0.0f; 7 const float referenceOctave = 4.0f; 8 9 if (!( 10 _pitch == params[PITCH_PARAM].getValue() && 11 _octave == params[OCTAVE_PARAM].getValue() && 12 _fine == params[FINE_PARAM].getValue() 13 )) { 14 _pitch = params[PITCH_PARAM].getValue(); 15 _octave = params[OCTAVE_PARAM].getValue(); 16 _fine = params[FINE_PARAM].getValue(); 17 _frequency = semitoneToFrequency(referenceSemitone + 12.0f*roundf(_octave - referenceOctave) + roundf(_pitch - referencePitch) + _fine); 18 _cv = frequencyToCV(_frequency); 19 } 20 21 if (outputs[CV_OUTPUT].isConnected()) { 22 outputs[CV_OUTPUT].setVoltage(_cv); 23 } 24 else { 25 outputs[CV_OUTPUT].setVoltage(0.0); 26 } 27 28 if (outputs[OUT_OUTPUT].isConnected()) { 29 _sine.setFrequency(_frequency); 30 outputs[OUT_OUTPUT].setVoltage(_sine.next() * 5.0f); 31 } 32 else { 33 outputs[OUT_OUTPUT].setVoltage(0.0); 34 } 35 } 36 37 struct ReftoneDisplay : DisplayWidget { 38 const NVGcolor _textColor = nvgRGBA(0x00, 0xff, 0x00, 0xee); 39 40 Reftone* _module; 41 const Vec _size; 42 std::string _fontPath; 43 44 ReftoneDisplay( 45 Reftone* module, 46 Vec size 47 ) 48 : DisplayWidget(module) 49 , _module(module) 50 , _size(size) 51 , _fontPath(asset::plugin(pluginInstance, "res/fonts/inconsolata-bold.ttf")) 52 { 53 } 54 55 void draw(const DrawArgs& args) override; 56 void drawLit(const DrawArgs& args) override; 57 void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override; 58 void drawBackground(const DrawArgs& args); 59 void drawText(const DrawArgs& args, const char* s, float x, float y, int size); 60 void drawCenteredText(const DrawArgs& args, const char* s, float y, int size); 61 float textRenderWidth(const DrawArgs& args, const char* s, int size); 62 }; 63 64 void ReftoneDisplay::draw(const DrawArgs& args) { 65 if (!isLit()) { 66 drawOnce(args, isScreenshot(), false); 67 } 68 } 69 70 void ReftoneDisplay::drawLit(const DrawArgs& args) { 71 if (isLit()) { 72 drawOnce(args, false, true); 73 } 74 } 75 76 void ReftoneDisplay::drawOnce(const DrawArgs& args, bool screenshot, bool lit) { 77 int mPitch = 9; 78 int mOctave = 4; 79 float mFine = 0.0f; 80 float mFrequency = 440.0f; 81 if (!screenshot) { 82 mPitch = _module->_pitch; 83 mOctave = _module->_octave; 84 mFine = _module->_fine; 85 mFrequency = _module->_frequency; 86 } 87 88 std::string octave = std::to_string(mOctave); 89 std::string fine = format("%s%02d", mFine < 0.0 ? "-" : "+", abs((int)(mFine * 100))); 90 std::string frequency = format(mFrequency >= 1000.0 ? "%0.0f" : "%0.1f", mFrequency); 91 const char* pitch = NULL; 92 const char* sharpFlat = NULL; 93 switch (mPitch) { 94 case 0: { 95 pitch = "C"; 96 break; 97 } 98 case 1: { 99 pitch = "C"; 100 sharpFlat = "#"; 101 break; 102 } 103 case 2: { 104 pitch = "D"; 105 break; 106 } 107 case 3: { 108 pitch = "E"; 109 sharpFlat = "b"; 110 break; 111 } 112 case 4: { 113 pitch = "E"; 114 break; 115 } 116 case 5: { 117 pitch = "F"; 118 break; 119 } 120 case 6: { 121 pitch = "F"; 122 sharpFlat = "#"; 123 break; 124 } 125 case 7: { 126 pitch = "G"; 127 break; 128 } 129 case 8: { 130 pitch = "G"; 131 sharpFlat = "#"; 132 break; 133 } 134 case 9: { 135 pitch = "A"; 136 break; 137 } 138 case 10: { 139 pitch = "B"; 140 sharpFlat = "b"; 141 break; 142 } 143 case 11: { 144 pitch = "B"; 145 break; 146 } 147 } 148 149 nvgSave(args.vg); 150 if (!screenshot && !lit) { 151 drawBackground(args); 152 } 153 else { 154 drawBackground(args); 155 if (sharpFlat) { 156 drawText(args, pitch, 3, 20, 28); 157 drawText(args, sharpFlat, 16, 12, 16); 158 drawText(args, octave.c_str(), 22, 20, 28); 159 } 160 else { 161 drawCenteredText(args, (pitch + octave).c_str(), 20, 28); 162 } 163 drawCenteredText(args, fine.c_str(), 32.5, 14); 164 drawCenteredText(args, frequency.c_str(), 45, 14); 165 } 166 nvgRestore(args.vg); 167 } 168 169 void ReftoneDisplay::drawBackground(const DrawArgs& args) { 170 nvgSave(args.vg); 171 nvgBeginPath(args.vg); 172 nvgRect(args.vg, 0, 0, _size.x, _size.y); 173 nvgFillColor(args.vg, nvgRGBA(0x00, 0x00, 0x00, 0xff)); 174 nvgFill(args.vg); 175 nvgStrokeColor(args.vg, nvgRGBA(0x50, 0x50, 0x50, 0xff)); 176 nvgStroke(args.vg); 177 nvgRestore(args.vg); 178 } 179 180 void ReftoneDisplay::drawText(const DrawArgs& args, const char* s, float x, float y, int size) { 181 std::shared_ptr<Font> font = APP->window->loadFont(_fontPath); 182 nvgSave(args.vg); 183 nvgTranslate(args.vg, x, y); 184 nvgFontSize(args.vg, size); 185 nvgFontFaceId(args.vg, font->handle); 186 nvgFillColor(args.vg, _textColor); 187 nvgText(args.vg, 0, 0, s, NULL); 188 nvgRestore(args.vg); 189 } 190 191 void ReftoneDisplay::drawCenteredText(const DrawArgs& args, const char* s, float y, int size) { 192 float x = textRenderWidth(args, s, size); 193 x = std::max(0.0f, _size.x - x); 194 x /= 2.0; 195 drawText(args, s, x, y, size); 196 } 197 198 float ReftoneDisplay::textRenderWidth(const DrawArgs& args, const char* s, int size) { 199 // nvgSave(args.vg); 200 // nvgFontSize(args.vg, size); 201 // float w = nvgTextBounds(args.vg, 0, 0, s, NULL, NULL); 202 // nvgRestore(args.vg); 203 // return w - size/4.0; 204 return strlen(s) * (size / 2.1); 205 } 206 207 struct ReftoneWidget : BGModuleWidget { 208 static constexpr int hp = 3; 209 210 ReftoneWidget(Reftone* module) { 211 setModule(module); 212 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 213 setPanel(box.size, "Reftone"); 214 createScrews(); 215 216 { 217 auto inset = Vec(3.5, 18); 218 auto size = Vec(38, 48); 219 auto display = new ReftoneDisplay(module, size); 220 display->box.pos = inset; 221 display->box.size = size; 222 addChild(display); 223 } 224 225 // generated by svg_widgets.rb 226 auto pitchParamPosition = Vec(9.5, 89.5); 227 auto octaveParamPosition = Vec(9.5, 143.5); 228 auto fineParamPosition = Vec(9.5, 197.5); 229 230 auto cvOutputPosition = Vec(10.5, 239.0); 231 auto outOutputPosition = Vec(10.5, 274.0); 232 // end generated by svg_widgets.rb 233 234 addParam(createParam<Knob26>(pitchParamPosition, module, Reftone::PITCH_PARAM)); 235 addParam(createParam<Knob26>(octaveParamPosition, module, Reftone::OCTAVE_PARAM)); 236 addParam(createParam<Knob26>(fineParamPosition, module, Reftone::FINE_PARAM)); 237 238 addOutput(createOutput<Port24>(cvOutputPosition, module, Reftone::CV_OUTPUT)); 239 addOutput(createOutput<Port24>(outOutputPosition, module, Reftone::OUT_OUTPUT)); 240 } 241 }; 242 243 Model* modelReftone = bogaudio::createModel<Reftone, ReftoneWidget>("Bogaudio-Reftone", "REFTONE", "Precision pitch CV generator", "Tuner");