Skip to content

Commit

Permalink
Add support for size zero KBM maps (surge-synthesizer#1463)
Browse files Browse the repository at this point in the history
I didn't even know Size 0 KBM maps were a thing! But they
are. They mean exactly what you'd expect (note-for-note).
So add them here with regtests to show they work rather than
crash.

Addresses surge-synthesizer#1041
  • Loading branch information
baconpaul authored Jan 10, 2020
1 parent 370a7ca commit a11f680
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/common/SurgeStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,10 @@ bool SurgeStorage::retuneToScale(const Surge::Storage::Scale& s)
float pitchMod = log(scaleConstantPitch())/log(2) - 1;

int scalePositionOfStartNote = 0;
int scalePositionOfTuningNote = currentMapping.keys[currentMapping.tuningConstantNote - currentMapping.middleNote];
int scalePositionOfTuningNote = currentMapping.tuningConstantNote - currentMapping.middleNote;
if( currentMapping.count > 0 )
scalePositionOfTuningNote = currentMapping.keys[scalePositionOfTuningNote];

float tuningCenterPitchOffset;
if( scalePositionOfTuningNote == 0 )
tuningCenterPitchOffset = 0;
Expand Down Expand Up @@ -1335,7 +1338,7 @@ bool SurgeStorage::retuneToScale(const Surge::Storage::Scale& s)
int rounds;
int thisRound;
int disable = false;
if( currentMapping.isStandardMapping )
if( currentMapping.isStandardMapping || ( currentMapping.count == 0 ) )
{
rounds = (distanceFromScale0-1) / s.count;
thisRound = (distanceFromScale0-1) % s.count;
Expand Down Expand Up @@ -1439,8 +1442,16 @@ bool SurgeStorage::remapToKeyboard(const Surge::Storage::KeyboardMapping& k)
tuningPitch = k.tuningFrequency / 8.175798915;
tuningPitchInv = 1.0 / tuningPitch;
}
// The mapping will change all the cached pitches
retuneToScale(currentScale);
// The mapping will change all the cached pitches.
if( ! currentScale.isValid() )
{
// We need to set the current scale to a default scale
retuneToScale(Surge::Storage::Scale::evenTemprament12NoteScale());
}
else
{
retuneToScale(currentScale);
}
return true;
}

Expand Down
23 changes: 23 additions & 0 deletions src/common/Tunings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,29 @@ Surge::Storage::Scale Surge::Storage::parseSCLData(const std::string &d)
return res;
}

Surge::Storage::Scale Surge::Storage::Scale::evenTemprament12NoteScale()
{
auto data = R"SCL(! even.scl
!
12 note even temprament
12
!
100.0
200.0
300.0
400.0
500.0
600.0
700.0
800.0
900.0
1000.0
1100.0
2/1
)SCL";
return parseSCLData(data);
}

Surge::Storage::KeyboardMapping keyboardMappingFromStream(std::istream &inf)
{
std::string line;
Expand Down
2 changes: 2 additions & 0 deletions src/common/Tunings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct Scale
bool isValid() const;

std::string toHtml(SurgeStorage *storage);

static Scale evenTemprament12NoteScale();
};

struct KeyboardMapping
Expand Down
63 changes: 63 additions & 0 deletions src/headless/UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,69 @@ TEST_CASE( "Non-uniform keyboard mapping", "[tun]" )
}
}

TEST_CASE( "Zero Size Maps", "[tun]" )
{
auto surge = surgeOnSine();
REQUIRE( surge.get() );

SECTION( "Note 61" )
{
auto f60std = frequencyForNote( surge, 60 );
auto f61std = frequencyForNote( surge, 61 );
REQUIRE( f60std == Approx( 261.63 ).margin( 0.1 ) );

auto k61 = Surge::Storage::readKBMFile( "test-data/scl/empty-note61.kbm" );
REQUIRE( !k61.isStandardMapping );
REQUIRE( k61.count == 0 );
surge->storage.remapToKeyboard( k61 );

auto f60map = frequencyForNote( surge, 60 );
auto f61map = frequencyForNote( surge, 61 );
REQUIRE( frequencyForNote( surge, 61 ) == Approx( 280 ).margin( 0.1 ) );
REQUIRE( f61std / f60std == Approx( f61map / f60map ).margin( 0.001 ) );
}

SECTION( "Note 69" )
{
auto f60std = frequencyForNote( surge, 60 );
auto f69std = frequencyForNote( surge, 69 );
REQUIRE( f60std == Approx( 261.63 ).margin( 0.1 ) );
REQUIRE( f69std == Approx( 440.0 ).margin( 0.1 ) );

auto k69 = Surge::Storage::readKBMFile( "test-data/scl/empty-note69.kbm" );
REQUIRE( !k69.isStandardMapping );
REQUIRE( k69.count == 0 );
surge->storage.remapToKeyboard( k69 );

auto f60map = frequencyForNote( surge, 60 );
auto f69map = frequencyForNote( surge, 69 );
REQUIRE( frequencyForNote( surge, 69 ) == Approx( 452 ).margin( 0.1 ) );
REQUIRE( f69std / f60std == Approx( f69map / f60map ).margin( 0.001 ) );
}

SECTION( "Note 69 with Tuning" )
{
Surge::Storage::Scale s = Surge::Storage::readSCLFile("test-data/scl/marvel12.scl" );
surge->storage.retuneToScale(s);
auto f60std = frequencyForNote( surge, 60 );
auto f69std = frequencyForNote( surge, 69 );
REQUIRE( f60std == Approx( 261.63 ).margin( 0.1 ) );
REQUIRE( f69std != Approx( 440.0 ).margin( 0.1 ) );


auto k69 = Surge::Storage::readKBMFile( "test-data/scl/empty-note69.kbm" );
REQUIRE( !k69.isStandardMapping );
REQUIRE( k69.count == 0 );
surge->storage.remapToKeyboard( k69 );

auto f60map = frequencyForNote( surge, 60 );
auto f69map = frequencyForNote( surge, 69 );
REQUIRE( frequencyForNote( surge, 69 ) == Approx( 452 ).margin( 0.1 ) );
REQUIRE( f69std / f60std == Approx( f69map / f60map ).margin( 0.001 ) );
}

}

TEST_CASE( "Simple Single Oscillator is Constant", "[dsp]" )
{
SurgeSynthesizer* surge = Surge::Headless::createSurge(44100);
Expand Down
17 changes: 17 additions & 0 deletions test-data/scl/empty-note61.kbm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
! 61-277-61 Concert C#, Db.kbm
!
! Size of map:
0
! First MIDI note number to retune:
0
! Last MIDI note number to retune:
127
! Middle note where the first entry in the mapping is mapped to:
61
! Reference note for which frequency is given:
61
! Frequency to tune the above note to (floating point e.g. 440.0):
280.0
! Scale degree to consider as formal octave:
0
! Mapping.
17 changes: 17 additions & 0 deletions test-data/scl/empty-note69.kbm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
! 61-277-61 Concert C#, Db.kbm
!
! Size of map:
0
! First MIDI note number to retune:
0
! Last MIDI note number to retune:
127
! Middle note where the first entry in the mapping is mapped to:
60
! Reference note for which frequency is given:
69
! Frequency to tune the above note to (floating point e.g. 440.0):
452
! Scale degree to consider as formal octave:
0
! Mapping.

0 comments on commit a11f680

Please sign in to comment.