You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.1KB

  1. #include "rack.hpp"
  2. using namespace rack;
  3. namespace rack_plugin_Alikins {
  4. // TODO: mv to header
  5. // float A440_VOLTAGE = 4.75f;
  6. // https://vcvrack.com/manual/VoltageStandards.html#pitch-and-frequencies
  7. // 0v = C4 = 261.626f
  8. float VCO_BASELINE_VOLTAGE = 0.0f;
  9. float VCO_BASELINE_FREQ = 261.626f;
  10. float VCO_BASELINE_NOTE_OCTAVE_OFFSET = 4.0f;
  11. //float VCO_BASELINE_VOLTAGE = 4.75f;
  12. //float VCO_BASELINE_FREQ = 440.0f;
  13. int A440_MIDI_NUMBER = 69;
  14. // bogaudio lfo, defaults to 0v == 16.35f
  15. // float LFO_BASELINE_FREQ = 16.35f;
  16. // https://vcvrack.com/manual/VoltageStandards.html#pitch-and-frequencies
  17. float LFO_BASELINE_VOLTAGE = 0.0f;
  18. float LFO_BASELINE_FREQ = 2.0f;
  19. // FIXME: can/should be inline
  20. // FIXME: likely should be a NoteInfo type/struct/object
  21. // These are assuming
  22. // 440.0 hz == A4 == 0.75v (A440)
  23. // 261.626f == C4 == 0v
  24. float freq_to_cv(float freq) {
  25. float volts = log2f(freq / VCO_BASELINE_FREQ * powf(2.0f, VCO_BASELINE_VOLTAGE));
  26. // debug("freq_to_vc freq=%f -> vc volts=%f (vco_baseline_freq=%f)",
  27. // freq, volts, VCO_BASELINE_VOLTAGE);
  28. return volts;
  29. }
  30. float lfo_freq_to_cv(float lfo_freq) {
  31. float volts = log2f(lfo_freq / LFO_BASELINE_FREQ * powf(2.0f, LFO_BASELINE_VOLTAGE));
  32. // debug("lfo_freq_to_cv: lfo_freq=%f volts=%f LFO_BASELINE_VOLTAGE=%f",
  33. // lfo_freq, volts, LFO_BASELINE_VOLTAGE);
  34. return volts;
  35. }
  36. float cv_to_freq(float volts) {
  37. float freq = VCO_BASELINE_FREQ / powf(2.0f, VCO_BASELINE_VOLTAGE) * powf(2.0f, volts);
  38. // debug("cv_to_freq: cv volts=%f -> freq=%f (vco_baseline_freq=%f)",
  39. // volts, freq, VCO_BASELINE_FREQ);
  40. return freq;
  41. }
  42. float lfo_cv_to_freq(float volts) {
  43. // TODO: figure out what a common LFO baseline is
  44. float freq = LFO_BASELINE_FREQ / powf(2.0f, LFO_BASELINE_VOLTAGE) * powf(2.0f, volts);
  45. // debug("lfo_cv_to_freq freq=%f volts=%f ", freq, volts);
  46. return freq;
  47. }
  48. // can return negative
  49. double volts_of_nearest_note(float volts) {
  50. double res = round( (volts * 12.0) ) / 12.0;
  51. return res;
  52. }
  53. int volts_to_note(float volts) {
  54. int res = abs(static_cast<int>( roundf( ( volts * 12.0f) ) ) ) % 12;
  55. // FIXME: ugly, sure there is a more elegant way to do this
  56. if (volts < 0.0f && res > 0) {
  57. res = 12 - res;
  58. }
  59. // debug("volts_to_note: volts=%f res=%d", volts, res);
  60. return res;
  61. }
  62. int volts_to_octave(float volts) {
  63. int octave = floor(volts) + VCO_BASELINE_NOTE_OCTAVE_OFFSET;
  64. //debug("volts_to_octaves: volts=%f -> octave=%d (offset_from_baseline=%f, v+ofb=%f)",
  65. // volts, octave, offset_from_baseline, volts+offset_from_baseline);
  66. return octave;
  67. }
  68. float volts_to_note_cents(float volts) {
  69. float nearest_note = volts_of_nearest_note(volts);
  70. double cent_volt = 1.0f / 12.0f / 100.0f;
  71. float offset_cents = (volts - nearest_note)/cent_volt;
  72. // debug("volts: %f volts_of_nearest: %f volts-volts_nearest: %f offset_cents %f",
  73. // volts, nearest_note, volts-nearest_note, offset_cents);
  74. return offset_cents;
  75. }
  76. int volts_to_midi(float volts) {
  77. int midi_note = floor(volts * 12.0f) + 21;
  78. return midi_note;
  79. }
  80. } // namespace rack_plugin_Alikins
  81. using namespace rack_plugin_Alikins;