Skip to content

Instantly share code, notes, and snippets.

@wbajzek
Last active August 29, 2015 14:24
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 wbajzek/5be46cfa8ebc11f7cc69 to your computer and use it in GitHub Desktop.
Save wbajzek/5be46cfa8ebc11f7cc69 to your computer and use it in GitHub Desktop.
Scala parser
#include <iostream>
#include <string>
#include <math.h>
#include <array>
class ScalaDigester
{
public:
ScalaDigester(std::string input)
{
scala_string = input;
current_pos = 0;
}
std::string getNextLine()
{
bool is_comment = false;
std::string line;
if (current_pos < scala_string.length())
do
{
line = scala_string.substr(current_pos,
scala_string.find("\n", current_pos) - current_pos);
current_pos += line.length() + 1;
// lines in a scala file beginning with ! are comments
if (line.at(0) == '!')
is_comment = true;
else
is_comment = false;
}
while (is_comment == true);
return line;
}
private:
std::string scala_string;
int current_pos;
};
class Scale
{
public:
Scale(std::string input)
{
ScalaDigester digester(input);
name = digester.getNextLine();
degrees = std::stoi(digester.getNextLine());
int count = 0;
while (count < degrees)
intervals[count++] = digester.getNextLine();
}
std::string getName()
{
return name;
}
int getDegrees()
{
return degrees;
}
void getFrequencies(float frequencies[128], float root)
{
frequencies[0] = root;
int key_note = 1;
while (key_note < 128)
{
int current_degree = 0;
while (current_degree < degrees)
{
float interval = parseInterval(intervals[current_degree]);
frequencies[key_note] = root * interval;
current_degree++;
if (current_degree == degrees)
root = frequencies[key_note];
key_note++;
if (key_note > 128)
return;
}
}
}
private:
float parseInterval(std::string interval)
{
if (interval.find(".") < interval.length())
return pow(2.0, std::stof(interval) / 1200.0);
else
{
int slash_pos = interval.find("/");
float numerator;
float denominator;
if (slash_pos > -1) {
numerator = std::stof(interval.substr(0,slash_pos));
denominator = std::stof(interval.substr(slash_pos + 1));
}
else
{
numerator = std::stof(interval);
denominator = 1.f;
}
return numerator / denominator;
}
}
std::string name;
int degrees;
std::string intervals[128];
};
int main()
{
// taken from http://www.huygens-fokker.org/scala/scl_format.html
std::string sample_input = "! meanquar.scl\n!\n1/4-comma meantone scale. Pietro Aaron's temperament (1523)\n 12\n!\n 76.04900\n 193.15686\n 310.26471\n 5/4\n 503.42157\n 579.47057\n 696.57843\n 25/16\n 889.73529\n 1006.84314\n 1082.89214\n 2/1";
// after you instantiate the object you can get the name and # scale degrees
Scale scale(sample_input);
std::cout << scale.getName() << "\n";
std::cout << scale.getDegrees() << "\n";
// given a root_frequency, it will populate a frequencies array with the scale
float root_frequency = 1.0;
float frequencies[128];
scale.getFrequencies(frequencies, root_frequency);
// print them out for testing purposes
int i = 0;
while (i < 128)
std::cout << frequencies[i++] << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment