Last active
January 10, 2024 05:34
-
-
Save GanaramInukshuk/b010ff8c29cd03c13b84f1b504efce62 to your computer and use it in GitHub Desktop.
Prototype JI ratio finder (for edos, eds of arbitrary equaves, and arbitrary cent values)
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
// xen_ji_ratio_finder.cpp : This file contains the 'main' function. Program execution begins and ends there. | |
// | |
#include <iostream> | |
#include <string> | |
#include <set> | |
#include <math.h> | |
typedef std::pair<int, int> Ratio; | |
Ratio RatioFinder(float cents, float tolerance, int prime_limit, int odd_limit); | |
Ratio RatioFinder(int edsteps, int ed, Ratio equave); | |
float RatioToCents(Ratio ratio); | |
float RatioToCents(int numerator, int denominrator); | |
int maxPrimeFactors(int n); | |
int gcd(int u, int v); | |
int main() | |
{ | |
Ratio equave = Ratio(2, 1); | |
int ed = 16; | |
for (int i = 1; i < ed; ++i) { | |
std::cout << "Approximated ratios for " << i << "\\" << ed << " (" << RatioToCents(equave) * i / ed << "c):\n"; | |
RatioFinder(i, ed, equave); | |
} | |
std::cout << "End of program reached.\n"; | |
return 0; | |
} | |
float RatioToCents(Ratio ratio) { | |
return log2((float)ratio.first / ratio.second) * 1200; | |
} | |
float RatioToCents(int numerator, int denominator) { | |
return log2((float)numerator / denominator) * 1200; | |
} | |
// A function to find largest prime factor | |
// From https://www.geeksforgeeks.org/find-largest-prime-factor-number/# | |
// Copypasted for sake of prototyping | |
int maxPrimeFactors(int n) { | |
// Initialize the maximum prime factor | |
// variable with the lowest one | |
int maxPrime = -1; | |
// Print the number of 2s that divide n | |
while (n % 2 == 0) { | |
maxPrime = 2; | |
n >>= 1; // equivalent to n /= 2 | |
} | |
// n must be odd at this point | |
while (n % 3 == 0) { | |
maxPrime = 3; | |
n = n / 3; | |
} | |
// now we have to iterate only for integers | |
// who does not have prime factor 2 and 3 | |
for (int i = 5; i <= sqrt(n); i += 6) { | |
while (n % i == 0) { | |
maxPrime = i; | |
n = n / i; | |
} | |
while (n % (i + 2) == 0) { | |
maxPrime = i + 2; | |
n = n / (i + 2); | |
} | |
} | |
// This condition is to handle the case | |
// when n is a prime number greater than 4 | |
if (n > 4) | |
maxPrime = n; | |
return maxPrime; | |
} | |
Ratio RatioFinder(float cents, float tolerance, int prime_limit, int odd_limit) { | |
int numerator = 1, denominator = 1; | |
bool ratio_within_max_tolerance; | |
bool ratio_within_prime_limit; | |
bool ratio_within_odd_limit; | |
do { | |
do { | |
numerator++; | |
float ratio_in_cents = RatioToCents(numerator, denominator); | |
ratio_within_max_tolerance = ratio_in_cents < cents + tolerance; | |
ratio_within_odd_limit = numerator <= odd_limit && denominator <= odd_limit; | |
ratio_within_prime_limit = maxPrimeFactors(numerator) <= prime_limit && maxPrimeFactors(denominator) <= prime_limit; | |
if (ratio_in_cents > cents - tolerance && ratio_in_cents < cents + tolerance && gcd(numerator, denominator) == 1) { | |
std::cout << numerator << "/" << denominator << " = " << ratio_in_cents << std::endl; | |
} | |
} while (ratio_within_max_tolerance && ratio_within_odd_limit && ratio_within_prime_limit); | |
denominator++; | |
numerator = denominator; | |
} while (denominator <= odd_limit && numerator <= odd_limit); | |
Ratio rat = std::pair<int, int>(2, 1); | |
return rat; | |
} | |
Ratio RatioFinder(int edsteps, int ed, Ratio equave) { | |
float equave_in_cents = RatioToCents(equave); | |
float edstep_in_cents = equave_in_cents / ed; | |
return RatioFinder(edstep_in_cents * edsteps, edstep_in_cents / 4, 19, 19); | |
} | |
int gcd(int u, int v) { | |
while (v != 0) { | |
int r = u % v; | |
u = v; | |
v = r; | |
} | |
return u; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment