diff --git a/scripts/pitch_quantize_prototype.wl b/scripts/pitch_quantize_prototype.wl new file mode 100644 index 0000000..27e94d7 --- /dev/null +++ b/scripts/pitch_quantize_prototype.wl @@ -0,0 +1,122 @@ +# -1.0 == 21 => A0 +# -0.1 == 69 - 12 => A3 +# 0.0 == 69 => A4 +# 0.1 == 69 + 12 => A5 +# 0.2 == 69 + 12 => A6 +# 0.3 == 69 + 12 => A7 +# 0.4 == 69 + 12 => A8 +# 0.5 == 69 + 12 => A9 +# 0.6 == 69 + 12 => A10 +# 0.7 == 69 + 12 => A11 +# 0.7 == 69 + 12 => A12 +# 0.9 == 69 + 12 => A13 +# 1.0 == 69 + 12 => A14 +!f2note = { 69.0 + _ * 120.0 }; +!note2pitch = { 440.0 * 2.0 ^ ((_ - 69) / 12) }; + +!f2p = { 440.0 * 2.0 ^ (_ * 10.0); }; + +!pitch2note = { + 12.0 * std:num:log2[_ / 440.0] + 69.0 +}; + +!note2f = { _ / 120.0 - 0.575 }; + +!p2f = { 0.1 * std:num:log2[_ / 440.0] }; + +# ((($x as f32).max(0.01) / 440.0).log2() / 10.0) + +!in = (1.0 / 12.0) / 10.0; +std:displayln :f2note ~ f2note in; +std:displayln :note2pitch ~ note2pitch ~ f2note in; +std:displayln :f2p " "~ f2p in; +!f = f2p in; +std:displayln :pitch2note " "~ pitch2note f; +std:displayln :note2f " "~ note2f ~ pitch2note f; +std:displayln :p2f " "~ p2f f; + +# gets the index in the 24 half semitone array +!get_note_idx = { + std:num:floor ~ (_ % 0.1 + 0.1) * 240.0 +}; + +std:displayln :for674_12 ~ note2f (67.4 - 12.0); +std:displayln :for674_12 ~ get_note_idx ~ note2f (67.4 - 12.0); + +std:displayln :for675_12 ~ note2f (67.5 - 12.0); +std:displayln :for675_12 ~ get_note_idx ~ note2f (67.5 - 12.0); + +std:displayln :for68 " " ~ note2f (68.0 - 12.0); +std:displayln :for68 " " ~ get_note_idx ~ note2f (68.0 - 12.0); + +std:displayln :for679 " " ~ note2f (67.9 - 0.0); +std:displayln :for679 " " ~ get_note_idx ~ note2f (67.9 - 0.0); + +std:displayln :for69_115 ~ note2f (69.0 - 11.5); +std:displayln :for69_115 ~ get_note_idx ~ note2f (69.0 - 11.5); + +std:displayln :for69_12 "" ~ note2f (69.0 - 11.5); +std:displayln :for69_12 "" ~ get_note_idx ~ note2f (69.0 - 11.5); + +std:displayln :for69 " " ~ note2f (69.0 - 0.0); +std:displayln :for69 " " ~ get_note_idx ~ note2f (69.0 - 0.0); + +std:displayln :for69+114 ~ note2f (69.0 + 11.4); +std:displayln :for69+114 ~ get_note_idx ~ note2f (69.0 + 11.4); + + +# Taken from VCV Rack Fundamental Modules Quantizer.cpp +# Under GPL-3.0-or-later +# +# void process(const ProcessArgs& args) override { +# bool playingNotes[12] = {}; +# int channels = std::max(inputs[PITCH_INPUT].getChannels(), 1); +# +# for (int c = 0; c < channels; c++) { +# float pitch = inputs[PITCH_INPUT].getVoltage(c); +# int range = std::floor(pitch * 24); +# int octave = eucDiv(range, 24); +# range -= octave * 24; +# int note = ranges[range] + octave * 12; +# playingNotes[eucMod(note, 12)] = true; +# pitch = float(note) / 12; +# outputs[PITCH_OUTPUT].setVoltage(pitch, c); +# } +# outputs[PITCH_OUTPUT].setChannels(channels); +# std::memcpy(this->playingNotes, playingNotes, sizeof(playingNotes)); +# } +# +# void updateRanges() { +# // Check if no notes are enabled +# bool anyEnabled = false; +# for (int note = 0; note < 12; note++) { +# if (enabledNotes[note]) { +# anyEnabled = true; +# break; +# } +# } +# // Find closest notes for each range +# for (int i = 0; i < 24; i++) { // => Oversampling, for taking care of the rounding?! +# int closestNote = 0; +# int closestDist = INT_MAX; +# for (int note = -12; note <= 24; note++) { +# int dist = std::abs((i + 1) / 2 - note); +# // Ignore enabled state if no notes are enabled +# if (anyEnabled && !enabledNotes[eucMod(note, 12)]) { +# continue; +# } +# if (dist < closestDist) { +# closestNote = note; +# closestDist = dist; +# } +# else { +# // If dist increases, we won't find a better one. +# break; +# } +# } +# ranges[i] = closestNote; +# } +# } + + +#std:displayln ~ get_note_offs ~ note2f (0.1 + (4.0 / 12.0) / 10.0);