Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <set>
- #include <array>
- #include <numeric>
- #include <algorithm>
- #include <iostream>
- #include <math.h>
- // Because C++ mod is really remainder not mod
- int mod(int a, int b) { return a % b + b * (a < 0); }
- int diatonic_to_chromatic(int d, int a = 0) { return d * 2 - (d / 7) * 2 - (mod(d, 7) > 2) + a; }
- struct Note
- {
- int pitch = 0, acc = 0;
- std::array<unsigned, 12> chromagram = {};
- int diatonic() { return (pitch - acc) / 2 + ((pitch - acc) / 12) + (mod((pitch - acc), 12) > 4); }
- void set_acc_by_diatonic(int step)
- {
- acc = mod(pitch, 12) - diatonic_to_chromatic(mod(step, 7));
- acc -= 12 * (acc > 6);
- }
- };
- void pitchSpell(std::vector<Note>& notes, int kPre = 10, int kPost = 42)
- {
- for(int i = 0; i < notes.size(); i++)
- for(int j = std::max(0, i - kPre); j < std::min((int)notes.size(), i + kPost); j++)
- ++notes[i].chromagram[notes[j].pitch % 12];
- std::array<int, 12> morphInt = {0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6};
- std::array<int, 12> initMorph = {0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6};
- int c0 = notes[0].pitch % 12;
- int m0 = initMorph[c0];
- std::array<int, 12> tonicMorphForTonicChroma;
- for(int ct = 0; ct < 12; ct++)
- tonicMorphForTonicChroma[ct] = mod(m0 - morphInt[mod(c0-ct, 12)], 7);
- for(auto& note : notes)
- {
- std::vector<std::set<int>> chromas(7);
- for(int ct = 0; ct < 12; ct++)
- chromas[mod(morphInt[mod(note.pitch % 12 - ct, 12)] + tonicMorphForTonicChroma[ct], 7)].insert(ct);
- int maxStrength = -1;
- int maxM = 0;
- for(int m = 0; m < 7; m++)
- {
- int strength = 0;
- for(int tonicChroma : chromas[m])
- strength += note.chromagram[tonicChroma];
- maxM = strength > maxStrength ? m : maxM;
- maxStrength = std::max(strength, maxStrength);
- }
- note.set_acc_by_diatonic(maxM);
- std::cout << note.pitch << " " << maxM << " " << note.acc << std::endl;
- }
- }
- int main(int argc, char** argv)
- {
- std::vector<int> pitches = {0, 0, 7, 7, 9, 9, 7, 7, 5, 5, 4 ,4 ,3, 3, 0, 0};
- std::vector<Note> notes;
- for(auto p : pitches) notes.push_back({p, 0});
- pitchSpell(notes);
- for(auto n : notes)
- {
- std::cout << "CDEFGAB"[(n.diatonic() + 7*100) % 7] << "-b #+"[n.acc + 2] << ' ';
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement