-
-
Save GanaramInukshuk/5b59543eb13cd5af74a340690e90441a to your computer and use it in GitHub Desktop.
This is the original mosfinder program that I written in C++.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <iomanip> | |
#include <vector> | |
#include <algorithm> | |
#include <string> | |
#include <set> | |
typedef std::vector<int> MosScale; | |
std::vector<MosScale> GetScaleSequence(int lg_gen, int sm_gen, int period); | |
MosScale GetChildScale(const MosScale& s); | |
int GetLargeStep(const MosScale& s); | |
int GetSmallStep(const MosScale& s); | |
std::string GetTamnamsName(int l, int s); | |
void PrintScale(const MosScale& s); | |
int main() { | |
int edo = 50; | |
// A set of factors that the ed can divide into | |
std::set<int> factors; | |
std::cout << "--------------------------------------------------------\n"; | |
std::cout << "Single-Period Moment-of-Symmetry Scales\n"; | |
std::cout << "--------------------------------------------------------\n\n"; | |
for (int i = edo - 1; i > (edo + 1)/2; i--) { | |
int lg_gen = i; | |
int sm_gen = edo - i; | |
std::vector<MosScale> scale_sequence = GetScaleSequence(lg_gen, sm_gen, 1); | |
std::cout << "Generators: " << lg_gen << "\\" << edo << " and " << sm_gen << "\\" << edo << std::endl; | |
std::cout << "Number of scales with generator pair: " << scale_sequence.size() << std::endl; | |
for (int i = 0; i < scale_sequence.size(); i++) { | |
PrintScale(scale_sequence[i]); | |
} | |
// The last scale in the step sequence is an equal division of the equave | |
// meaning that all the steps are the same size. If that step size is not | |
// equal to 1, that means the ed is able to have multi-period mosses | |
// whose period is the size of that step size. | |
int ed_step_size = scale_sequence[scale_sequence.size() - 1][0]; | |
if (ed_step_size > 1) factors.insert(ed_step_size); | |
std::cout << std::endl; | |
} | |
if (!factors.empty()) { | |
for (std::set<int>::iterator i = factors.begin(); i != factors.end(); ++i) { | |
int factor = *i; | |
int multi_edo = edo / factor; | |
std::cout << "--------------------------------------------------------\n"; | |
std::cout << "Multi-Period Moment-of-Symmetry Scales (period of " << factor << ")\n"; | |
std::cout << "--------------------------------------------------------\n\n"; | |
for (int i = (multi_edo + 1) / 2; i < multi_edo; i++) { | |
int lg_gen = i; | |
int sm_gen = multi_edo - i; | |
std::vector<MosScale> multi_scale_sequence = GetScaleSequence(lg_gen, sm_gen, factor); | |
std::cout << "Generators: " << lg_gen << "\\" << edo << " and " << sm_gen << "\\" << edo << std::endl; | |
std::cout << "Number of scales with generator pair: " << multi_scale_sequence.size() << std::endl; | |
for (int i = 0; i < multi_scale_sequence.size(); i++) { | |
PrintScale(multi_scale_sequence[i]); | |
} | |
std::cout << std::endl; | |
} | |
} | |
} | |
} | |
std::vector<MosScale> GetScaleSequence(int lg_gen, int sm_gen, int period) { | |
MosScale scale = { lg_gen, sm_gen }; | |
std::vector<MosScale> scale_sequence; | |
int sm_step = sm_gen; | |
int lg_step = lg_gen; | |
if (period > 1) { | |
for (int i = 0; i < period - 1; i++) { | |
scale.push_back(lg_gen); | |
scale.push_back(sm_gen); | |
} | |
} | |
do { | |
sm_step = GetSmallStep(scale); | |
lg_step = GetLargeStep(scale); | |
scale_sequence.push_back(scale); | |
scale = GetChildScale(scale); | |
} while (sm_step != lg_step); | |
return scale_sequence; | |
} | |
MosScale GetChildScale(const MosScale& s) { | |
int sm_step = *min_element(s.begin(), s.end()); | |
int lg_step = *max_element(s.begin(), s.end()); | |
int chroma = lg_step - sm_step; // L - s | |
int next_lg_step = 0; | |
int next_sm_step = 0; | |
int first_step = s[0]; | |
int last_step = s[s.size() - 1]; | |
MosScale next_scale; | |
if (sm_step < chroma) { | |
// s' = s and L' = L - s | |
next_lg_step = chroma; | |
next_sm_step = sm_step; | |
if (first_step == lg_step && last_step == sm_step) { | |
for (int i = 0; i < s.size(); i++) { | |
if (s[i] == lg_step) { | |
next_scale.push_back(next_lg_step); | |
next_scale.push_back(next_sm_step); | |
} else if (s[i] == sm_step) { | |
next_scale.push_back(next_sm_step); | |
} | |
} | |
} else { | |
for (int i = 0; i < s.size(); i++) { | |
if (s[i] == lg_step) { | |
next_scale.push_back(next_sm_step); | |
next_scale.push_back(next_lg_step); | |
} else if (s[i] == sm_step) { | |
next_scale.push_back(next_sm_step); | |
} | |
} | |
} | |
} else { | |
// s' = L-s and L' = s | |
next_lg_step = sm_step; | |
next_sm_step = chroma; | |
if (first_step == lg_step && last_step == sm_step) { | |
for (int i = 0; i < s.size(); i++) { | |
if (s[i] == lg_step) { | |
next_scale.push_back(next_sm_step); | |
next_scale.push_back(next_lg_step); | |
} else if (s[i] == sm_step) { | |
next_scale.push_back(next_lg_step); | |
} | |
} | |
} else { | |
for (int i = 0; i < s.size(); i++) { | |
if (s[i] == lg_step) { | |
next_scale.push_back(next_lg_step); | |
next_scale.push_back(next_sm_step); | |
} else if (s[i] == sm_step) { | |
next_scale.push_back(next_lg_step); | |
} | |
} | |
} | |
} | |
return next_scale; | |
} | |
int GetLargeStep(const MosScale& s) { | |
return *max_element(s.begin(), s.end()); | |
} | |
int GetSmallStep(const MosScale& s) { | |
return *min_element(s.begin(), s.end()); | |
} | |
void PrintScale(const MosScale& s) { | |
int sm_step = GetSmallStep(s); | |
int lg_step = GetLargeStep(s); | |
int l_count = 0; | |
int s_count = 0; | |
int step_count = 0; | |
std::string temp_string; | |
if (sm_step != lg_step) { | |
for (int i = 0; i < s.size(); i++) { | |
if (s[i] == sm_step) { | |
s_count++; | |
step_count++; | |
temp_string += "s"; | |
} else if (s[i] == lg_step) { | |
l_count++; | |
step_count++; | |
temp_string += "L"; | |
} | |
} | |
std::cout << "MOS: " << std::setw(3) << std::right << std::to_string(l_count) + "L" << std::setw(4) << std::to_string(s_count) + "s"; | |
std::cout << " | Steps: " << std::setw(2) << (step_count); | |
std::cout << " | Step ratio: " << std::setw(5) << std::to_string(lg_step) + ":" + std::to_string(sm_step) << " | Scale pattern: " << temp_string; | |
} else { | |
for (int i = 0; i < s.size(); i++) { | |
temp_string += "u"; | |
step_count++; | |
} | |
std::cout << "MOS: " << std::setw(7) << std::to_string(step_count) + "ed"; | |
std::cout << " | Steps: " << std::setw(2) << (step_count); | |
std::cout << " | Step ratio: " << std::setw(5) << std::to_string(lg_step) + ":" + std::to_string(sm_step) << " | Scale pattern: " << temp_string; | |
} | |
std::cout << std::endl; | |
} | |
// Basically a lookup table for named scales | |
std::string GetTamnamsName(int l, int s) { | |
std::vector<std::vector<std::string>> lookup_table = { | |
{"protic"}, | |
{"antideuteric", "deuteric"}, | |
{"antitetric", "diwood", "tetric"}, | |
{"antimanic", "pentic", "antipentic", "manic"}, | |
{"antimachinoid", "antilemon", "triwood", "lemon", "machinoid"}, | |
}; | |
return lookup_table[l - 1][s - 1]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment