Skip to content

Commit

Permalink
Add ScaleCV module
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronstatic committed Oct 29, 2021
1 parent 2387aee commit 4f06ee3
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 24 deletions.
42 changes: 24 additions & 18 deletions plugin.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
{
"slug": "AaronStatic",
"name": "Aaron Static",
"version": "2.0.0",
"license": "MIT",
"brand": "Aaron Static",
"author": "Aaron Static",
"authorEmail": "aaronstatic@gmail.com",
"authorUrl": "https://github.com/aaronstatic/",
"pluginUrl": "https://github.com/aaronstatic/AaronStatic_modules",
"manualUrl": "https://github.com/aaronstatic/AaronStatic_modules",
"sourceUrl": "https://github.com/aaronstatic/AaronStatic_modules",
"donateUrl": "https://paypal.me/AaronStaticAU",
"changelogUrl": "",
"modules": [
"slug": "AaronStatic",
"name": "Aaron Static",
"version": "2.0.0",
"license": "MIT",
"brand": "Aaron Static",
"author": "Aaron Static",
"authorEmail": "aaronstatic@gmail.com",
"authorUrl": "https://github.com/aaronstatic/",
"pluginUrl": "https://github.com/aaronstatic/AaronStatic_modules",
"manualUrl": "https://github.com/aaronstatic/AaronStatic_modules",
"sourceUrl": "https://github.com/aaronstatic/AaronStatic_modules",
"donateUrl": "https://paypal.me/AaronStaticAU",
"changelogUrl": "",
"modules": [
{
"slug": "ChordCV",
"name": "ChordCV",
"description": "Generates a chord",
"tags": ["Polyphonic","Tuner"]
"slug": "ChordCV",
"name": "ChordCV",
"description": "Generates a chord",
"tags": ["Polyphonic","Tuner"]
},
{
"slug": "ScaleCV",
"name": "ScaleCV",
"description": "Generates a scale",
"tags": ["Polyphonic","Tuner"]
}
]
}
132 changes: 132 additions & 0 deletions res/ScaleCV.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
129 changes: 129 additions & 0 deletions src/ScaleCV.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include "plugin.hpp"
#include "musiclib.hpp"

struct ScaleCV : Module {
enum ParamIds {
ROOT_PARAM,
MODE_PARAM,
NUM_PARAMS
};
enum InputIds {
ROOT_INPUT,
MODE_INPUT,
NUM_INPUTS
};
enum OutputIds {
POLY_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

int root_semi = 0;
int mode = 0;

ScaleCV() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(ROOT_PARAM, -4.0, 4.0, 0.0, "Root Note");
configParam(MODE_PARAM, -4.0, 4.0, -4.0, "Mode");

configInput(ROOT_INPUT, "1V/oct pitch");
configInput(MODE_INPUT, "Mode");

configOutput(POLY_OUTPUT, "Polyphonic");
}

void process(const ProcessArgs& args) override;
};

void ScaleCV::process(const ProcessArgs &args){
float value = params[ROOT_PARAM].getValue();
if(inputs[ROOT_INPUT].isConnected()){
value = inputs[ROOT_INPUT].getVoltage();
}
float mode_val = params[MODE_PARAM].getValue();
if(inputs[MODE_INPUT].isConnected()){
mode_val = inputs[MODE_INPUT].getVoltage();
}
mode_val = clamp(mode_val,-4.0f, 2.0f);
mode = (int)floor(mode_val + 4.0f);

//quantize root note
float octave = round(value);
float semi = voltage_to_note(value);
root_semi = voltage_to_note_int(value);
int root_note = (octave + 4) * 12 + (int)semi;

//Make the scale
struct scale s = get_scale(root_note, mode);

outputs[POLY_OUTPUT].setChannels(8);
for(int t=0; t<8; t++){
outputs[POLY_OUTPUT].setVoltage(note_to_voltage(s.notes[t]),t);
}
}


struct ScaleCVWidget : ModuleWidget {
struct ChordDisplayWidget : TransparentWidget {
ScaleCV* module;
std::shared_ptr<Font> font;
char text[13];

ChordDisplayWidget(Vec _pos, Vec _size, ScaleCV* _module) {
box.size = _size;
box.pos = _pos.minus(_size.div(2));
module = _module;
font = APP->window->loadFont(asset::plugin(pluginInstance, "res/fonts/PixelOperator.ttf"));
}

void draw(const DrawArgs &args) override {
NVGcolor textColor = prepareDisplay(args.vg, &box, 22);
nvgFontFaceId(args.vg, font->handle);
nvgTextLetterSpacing(args.vg, -1.5);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER);

Vec textPos = Vec(box.size.x/2, 21.0f);
nvgFillColor(args.vg, textColor);

if (module != NULL){
get_scale_name(module->root_semi,module->mode,text);
}else{
snprintf(text, 13, " ");
}

nvgText(args.vg, textPos.x, textPos.y, text, NULL);
}

};

ScaleCVWidget(ScaleCV* module) {
setModule(module);
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/ScaleCV.svg")));

addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

const int centerX = box.size.x / 2;

ChordDisplayWidget* display = new ChordDisplayWidget(Vec(centerX, 55), Vec(box.size.x - 5, 29), module);
addChild(display);

const int offsetXL = 40;


addParam(createParamCentered<Rogan2PWhite>(Vec(centerX,95), module, ScaleCV::ROOT_PARAM));
addInput(createInputCentered<PJ301MPort>(Vec(centerX - offsetXL, 95), module, ScaleCV::ROOT_INPUT));

addParam(createParamCentered<Rogan2PWhite>(Vec(centerX,140), module, ScaleCV::MODE_PARAM));
addInput(createInputCentered<PJ301MPort>(Vec(centerX - offsetXL, 140), module, ScaleCV::MODE_INPUT));

addOutput(createOutputCentered<PJ301MPort>(Vec(centerX, 330), module, ScaleCV::POLY_OUTPUT));
}
};


Model* modelScaleCV = createModel<ScaleCV, ScaleCVWidget>("ScaleCV");
51 changes: 45 additions & 6 deletions src/musiclib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ struct chord get_chord(int root_note, int type, int inversion, int voicing){
return return_chord;
}

static const char * noteNames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
static const char * chordTypes[] = {
static const char * NOTE_NAMES[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
static const char * CHORD_TYPE_NAMES[] = {
"",
"m",
"7",
Expand All @@ -155,11 +155,50 @@ static const char * chordTypes[] = {
};

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(inv,"/%s",NOTE_NAMES[bass_note]);
}
sprintf(text, "%s%s%s", noteNames[note], chordTypes[type], inv);
sprintf(text, "%s%s%s", NOTE_NAMES[root_semi], CHORD_TYPE_NAMES[chord_type], inv);
}

//Scales
static const char * MODE_NAMES[] = {
"",
" Dorian",
" Phrygian",
" Lydian",
" Mixolydian",
" Minor",
" Locrian"
};

void get_scale_name(int root_semi, int mode, char* text) {
sprintf(text, "%s%s", NOTE_NAMES[root_semi], MODE_NAMES[mode]);
}

static const int MODE_DEGREES[7][7] = {
{2,2,1,2,2,2,1}, //Major (Ionian)
{2,1,2,2,2,1,2}, //Dorian
{1,2,2,2,1,2,2}, //Phrygian
{2,2,2,1,2,2,1}, //Lydian
{2,2,1,2,2,1,2}, //Mixolydian
{2,1,2,2,1,2,2}, //Minor (Aeolian)
{1,2,2,1,2,2,2}, //Locrian
};

struct scale get_scale(int root_note, int mode){
struct scale return_scale;

const int *degrees = MODE_DEGREES[mode];

return_scale.notes[0] = root_note;
int current_note = root_note;

int t;
for(t=1; t<8; t++){
current_note += degrees[t-1];
return_scale.notes[t] = current_note;
}
return return_scale;
}
Loading

0 comments on commit 4f06ee3

Please sign in to comment.