diff --git a/src/common/SurgeStorage.cpp b/src/common/SurgeStorage.cpp index f0516d95633..9a9a5234679 100644 --- a/src/common/SurgeStorage.cpp +++ b/src/common/SurgeStorage.cpp @@ -1190,49 +1190,58 @@ float envelope_rate_linear(float x) void SurgeStorage::retuneToScale(const Surge::Storage::Scale& s) { - int scale0 = 48; + int scale0 = 48; // This is the 1.0 point float value0 = 16; - - for (int i = 0; i < 512; ++i) - { - int noteBase = i - 256; - int distanceFromScale0 = noteBase - scale0 - 1; - int turns = 0; - float baseValue = value0; - while (distanceFromScale0 < 0) - { - distanceFromScale0 += s.count; - baseValue /= 2; - } - while (distanceFromScale0 >= s.count) - { - distanceFromScale0 -= s.count; - baseValue *= 2; - } -#if DEBUG_SCALE - if ((i>= 254 && i <=258) || ( i >= 302 && i <= 308)) - std::cout << i << " " << std::setw(5) << noteBase << " or " << i << " D0=" << std::setw(3) << distanceFromScale0 - << " PP=" << std::setw(10) << table_pitch[i] - << " bv=" << std::setw(5) << baseValue - << " sc=" << std::setw(10) << s.tones[distanceFromScale0].floatValue - << " exp=" << std::setw(10) << pow( 2.0f, s.tones[distanceFromScale0].floatValue - 1.0f) - << " sc*bv=" << std::setw(10) << pow( 2.0f, s.tones[distanceFromScale0].floatValue - 1.0f) * baseValue - << " diff=" << std::setw(10) << pow( 2.0f, s.tones[distanceFromScale0].floatValue - 1.0f) * baseValue - table_pitch[i] - ; -#endif - table_pitch[i] = pow( 2.0f, s.tones[distanceFromScale0].floatValue - 1.0f) * baseValue; + float pitches[512]; + int pos0 = 256 + scale0; + pitches[pos0] = 1.0; + for (int i=0; i<512; ++i) + { + int distanceFromScale0 = i - pos0; + + if( distanceFromScale0 == 0 ) + { + } + else + { + int rounds = (distanceFromScale0-1) / s.count; + int thisRound = (distanceFromScale0-1) % s.count; -#if DEBUG_SCALE - if ((i>= 254 && i <=258) || ( i >= 302 && i <= 308)) - std::cout << " NEWP=" << table_pitch[i] << std::endl; -#endif - + if( thisRound < 0 ) + { + thisRound += s.count; + rounds -= 1; + } + float mul = pow( s.tones[s.count-1].floatValue, rounds); + pitches[i] = s.tones[thisRound].floatValue + rounds * (s.tones[s.count - 1].floatValue - 1.0); + float otp = table_pitch[i]; + table_pitch[i] = pow( 2.0, pitches[i] + 3 ); + +#if DEBUG_SCALES + if( i > 296 && i < 340 ) + std::cout << "PITCH: i=" << i << " n=" << i - 256 << " r=" << rounds << " t=" << thisRound + << " p=" << pitches[i] + << " t=" << s.tones[thisRound].floatValue + << " tp=" << table_pitch[i] + << " otp=" << otp + << " diff=" << table_pitch[i] - otp + + //<< " l2p=" << log(otp)/log(2.0) + //<< " l2p-p=" << log(otp)/log(2.0) - pitches[i] - rounds - 3 + << std::endl; +#endif + } + } + + for( int i=0; i<512; ++i ) + { table_pitch_inv[i] = 1.f / table_pitch[i]; table_note_omega[0][i] = (float)sin(2 * M_PI * min(0.5, 440 * table_pitch[i] * dsamplerate_os_inv)); table_note_omega[1][i] = (float)cos(2 * M_PI * min(0.5, 440 * table_pitch[i] * dsamplerate_os_inv)); + } } diff --git a/src/common/Tunings.cpp b/src/common/Tunings.cpp index 000aa7801fc..73941fd0539 100644 --- a/src/common/Tunings.cpp +++ b/src/common/Tunings.cpp @@ -4,6 +4,7 @@ #include #include #include +#include /* From: http://huygens-fokker.org/scala/scl_format.html @@ -67,7 +68,6 @@ Surge::Storage::Scale Surge::Storage::readSCLFile(std::string fname) { t.type = Tone::kToneCents; t.cents = atof(line.c_str()); - t.floatValue = t.cents / 1200.0 + 1.0; } else { @@ -75,16 +75,21 @@ Surge::Storage::Scale Surge::Storage::readSCLFile(std::string fname) auto slashPos = line.find("/"); if (slashPos == std::string::npos) { - t.ratio_d = atoi(line.c_str()); - t.ratio_n = 1; + t.ratio_n = atoi(line.c_str()); + t.ratio_d = 1; } else { t.ratio_n = atoi(line.substr(0, slashPos).c_str()); t.ratio_d = atoi(line.substr(slashPos + 1).c_str()); } - t.floatValue = 1.0 * t.ratio_n / t.ratio_d; + + // 2^(cents/1200) = n/d + // cents = 1200 * log(n/d) / log(2) + + t.cents = 1200 * log(1.0 * t.ratio_n/t.ratio_d) / log(2.0); } + t.floatValue = t.cents / 1200.0 + 1.0; res.tones.push_back(t); break; @@ -101,7 +106,7 @@ std::ostream& Surge::Storage::operator<<(std::ostream& os, const Surge::Storage: os << t.cents; else os << t.ratio_n << " / " << t.ratio_d; - os << " (" << t.floatValue << ")"; + os << " (f=" << t.floatValue << " c=" << t.cents << ")"; return os; } diff --git a/src/common/gui/SurgeGUIEditor.cpp b/src/common/gui/SurgeGUIEditor.cpp index 2197b0affba..d5b24f99182 100644 --- a/src/common/gui/SurgeGUIEditor.cpp +++ b/src/common/gui/SurgeGUIEditor.cpp @@ -2754,6 +2754,15 @@ void SurgeGUIEditor::showSettingsMenu(CRect &menuRect) { auto cb = [this](std::string sf) { + std::string sfx = ".scl"; + if( sf.length() >= sfx.length()) + { + if( sf.compare(sf.length() - sfx.length(), sfx.length(), sfx) != 0 ) + { + Surge::UserInteractions::promptError( "Please only select .scl files", "Invalid Choice" ); + return; + } + } auto sc = Surge::Storage::readSCLFile(sf); this->synth->storage.retuneToScale(sc); }; diff --git a/src/headless/main.cpp b/src/headless/main.cpp index 071435b637a..5f074a14031 100644 --- a/src/headless/main.cpp +++ b/src/headless/main.cpp @@ -93,7 +93,8 @@ void testTuning() { SurgeSynthesizer* surge = Surge::Headless::createSurge(44100); - Surge::Storage::Scale s = Surge::Storage::readSCLFile("/Users/paul/dev/music/scl/05-22.scl"); + //Surge::Storage::Scale s = Surge::Storage::readSCLFile("/Users/paul/dev/music/test_scl/Q4.scl" ); + Surge::Storage::Scale s = Surge::Storage::readSCLFile("/Users/paul/dev/music/test_scl/12-flat.scl" ); std::cout << s; auto n2f = [surge](int n) @@ -108,11 +109,11 @@ void testTuning() //auto s = Surge::Storage::readSCLFile("/Users/paul/tmp/scl/lumma_12_strangeion.scl"); std::cout << "BEFORE\n"; - n2f(0); n2f(24); n2f(25); n2f(60); n2f(57); n2f(48); + //n2f(0); n2f(24); n2f(25); n2f(60); n2f(57); n2f(48); surge->storage.retuneToScale(s); - std::cout << "AFTER\n"; - n2f(0); n2f(24); n2f(25); n2f(60); n2f(57); n2f(48); + //std::cout << "AFTER\n"; + //n2f(0); n2f(24); n2f(25); n2f(60); n2f(57); n2f(48); } void playSomeBach()