Skip to content

Instantly share code, notes, and snippets.

@GanaramInukshuk
Last active January 10, 2024 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GanaramInukshuk/b010ff8c29cd03c13b84f1b504efce62 to your computer and use it in GitHub Desktop.
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)
// 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