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.

53 lines
1.1KB

  1. #pragma once
  2. #include <utility>
  3. class PitchUtils
  4. {
  5. public:
  6. static constexpr float semitone = 1.f / 12.f; // one semitone is a 1/12 volt
  7. static constexpr float octave = 1.f;
  8. static std::pair<int, int> cvToPitch(float cv);
  9. static int cvToSemitone(float cv);
  10. static float pitchToCV(int octave, int semi);
  11. static bool isAccidental(float cv);
  12. };
  13. inline std::pair<int, int> PitchUtils::cvToPitch(float cv)
  14. {
  15. // VCV 0 is C4
  16. int octave = int(std::floor(cv));
  17. float remainder = cv - octave;
  18. octave += 4;
  19. float s = remainder * 12;
  20. int semi = int(std::round(s));
  21. return std::pair<int, int>(octave, semi);
  22. }
  23. inline int PitchUtils::cvToSemitone(float cv)
  24. {
  25. auto p = cvToPitch(cv);
  26. return p.first * 12 + p.second;
  27. }
  28. inline float PitchUtils::pitchToCV(int octave, int semi)
  29. {
  30. return float(octave - 4) + semi * semitone;
  31. }
  32. inline bool PitchUtils::isAccidental(float cv)
  33. {
  34. int semi = cvToPitch(cv).second;
  35. bool ret = false;
  36. switch (semi) {
  37. case 1:
  38. case 3:
  39. case 6:
  40. case 8:
  41. case 10:
  42. ret = true;
  43. break;
  44. }
  45. return ret;
  46. }