surge-synthesizer / tuning-library

Micro-tuning format parsing and frequency finding as a header-only C+ library

Home Page:https://surge-synth-team.org/tuning-library/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect tuning in some locales

jpcima opened this issue · comments

Hello,

If the programs sets a C locale which prefers comma as decimal separator, the file is misread and gives wrong results.

If you trace this portion of code as follows.

t.cents = atof(line.c_str());
fprintf(stderr, "CONVERT \"%s\" to %f\n", line.c_str(), t.cents);

You may observe either of the following results depending on the program's locale.

CONVERT " 76.04900" to 76.049000
CONVERT " 76.04900" to 76,000000
commented

Oh thank you! I will add locale aware parsing to these parts of the code base this week.

Appreciated.

commented

Oh and @jpcima I made this library because I copied the surge library for our branch of dexed. On my list for the immediate future is to rip out our dexed tuning implementation and replace it with this as a submodule of course.

commented
float longitude = 0.0f;
std::istringstream istr(pField);

istr.imbue(std::locale("C"));
istr >> longitude;

Is what I need; plus some regtests where I run in a European locale

This, I also believe, is the simplest portable fix of this problem.

This is great, thanks! We will likely add this library into Sfizz to provide some tuning options.

commented

Oh excellent - here's a retest which fails in the current lib. Cool will be easy to fix now.

    SECTION( "Test All Constraints SCL and KBM in Spain" )
    {
        std::locale::global( std::locale( "es_ES" ) );
        for( auto fs: testSCLs() )
            for( auto fk : testKBMs() )
            {
                INFO( "Testing Constraints with " << fs << " " << fk );
                auto s = Tunings::readSCLFile(testFile(fs));
                auto k = Tunings::readKBMFile(testFile(fk));
                Tunings::Tuning t(s,k);
                
                for( int i=0; i<127; ++i )
                {
                    REQUIRE( t.frequencyForMidiNote(i) == t.frequencyForMidiNoteScaledByMidi0(i) * Tunings::MIDI_0_FREQ );
                    REQUIRE( t.frequencyForMidiNoteScaledByMidi0(i) == pow( 2.0, t.logScaledFrequencyForMidiNote(i) ) );
                }
            }
        std::locale::global( std::locale( "" ) );
    }
commented

This is great, thanks! We will likely add this library into Sfizz to provide some tuning options.

Awesome! That's why we factored it and MIT licensed it!

commented

OK I just pushed a fix to master, including a regtest. The regrets actually exposed another locale bug so I fixed that too.

Please give it a whirl! And if you can check if 'make alltests' works for you in your locale that would be great.

If it's all OK please close the issue.

And lemme know how it goes!

It works well ! Thank you