Advertisement
Guest User

Untitled

a guest
Aug 21st, 2019
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.12 KB | None | 0 0
  1. #include <vector>
  2. #include <set>
  3. #include <array>
  4. #include <numeric>
  5. #include <algorithm>
  6. #include <iostream>
  7. #include <math.h>
  8.  
  9. // Because C++ mod is really remainder not mod
  10. int mod(int a, int b) { return a % b + b * (a < 0); }
  11. int diatonic_to_chromatic(int d, int a = 0) { return d * 2 - (d / 7) * 2 - (mod(d, 7) > 2) + a; }
  12.  
  13. struct Note
  14. {
  15. int pitch = 0, acc = 0;
  16. std::array<unsigned, 12> chromagram = {};
  17.  
  18. int diatonic() { return (pitch - acc) / 2 + ((pitch - acc) / 12) + (mod((pitch - acc), 12) > 4); }
  19. void set_acc_by_diatonic(int step)
  20. {
  21. acc = mod(pitch, 12) - diatonic_to_chromatic(mod(step, 7));
  22. acc -= 12 * (acc > 6);
  23. }
  24. };
  25.  
  26. void pitchSpell(std::vector<Note>& notes, int kPre = 10, int kPost = 42)
  27. {
  28. for(int i = 0; i < notes.size(); i++)
  29. for(int j = std::max(0, i - kPre); j < std::min((int)notes.size(), i + kPost); j++)
  30. ++notes[i].chromagram[notes[j].pitch % 12];
  31.  
  32. std::array<int, 12> morphInt = {0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6};
  33. std::array<int, 12> initMorph = {0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6};
  34. int c0 = notes[0].pitch % 12;
  35. int m0 = initMorph[c0];
  36. std::array<int, 12> tonicMorphForTonicChroma;
  37. for(int ct = 0; ct < 12; ct++)
  38. tonicMorphForTonicChroma[ct] = mod(m0 - morphInt[mod(c0-ct, 12)], 7);
  39.  
  40. for(auto& note : notes)
  41. {
  42. std::vector<std::set<int>> chromas(7);
  43. for(int ct = 0; ct < 12; ct++)
  44. chromas[mod(morphInt[mod(note.pitch % 12 - ct, 12)] + tonicMorphForTonicChroma[ct], 7)].insert(ct);
  45.  
  46. int maxStrength = -1;
  47. int maxM = 0;
  48. for(int m = 0; m < 7; m++)
  49. {
  50. int strength = 0;
  51. for(int tonicChroma : chromas[m])
  52. strength += note.chromagram[tonicChroma];
  53.  
  54. maxM = strength > maxStrength ? m : maxM;
  55. maxStrength = std::max(strength, maxStrength);
  56. }
  57.  
  58. note.set_acc_by_diatonic(maxM);
  59. std::cout << note.pitch << " " << maxM << " " << note.acc << std::endl;
  60. }
  61. }
  62.  
  63. int main(int argc, char** argv)
  64. {
  65. std::vector<int> pitches = {0, 0, 7, 7, 9, 9, 7, 7, 5, 5, 4 ,4 ,3, 3, 0, 0};
  66. std::vector<Note> notes;
  67. for(auto p : pitches) notes.push_back({p, 0});
  68. pitchSpell(notes);
  69. for(auto n : notes)
  70. {
  71. std::cout << "CDEFGAB"[(n.diatonic() + 7*100) % 7] << "-b #+"[n.acc + 2] << ' ';
  72. }
  73. return 0;
  74. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement