1 /*
2  * High accuracy program to create HTML formatted
3  * list of musical note names, MIDI note numbers
4  * and actual frequencies.
5  * Only covers the useful range of note numbers
6  * not the full range.
7  *
8  * Note:
9  *   you can get an approximation of 12root2 with:
10  *  196 / 185
11  * this gives:
12  *  1.05946
13  *
14  * 07/08/2021
15  *
16  * g++ -Wall midiListGen.cpp -o midiListGen
17  *
18  */
19 #include <math.h>
20 #include <limits>
21 #include <iostream>
22 #include <fstream>
23 #include <string>
24 #include <vector>
25 #include <sstream>
26 #include <cstring>
27 #include <regex>
28 
29 using namespace std;
30 
asLongString(double n,size_t digits)31 std::string asLongString(double n, size_t digits)
32 {
33     std::ostringstream oss;
34     oss.precision(digits);
35     oss.width(digits);
36     oss << n;
37     std::string value = oss.str();
38     value = std::regex_replace(value, std::regex("^ +"), "");
39 
40     if (value.find('.') == std::string::npos)
41         value += '.';
42     while (value.length() <= digits)
43         value += '0';
44     return value;
45 }
46 
47 
main(void)48 int main(void)
49 { // we use doubles for greatest accuracy then reduce the result.
50   // this minimises accumulated errors from repeated multiplication
51     double twelfth = 12.0;
52     double two = 2.0;
53     double multiplier;
54     multiplier = pow(two, 1 / twelfth);
55     std::cout.precision(10);
56     std::cout << "twelfth root of two = " << multiplier << std::endl;
57 
58     static std::string names [] = {
59     "A", "#", "B", "C", "#", "D", "#", "E", "F", "#", "G", "#"
60     };
61     int stringcount = 0;
62     int octave = 0;
63     double result = 27.5;
64     int precision = 6;
65     std::string currentNote;
66     std::string fullString;
67     std::vector <std::string> ourlist;
68     for (int i = 21; i < 109; ++i) // practical MIDI note range
69     {
70         currentNote = names[stringcount];
71         if (currentNote == "C")
72             ++ octave;
73         if (currentNote != "#")
74             currentNote += std::to_string(octave);
75         ++ stringcount;
76         if (stringcount >= 12)
77             stringcount = 0;
78         fullString = "        <td>" + currentNote + "</td><td>" + std::to_string(i) + "</td><td>" + asLongString(result, precision) + "</td>";
79         ourlist.push_back("      </tr>");
80         ourlist.push_back(fullString);
81         ourlist.push_back("      <tr align=\"center\">");
82         result *= multiplier;
83     }
84     size_t idx = ourlist.size();
85     ofstream midiList;
86     midiList.open("midiList.txt");
87     if (!midiList.is_open())
88     {
89         std::cout << "Failed to open midiList.txt" << std::endl;
90         return 0;
91     }
92     while (idx > 0)
93     {
94         --idx;
95         midiList << ourlist[idx] << endl;
96     }
97     midiList.close();
98     return 0;
99 }
100