Skip to content

Commit 41d50c0

Browse files
committed
Quantizers added to ScaleCV
1 parent 3d43989 commit 41d50c0

5 files changed

Lines changed: 110 additions & 20 deletions

File tree

Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# If RACK_DIR is not defined when calling the Makefile, default to two directories above
2-
RACK_DIR ?= /e/Projects/vcv-rack/Rack-SDK
3-
RACK_USER_DIR ?= /c/Users/Aaron\ Static/OneDrive/Documents/Rack
2+
RACK_DIR ?= ../..
43

54
# FLAGS will be passed to both the C and C++ compiler
65
FLAGS +=

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ The first 1v/oct output (and first poly channel) will always be the bass note, i
2525
If the chord is a triad (3 notes), the 4th 1v/oct output will be the bass note + 1 octave for convenience. The polyphonic output will not include this higher note.
2626

2727
## ScaleCV
28-
![ChordCV](https://i.imgur.com/GHhsEgZ.jpg "ScaleCV")
28+
![ChordCV](https://i.imgur.com/z52Qqil.jpg "ScaleCV")
2929

30-
Generates a scale and outputs a polyphonic 1v/oct signal with 7 notes.
30+
Generates a scale and outputs a polyphonic 1v/oct signal with 7 notes + quantizes the 4 monophonic inputs to that scale if provided.
3131

3232
* **Root**: Chooses the root note (1v/oct, input range -4v to 4v)
3333
* **Mode**: Chooses the scale mode (input range -4v to 4v)
34+
* **Quantizers**: 4 Quantizers that will quantize a monophonic input to the selected scale
3435

3536
## RandomNoteCV
3637
![RandomNoteCV](https://i.imgur.com/5rybov5.jpg "RandomNoteCV")

plugin.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
"slug": "ScaleCV",
2424
"name": "ScaleCV",
2525
"description": "Generates a scale",
26-
"tags": ["Polyphonic","Tuner"]
26+
"tags": ["Polyphonic","Tuner","Quantizer"]
2727
},
2828
{
2929
"slug": "RandomNoteCV",
3030
"name": "RandomNoteCV",
3131
"description": "Generates a random note when triggered",
32-
"tags": ["Polyphonic","Tuner"]
32+
"tags": ["Polyphonic","Tuner","Random"]
3333
}
3434
]
3535
}

res/ScaleCV.svg

Lines changed: 57 additions & 14 deletions
Loading

src/ScaleCV.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ struct ScaleCV : Module {
1010
enum InputIds {
1111
ROOT_INPUT,
1212
MODE_INPUT,
13+
ENUMS(QUANTIZER_INPUTS, 4),
1314
NUM_INPUTS
1415
};
1516
enum OutputIds {
1617
POLY_OUTPUT,
18+
ENUMS(QUANTIZER_OUTPUTS, 4),
1719
NUM_OUTPUTS
1820
};
1921
enum LightIds {
@@ -58,6 +60,35 @@ void ScaleCV::process(const ProcessArgs &args){
5860
//Make the scale
5961
struct scale s = get_scale(root_note, mode);
6062

63+
//Quantizers
64+
for(int t=0; t<4; t++){
65+
if(inputs[QUANTIZER_INPUTS + t].isConnected() && outputs[QUANTIZER_OUTPUTS + t].isConnected()){
66+
float in_v = inputs[QUANTIZER_INPUTS + t].getVoltage();
67+
float in_octave = round(in_v) + 4;
68+
float in_semi = voltage_to_note(in_v);
69+
float lowest_dist = 12.0f;
70+
float out_note = 0.0f;
71+
for(int i=0; i<7; i++){
72+
float note = (float)(s.notes[i] - ((octave + 4) * 12));
73+
float dist = abs(note - in_semi);
74+
if(dist < lowest_dist){
75+
out_note = note;
76+
lowest_dist = dist;
77+
}
78+
//check one octave down
79+
note -= 12;
80+
dist = abs(note - in_semi);
81+
if(dist < lowest_dist){
82+
out_note = note;
83+
lowest_dist = dist;
84+
}
85+
}
86+
out_note += in_octave * 12.0f;
87+
outputs[QUANTIZER_OUTPUTS+t].setVoltage(note_to_voltage((int)out_note));
88+
}
89+
90+
}
91+
6192
outputs[POLY_OUTPUT].setChannels(7);
6293
for(int t=0; t<7; t++){
6394
outputs[POLY_OUTPUT].setVoltage(note_to_voltage(s.notes[t]),t);
@@ -115,13 +146,29 @@ struct ScaleCVWidget : ModuleWidget {
115146

116147
const int offsetXL = 40;
117148

149+
static const int offsetX = 28;
150+
static const int posY = 190;
151+
static const int spacingY2 = 32;
152+
static const int posY1 = posY + spacingY2;
153+
static const int posY2 = posY + (spacingY2 * 2);
154+
static const int posY3 = posY + (spacingY2 * 3);
118155

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

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

162+
addInput(createInputCentered<PJ301MPort>(Vec(centerX - offsetX, posY), module, ScaleCV::QUANTIZER_INPUTS + 0));
163+
addInput(createInputCentered<PJ301MPort>(Vec(centerX - offsetX, posY1), module, ScaleCV::QUANTIZER_INPUTS + 1));
164+
addInput(createInputCentered<PJ301MPort>(Vec(centerX - offsetX, posY2), module, ScaleCV::QUANTIZER_INPUTS + 2));
165+
addInput(createInputCentered<PJ301MPort>(Vec(centerX - offsetX, posY3), module, ScaleCV::QUANTIZER_INPUTS + 3));
166+
167+
addOutput(createOutputCentered<PJ301MPort>(Vec(centerX + offsetX, posY), module, ScaleCV::QUANTIZER_OUTPUTS + 0));
168+
addOutput(createOutputCentered<PJ301MPort>(Vec(centerX + offsetX, posY1), module, ScaleCV::QUANTIZER_OUTPUTS + 1));
169+
addOutput(createOutputCentered<PJ301MPort>(Vec(centerX + offsetX, posY2), module, ScaleCV::QUANTIZER_OUTPUTS + 2));
170+
addOutput(createOutputCentered<PJ301MPort>(Vec(centerX + offsetX, posY3), module, ScaleCV::QUANTIZER_OUTPUTS + 3));
171+
125172
addOutput(createOutputCentered<PJ301MPort>(Vec(centerX, 330), module, ScaleCV::POLY_OUTPUT));
126173
}
127174
};

0 commit comments

Comments
 (0)