diff --git a/src/ChordCV.cpp b/src/ChordCV.cpp index 0223016..4f8f4b6 100644 --- a/src/ChordCV.cpp +++ b/src/ChordCV.cpp @@ -108,7 +108,7 @@ void ChordCV::process(const ProcessArgs &args){ struct ChordCVWidget : ModuleWidget { struct ChordDisplayWidget : TransparentWidget { ChordCV* module; - char text[10]; + char text[13]; ChordDisplayWidget(Vec _pos, Vec _size, ChordCV* _module) { box.size = _size; @@ -130,7 +130,7 @@ struct ChordCVWidget : ModuleWidget { if (module != NULL){ get_chord_name(module->root_semi,module->chord_type,module->inverted,module->bass_note,text); }else{ - snprintf(text, 9, " "); + snprintf(text, 13, " "); } nvgText(args.vg, textPos.x, textPos.y, text, NULL); diff --git a/src/DiatonicCV.cpp b/src/DiatonicCV.cpp index 34f67ce..1a7a75b 100644 --- a/src/DiatonicCV.cpp +++ b/src/DiatonicCV.cpp @@ -73,7 +73,7 @@ void DiatonicCV::process(const ProcessArgs &args){ for (int c = 0; c < 16; c++) { float v = inputs[POLY_INPUT].getVoltage(c); polyNotes_v[c] = v; - polyNotes[c] = voltage_to_note_int(v); + polyNotes[c] = voltage_to_note_with_octave(v); } //sort the notes in ascending order std::sort(std::begin(polyNotes), polyNotes + polyChannels); @@ -85,6 +85,14 @@ void DiatonicCV::process(const ProcessArgs &args){ } } + //remove octave + if(polyChannels > 0){ + int root_octave = (int)floor((float)polyNotes[0] / 12.0f); + for (int c = 0; c < polyChannels; c++) { + polyNotes[c] -= root_octave * 12; + } + } + float octave_v = params[OCTAVE_PARAM].getValue(); if(inputs[OCTAVE_INPUT].isConnected()){ octave_v = inputs[OCTAVE_INPUT].getVoltage(); @@ -94,30 +102,28 @@ void DiatonicCV::process(const ProcessArgs &args){ float chord_v = params[CHORD_PARAM].getValue(); if(inputs[CHORD_INPUT].isConnected()){ chord_v = inputs[CHORD_INPUT].getVoltage(); - if(chord_v < 0.0f) chord_v = 0.0f; - if(chord_v > 7.0f) chord_v = 7.0f; } - chord = (int)round(chord_v); + chord = (int)round(clamp(chord_v, 0.0f, 6.0f)); float type_v = params[TYPE_PARAM].getValue(); if(inputs[TYPE_INPUT].isConnected()){ type_v = inputs[TYPE_INPUT].getVoltage(); - if(type_v < 0.0f) type_v = 0.0f; - if(type_v > 3.0f) type_v = 3.0f; } - chord_type = (int)round(type_v); + chord_type = (int)round(clamp(type_v, 0.0f, 2.0f)); //inversion - inversion = (int)round(params[INVERSION_PARAM].getValue()); - if(inputs[INVERSION_PARAM].isConnected()){ - inversion = (int)clamp(round(inputs[INVERSION_PARAM].getVoltage()),0.0f,3.0f); + float inversion_v = params[INVERSION_PARAM].getValue(); + if(inputs[INVERSION_INPUT].isConnected()){ + inversion_v = inputs[INVERSION_INPUT].getVoltage(); } + inversion = (int)round(clamp(inversion_v, 0.0f, 4.0f)); //voicing - voicing = (int)round(params[VOICING_PARAM].getValue()); - if(inputs[VOICING_PARAM].isConnected()){ - voicing = (int)clamp(round(inputs[VOICING_PARAM].getVoltage()),0.0f,4.0f); + float voicing_v = params[VOICING_PARAM].getValue(); + if(inputs[VOICING_INPUT].isConnected()){ + voicing_v = inputs[VOICING_INPUT].getVoltage(); } + voicing = (int)round(clamp(voicing_v, 0.0f, 4.0f)); //Make the chord playing_chord = get_diatonic_chord(polyNotes, polyChannels, octave, chord, chord_type, inversion, voicing); @@ -137,7 +143,7 @@ void DiatonicCV::process(const ProcessArgs &args){ struct DiatonicCVWidget : ModuleWidget { struct ChordDisplayWidget : TransparentWidget { DiatonicCV* module; - char text[10]; + char text[13]; ChordDisplayWidget(Vec _pos, Vec _size, DiatonicCV* _module) { box.size = _size; @@ -159,7 +165,7 @@ struct DiatonicCVWidget : ModuleWidget { if (module != NULL && module->playing_chord.num_notes > 2){ detect_chord_name_simple(module->playing_chord,text); }else{ - snprintf(text, 9, " "); + snprintf(text, 13, " "); } nvgText(args.vg, textPos.x, textPos.y, text, NULL); @@ -179,7 +185,7 @@ struct DiatonicCVWidget : ModuleWidget { const int centerX = box.size.x / 2; - ChordDisplayWidget* display = new ChordDisplayWidget(Vec(centerX, 55), Vec(76, 29), module); + ChordDisplayWidget* display = new ChordDisplayWidget(Vec(centerX, 55), Vec(box.size.x - 5, 29), module); addChild(display); addInput(createInputCentered(Vec(centerX, 95), module, DiatonicCV::POLY_INPUT)); diff --git a/src/musiclib.cpp b/src/musiclib.cpp index a2d679d..e5edf88 100644 --- a/src/musiclib.cpp +++ b/src/musiclib.cpp @@ -17,6 +17,13 @@ float voltage_to_note(float value) { return semi; } +int voltage_to_note_with_octave(float value) { + float octave = round(value); + float rest = value - 1.0*octave; + int semi = (int)(octave * 12.0f) + round(rest * 12.0); + return semi; +} + int voltage_to_note_int(float value) { float octave = round(value); float rest = value - 1.0*octave; @@ -177,18 +184,12 @@ struct chord get_diatonic_chord(int* notes, int num_notes, int octave, int chord int transpose = 0; //Wrap if needed - if(index >= num_notes){ - index -= num_notes; - transpose++; - } - - //Wrap again if needed - if(index >= num_notes){ + while(index >= num_notes){ index -= num_notes; transpose++; } - if(index < num_notes){ + if(index < num_notes && index > -1){ return_chord.notes_pre[t] = (transpose * 12) + notes[index]; actual_length++; } @@ -364,13 +365,17 @@ void detect_chord_name_simple(struct chord chord, char* text){ if(intervals[0] == MAJOR_SECOND && intervals[1] == PERFECT_FOURTH) chord_type = 5; //sus2 if(intervals[0] == PERFECT_FOURTH && intervals[1] == MAJOR_SECOND) chord_type = 6; //sus4 } - } - if(chord.inversion > 0){ - int bass_note = chord.notes[0] % 12; - sprintf(text, "%s%s/%s", NOTE_NAMES[chord.notes_pre[0]], CHORD_TYPE_NAMES[chord_type], NOTE_NAMES[bass_note]); - }else{ - sprintf(text, "%s%s", NOTE_NAMES[chord.notes_pre[0]], CHORD_TYPE_NAMES[chord_type]); + int root_note = chord.notes_pre[0] % 12; + + if(chord.inversion > 0){ + int bass_note = chord.notes[0] % 12; + sprintf(text, "%s%s/%s", NOTE_NAMES[root_note], CHORD_TYPE_NAMES[chord_type], NOTE_NAMES[bass_note]); + }else{ + sprintf(text, "%s%s", NOTE_NAMES[root_note], CHORD_TYPE_NAMES[chord_type]); + } + }else{ + sprintf(text, " "); } } diff --git a/src/musiclib.hpp b/src/musiclib.hpp index ee6dcd1..946001f 100644 --- a/src/musiclib.hpp +++ b/src/musiclib.hpp @@ -7,6 +7,7 @@ using namespace rack; float note_to_voltage(int v); float voltage_to_note(float value); int voltage_to_note_int(float value); +int voltage_to_note_with_octave(float value); //DSP Stuff (credit Marc Boule / Impromptu Modular) struct Trigger : dsp::SchmittTrigger {