From 2387aeeca88cb9c91f49e87ac52185e0f8de7daa Mon Sep 17 00:00:00 2001 From: Aaron Static Date: Sat, 30 Oct 2021 03:27:48 +1100 Subject: [PATCH] Refactor and clean up Refactored to abstract out most functions to a library and prepare for new modules --- src/ChordCV.cpp | 190 ++++++----------------------------------------- src/Scratch.cpp | 47 ------------ src/musiclib.cpp | 165 ++++++++++++++++++++++++++++++++++++++++ src/musiclib.hpp | 15 ++++ 4 files changed, 204 insertions(+), 213 deletions(-) delete mode 100644 src/Scratch.cpp create mode 100644 src/musiclib.cpp create mode 100644 src/musiclib.hpp diff --git a/src/ChordCV.cpp b/src/ChordCV.cpp index 531985d..8898967 100644 --- a/src/ChordCV.cpp +++ b/src/ChordCV.cpp @@ -1,5 +1,5 @@ #include "plugin.hpp" - +#include "musiclib.hpp" struct ChordCV : Module { enum ParamIds { @@ -48,40 +48,8 @@ struct ChordCV : Module { void process(const ProcessArgs& args) override; }; -inline float note_to_voltage(float &v) { - float octave = floor(v / 12.0) - 4.0; - float semi = round((int)v % 12); - - return 1.0*octave + semi/12.0; -} - -inline float voltage_to_note(float &value) { - float octave = round(value); - float rest = value - 1.0*octave; - float semi = round( rest*12.0 ); - return semi; -} - -inline int voltage_to_note_int(float &value) { - float octave = round(value); - float rest = value - 1.0*octave; - int semi = (int)round( rest*12.0 ); - if(semi < 0) semi += 12; - return semi; -} - void ChordCV::process(const ProcessArgs &args){ - int degrees[9][3] = { - {4,7,0}, //Major - {3,7,0}, //Minor - {4,7,10}, //Dominant 7 - {3,7,10}, //Minor 7 - {4,7,11}, //Major 7 - {2,7,0}, //sus2 - {5,7,0}, //sus4 - {3,6,0}, //dim - {4,8,0} //aug - }; + float value = params[ROOT_PARAM].getValue(); if(inputs[ROOT_INPUT].isConnected()){ value = inputs[ROOT_INPUT].getVoltage(); @@ -112,115 +80,27 @@ void ChordCV::process(const ProcessArgs &args){ voicing = (int)clamp(round(inputs[VOICING_PARAM].getVoltage()),0.0f,4.0f); } + int root_note = (octave + 4) * 12 + (int)semi; + //Make the chord - int * chord = degrees[chord_type]; - - float root_note = (octave + 4.0) * 12.0 + semi; - float third_note = root_note + (float)chord[0]; - float fifth_note = root_note + (float)chord[1]; - float seventh_note = root_note + (float)chord[2]; - - float root_v = note_to_voltage(root_note); - float third_v = note_to_voltage(third_note); - float fifth_v = note_to_voltage(fifth_note); - float seventh_v=0.0; - if(chord[2] == 0){ - if(inversion == 3){ - inversion = 2; - } - if(inversion == 1){ - root_v += 1.0; - float v = root_v; - root_v = third_v; - third_v = fifth_v; - fifth_v = v; - } - if(inversion == 2){ - root_v += 1.0; - third_v += 1.0; - float v = root_v; - root_v = fifth_v; - fifth_v = third_v; - third_v = v; - } + struct chord c = get_chord(root_note,chord_type,inversion,voicing); - if(voicing == 1){ - root_v -= 1.0; - } - if(voicing == 2){ - root_v -= 1.0; - fifth_v -= 1.0; - } - if(voicing == 3 || voicing == 4){ - root_v -= 1.0; - third_v += 1.0; - } + if(inverted){ + bass_note = c.notes[0] % 12; + } - bass_note = voltage_to_note_int(root_v); - seventh_v = root_v + 1.0; - outputs[POLY_OUTPUT].setChannels(3); + outputs[CV_OUTPUTS + 0].setVoltage(note_to_voltage(c.notes[0])); + outputs[CV_OUTPUTS + 1].setVoltage(note_to_voltage(c.notes[1])); + outputs[CV_OUTPUTS + 2].setVoltage(note_to_voltage(c.notes[2])); + if(c.num_notes == 3){ + outputs[CV_OUTPUTS + 3].setVoltage(note_to_voltage(c.notes[0] + 12)); }else{ - seventh_v = note_to_voltage(seventh_note); - if(inversion == 1){ - root_v += 1.0; - float v = root_v; - root_v = third_v; - third_v = fifth_v; - fifth_v = seventh_v; - seventh_v = v; - } - if(inversion == 2){ - root_v += 1.0; - third_v += 1.0; - float v = third_v; - float r = root_v; - root_v = fifth_v; - fifth_v = r; - third_v = seventh_v; - seventh_v = v; - } - if(inversion == 3){ - root_v += 1.0; - third_v += 1.0; - fifth_v += 1.0; - float v = fifth_v; - float r = root_v; - root_v = seventh_v; - seventh_v = v; - fifth_v = third_v; - third_v = r; - } - - if(voicing == 1){ - root_v -= 1.0; - } - if(voicing == 2){ - root_v -= 1.0; - fifth_v -= 1.0; - } - if(voicing == 3){ - root_v -= 1.0; - third_v += 1.0; - } - if(voicing == 4){ - root_v -= 1.0; - seventh_v -= 1.0; - } - - bass_note = voltage_to_note_int(root_v); - outputs[POLY_OUTPUT].setChannels(4); + outputs[CV_OUTPUTS + 3].setVoltage(note_to_voltage(c.notes[3])); } - outputs[CV_OUTPUTS + 0].setVoltage(root_v); - outputs[CV_OUTPUTS + 1].setVoltage(third_v); - outputs[CV_OUTPUTS + 2].setVoltage(fifth_v); - outputs[CV_OUTPUTS + 3].setVoltage(seventh_v); - - outputs[POLY_OUTPUT].setVoltage(root_v,0); - outputs[POLY_OUTPUT].setVoltage(third_v,1); - outputs[POLY_OUTPUT].setVoltage(fifth_v,2); - if(chord[2] > 0){ - outputs[POLY_OUTPUT].setVoltage(seventh_v,3); + outputs[POLY_OUTPUT].setChannels(c.num_notes); + for(int t=0; twindow->loadFont(asset::plugin(pluginInstance, "res/fonts/PixelOperator.ttf")); } - void chordName() { - if (module != NULL){ - static const char * noteNames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; - static const char * chordTypes[] = { - "", - "m", - "7", - "m7", - "maj7", - "sus2", - "sus4", - "dim", - "+" - }; - - int note = module->root_semi; - int type = module->chord_type; - char inv[4]; - if(module->inverted){ - sprintf(inv,"/%s",noteNames[module->bass_note]); - } - sprintf(text, "%s%s%s", noteNames[note], chordTypes[type], inv); - - }else{ - snprintf(text, 9, " "); - } - } - void draw(const DrawArgs &args) override { NVGcolor textColor = prepareDisplay(args.vg, &box, 22); nvgFontFaceId(args.vg, font->handle); @@ -274,7 +126,13 @@ struct ChordCVWidget : ModuleWidget { Vec textPos = Vec(box.size.x/2, 21.0f); nvgFillColor(args.vg, textColor); - chordName(); + + if (module != NULL){ + get_chord_name(module->root_semi,module->chord_type,module->inverted,module->bass_note,text); + }else{ + snprintf(text, 9, " "); + } + nvgText(args.vg, textPos.x, textPos.y, text, NULL); } diff --git a/src/Scratch.cpp b/src/Scratch.cpp deleted file mode 100644 index 2e90d5d..0000000 --- a/src/Scratch.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "plugin.hpp" - - -struct Scratch : Module { - enum ParamIds { - ROOT_PARAM_PARAM, - NUM_PARAMS - }; - enum InputIds { - NUM_INPUTS - }; - enum OutputIds { - CVOUT1_OUTPUT_OUTPUT, - NUM_OUTPUTS - }; - enum LightIds { - NUM_LIGHTS - }; - - Scratch() { - config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - configParam(ROOT_PARAM_PARAM, 0.f, 1.f, 0.f, ""); - } - - void process(const ProcessArgs& args) override { - } -}; - - -struct ScratchWidget : ModuleWidget { - ScratchWidget(Scratch* module) { - setModule(module); - setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Scratch.svg"))); - - addChild(createWidget(Vec(RACK_GRID_WIDTH, 0))); - addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); - addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - - addParam(createParamCentered(mm2px(Vec(20.32, 25.639)), module, Scratch::ROOT_PARAM_PARAM)); - - addOutput(createOutputCentered(mm2px(Vec(20.32, 119.596)), module, Scratch::CVOUT1_OUTPUT_OUTPUT)); - } -}; - - -Model* modelScratch = createModel("Scratch"); \ No newline at end of file diff --git a/src/musiclib.cpp b/src/musiclib.cpp new file mode 100644 index 0000000..fed1e5a --- /dev/null +++ b/src/musiclib.cpp @@ -0,0 +1,165 @@ +#include +#include +#include "musiclib.hpp" + +//Note <-> Voltage conversion +float note_to_voltage(int v) { + float octave = floor((float)v / 12.0) - 4.0; + float semi = round(v % 12); + + return 1.0*octave + semi/12.0; +} + +float voltage_to_note(float value) { + float octave = round(value); + float rest = value - 1.0*octave; + float semi = round( rest*12.0 ); + return semi; +} + +int voltage_to_note_int(float value) { + float octave = round(value); + float rest = value - 1.0*octave; + int semi = (int)round( rest*12.0 ); + if(semi < 0) semi += 12; + return semi; +} + + + +//Chords +static const int CHORD_DEGREES[9][3] = { + {4,7,0}, //Major + {3,7,0}, //Minor + {4,7,10}, //Dominant 7 + {3,7,10}, //Minor 7 + {4,7,11}, //Major 7 + {2,7,0}, //sus2 + {5,7,0}, //sus4 + {3,6,0}, //dim + {4,8,0} //aug +}; + +struct chord get_chord(int root_note, int type, int inversion, int voicing){ + struct chord return_chord; + + const int *degrees = CHORD_DEGREES[type]; + + int third_note = root_note + degrees[0]; + int fifth_note = root_note + degrees[1]; + int seventh_note = root_note + degrees[2]; + + if(degrees[2] == 0){ //Has 3 notes + if(inversion == 3){ + inversion = 2; + } + if(inversion == 1){ + root_note += 12; + int tmp = root_note; + root_note = third_note; + third_note = fifth_note; + fifth_note = tmp; + } + if(inversion == 2){ + root_note += 12; + third_note += 12; + int tmp = root_note; + root_note = fifth_note; + third_note = fifth_note; + fifth_note = third_note; + third_note = tmp; + } + + if(voicing == 1 && root_note > 11){ + root_note -= 12; + } + if(voicing == 2 && root_note > 11){ + root_note -= 12; + fifth_note -= 12; + } + if((voicing == 3 || voicing == 4) && root_note > 11){ + root_note -= 12; + third_note += 12; + } + return_chord.notes[0] = root_note; + return_chord.notes[1] = third_note; + return_chord.notes[2] = fifth_note; + return_chord.num_notes = 3; + + }else{ //Has 4 notes + if(inversion == 1){ + root_note += 12; + int tmp = root_note; + root_note = third_note; + third_note = fifth_note; + fifth_note = seventh_note; + seventh_note = tmp; + } + if(inversion == 2){ + root_note += 12; + third_note += 12; + int tmp = third_note; + int r = root_note; + root_note = fifth_note; + fifth_note = r; + third_note = seventh_note; + seventh_note = tmp; + } + if(inversion == 3){ + root_note += 12; + third_note += 12; + fifth_note += 12; + int tmp = fifth_note; + int r = root_note; + root_note = seventh_note; + seventh_note = tmp; + fifth_note = third_note; + third_note = r; + } + + if(voicing == 1 && root_note > 11){ + root_note -= 12; + } + if(voicing == 2 && root_note > 11){ + root_note -= 12; + fifth_note -= 12; + } + if(voicing == 3 && root_note > 11){ + root_note -= 12; + third_note += 12; + } + if(voicing == 4 && root_note > 11){ + root_note -= 12; + seventh_note -= 12; + } + return_chord.notes[0] = root_note; + return_chord.notes[1] = third_note; + return_chord.notes[2] = fifth_note; + return_chord.notes[3] = seventh_note; + return_chord.num_notes = 4; + } + return return_chord; +} + +static const char * noteNames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; +static const char * chordTypes[] = { + "", + "m", + "7", + "m7", + "maj7", + "sus2", + "sus4", + "dim", + "+" +}; + +void get_chord_name(int root_semi, int chord_type, bool inverted, int bass_note, char* text) { + int note = root_semi; + int type = chord_type; + char inv[4]; + if(inverted){ + sprintf(inv,"/%s",noteNames[bass_note]); + } + sprintf(text, "%s%s%s", noteNames[note], chordTypes[type], inv); +} diff --git a/src/musiclib.hpp b/src/musiclib.hpp new file mode 100644 index 0000000..361477a --- /dev/null +++ b/src/musiclib.hpp @@ -0,0 +1,15 @@ +#pragma once + +//Note <-> Voltage conversion +float note_to_voltage(int v); +float voltage_to_note(float value); +int voltage_to_note_int(float value); + +//Chords +struct chord { + int num_notes; + int notes[4]; +}; + +struct chord get_chord(int root_note, int type, int inversion, int voicing); +void get_chord_name(int root_semi, int chord_type, bool inverted, int bass_note, char* text);