Skip to content

Instantly share code, notes, and snippets.

@GanaramInukshuk
Created March 26, 2022 09:30
Show Gist options
  • Save GanaramInukshuk/5b59543eb13cd5af74a340690e90441a to your computer and use it in GitHub Desktop.
Save GanaramInukshuk/5b59543eb13cd5af74a340690e90441a to your computer and use it in GitHub Desktop.
This is the original mosfinder program that I written in C++.
#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