cog/Frameworks/libsidplay/sidplay-residfp-code/combined-waveforms/combined.cpp

1062 lines
34 KiB
C++

/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2013-2016 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <cassert>
#include <ctime>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>
#include <random>
#include "parameters.h"
static const float EPSILON = 1e-3;
#ifdef __MINGW32__
// MinGW's std::random_device is a PRNG seeded with a constant value
// so we use system time as a random seed.
#include <chrono>
inline long getSeed()
{
using namespace std::chrono;
const auto now_ms = time_point_cast<std::chrono::milliseconds>(system_clock::now());
return now_ms.time_since_epoch().count();
}
#else
inline long getSeed()
{
return std::random_device{}();
}
#endif
static std::default_random_engine prng(getSeed());
static std::normal_distribution<> normal_dist(1.0, 0.001);
static std::normal_distribution<> normal_dist2(0.5, 0.2);
static double GetRandomValue()
{
return normal_dist(prng);
}
static float GetNewRandomValue()
{
return static_cast<float>(normal_dist2(prng));
}
static void Optimize(const ref_vector_t &reference, int wave, char chip)
{
Parameters bestparams;
/*
* The score here reported is the acoustic error.
* In parentheses the number of mispredicted bits
* on a total of 32768.
*/
switch (chip)
{
// 6581 R2
case 'B':
switch (wave)
{
case 3: // ST
// current score 152 (57)
bestparams.threshold = 0.988547385f;
bestparams.topbit = 0.f;
bestparams.distance1 = 5.58014059f;
bestparams.distance2 = 5.4269886f;
bestparams.stmix = 0.806023061f;
break;
case 5: // PT
// current score 2872 (154)
bestparams.threshold = 0.984531879f;
bestparams.pulsestrength = 3.03670526f;
bestparams.distance1 = 0.99342072f;
bestparams.distance2 = 1.11435139f;
break;
case 6: // PS
// current score 0
bestparams.threshold = 0.906437993f;
bestparams.pulsestrength = 2.11317873f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.130663797f;
bestparams.distance2 = 0.0835102722f;
break;
case 7: // PST
// current score 0
bestparams.threshold = 0.924151242f;
bestparams.pulsestrength = 1.16428149f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.920196056f;
bestparams.distance2 = 1.07491302f;
bestparams.stmix = 0.793505609f;
break;
}
break;
// 6581 R2 (odd)
case 'C':
switch (wave)
{
case 3:
// current score 2948 (446)
bestparams.threshold = 0.881458f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.93176f;
bestparams.stmix = 0.596385f;
break;
case 5:
// current score 10992 (367)
bestparams.threshold = 0.933451474f;
bestparams.pulsestrength = 3.04320669f;
bestparams.distance1 = 1.01660681f;
bestparams.distance2 = 1.19298482f;
break;
case 6:
// current score 5532 (298)
bestparams.threshold = 0.906489253f;
bestparams.pulsestrength = 3.24875951f;
bestparams.topbit = 1.57458532f; // ???
bestparams.distance1 = 0.101274647f;
bestparams.distance2 = 0.188963249f;
break;
case 7:
// current score 850 (60)
bestparams.threshold = 0.919113517f;
bestparams.pulsestrength = 1.62892509f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.21794045f;
bestparams.distance2 = 1.2279855f;
bestparams.stmix = 0.896797657f;
break;
}
break;
// 6581 R2 (odd)
case 'D':
switch (wave)
{
case 3:
// current score 1958 (302)
bestparams.threshold = 0.861116648f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.582165f;
bestparams.distance2 = 2.23844433f;
bestparams.stmix = 0.53945446f;
break;
case 5:
// current score 9924 (426)
bestparams.threshold = 0.927432716f;
bestparams.pulsestrength = 2.37539339f;
bestparams.distance1 = 1.00424087f;
bestparams.distance2 = 1.2061156f;
break;
case 6:
// current score 12332 (857)
bestparams.threshold = 0.883725405f;
bestparams.pulsestrength = 1.86024225f;
bestparams.topbit = 1.12501097f; // ???
bestparams.distance1 = 0.0956423283f;
bestparams.distance2 = 0.457357466f;
break;
case 7:
// current score 258 (64)
bestparams.threshold = 0.91076839f;
bestparams.pulsestrength = 1.2814858f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.17647922f;
bestparams.distance2 = 1.18998444f;
bestparams.stmix = 0.771969795f;
break;
}
break;
// 6581 R2
case 'E':
switch (wave)
{
case 3:
// current score 297 (98)
bestparams.threshold = 0.989183f;
bestparams.topbit = 0.f;
bestparams.distance1 = 5.75852f;
bestparams.stmix = 0.800831f;
break;
case 5:
// current score 3348 (146)
bestparams.threshold = 0.91292721f;
bestparams.pulsestrength = 1.83235359f;
bestparams.distance1 = 1.12143898f;
bestparams.distance2 = 1.12768865f;
break;
case 6:
// current score 8 (6)
bestparams.threshold = 0.91496712f;
bestparams.pulsestrength = 2.28155446f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.122848086f;
bestparams.distance2 = 0.0706237406f;
break;
case 7:
// current score 0
bestparams.threshold = 0.970328987f;
bestparams.pulsestrength = 1.75902855f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.21010804f;
bestparams.distance2 = 1.269436f;
bestparams.stmix = 0.983422756f;
break;
}
break;
// 6581 R2
case 'F':
switch (wave)
{
case 3:
// current score 240 (64)
bestparams.threshold = 0.99254179f;
bestparams.topbit = 0.001f;
bestparams.distance1 = 7.18324232f;
bestparams.distance2 = 6.00581455f;
bestparams.stmix = 0.841992021f;
break;
case 5:
// current score 3008 (57)
bestparams.threshold = 0.959230483f;
bestparams.pulsestrength = 2.74101543f;
bestparams.distance1 = 1.00775206f;
bestparams.distance2 = 1.11247838f;
break;
case 6:
// current score 432 (12)
bestparams.threshold = 0.902768612f;
bestparams.pulsestrength = 2.06190324f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.150018558f;
bestparams.distance2 = 0.102936305f;
break;
case 7:
// current score 2 (2)
bestparams.threshold = 0.896021485f;
bestparams.pulsestrength = 0.865568995f;
bestparams.topbit = 0.002f;
bestparams.distance1 = 0.98756659f;
bestparams.distance2 = 1.17235816f;
bestparams.stmix = 0.547210157f;
break;
}
break;
// 6581 R2 (odd)
case 'G':
switch (wave)
{
case 3:
// current score 1689 (280)
bestparams.threshold = 0.90251f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.9147f;
bestparams.distance2 = 1.6747f;
bestparams.stmix = 0.62376f;
break;
case 5:
// current score 6128 (130)
bestparams.threshold = 0.93088f;
bestparams.pulsestrength = 2.4843f;
bestparams.distance1 = 1.0353f;
bestparams.distance2 = 1.1484f;
break;
case 6:
// current score 10639 (569)
bestparams.threshold = 0.912298322f;
bestparams.pulsestrength = 2.32252741f;
bestparams.topbit = 1.10538983f; // ???
bestparams.distance1 = 0.0537932068f;
bestparams.distance2 = 0.252674758f;
break;
case 7:
// current score 64 (2)
bestparams.threshold = 0.91f;
bestparams.pulsestrength = 1.192f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.0169f;
bestparams.distance2 = 1.2f;
bestparams.stmix = 0.637f;
break;
}
break;
// 6581 R2
case 'H':
switch (wave)
{
case 3:
// current score 230 (78)
bestparams.threshold = 0.97577709f;
bestparams.topbit = 0.f;
bestparams.distance1 = 3.35368633f;
bestparams.distance2 = 2.60800719f;
bestparams.stmix = 0.670109689f;
break;
case 5:
// current score 2744 (91)
bestparams.threshold = 0.919414461f;
bestparams.pulsestrength = 1.49266505f;
bestparams.distance1 = 1.12526083f;
bestparams.distance2 = 1.15659571f;
break;
case 6:
// current score 360 (30)
bestparams.threshold = 0.941394627f;
bestparams.pulsestrength = 2.23991108f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.149554357f;
bestparams.distance2 = 0.150783867f;
break;
case 7:
// current score 0
bestparams.threshold = 0.98f;
bestparams.pulsestrength = 2.f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.1f;
bestparams.stmix = 0.91f;
break;
}
break;
// 6581 R2
case 'I':
switch (wave)
{
case 3:
// current score 184 (68)
bestparams.threshold = 0.982668161f;
bestparams.topbit = 0.001f;
bestparams.distance1 = 4.43093681f;
bestparams.distance2 = 4.43528938f;
bestparams.stmix = 0.775906205f;
break;
case 5:
// current score 6847 (171)
bestparams.threshold = 0.943752468f;
bestparams.pulsestrength = 2.28453493f;
bestparams.distance1 = 1.03244841f;
bestparams.distance2 = 1.17106056f;
break;
case 6:
// current score 422 (17)
bestparams.threshold = 0.894735754f;
bestparams.pulsestrength = 1.81871581f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.0912446976f;
bestparams.distance2 = 0.101162158f;
break;
case 7:
// current score 16 (6)
bestparams.threshold = 0.942962408f;
bestparams.pulsestrength = 1.57235372f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.1614747f;
bestparams.distance2 = 1.22249365f;
bestparams.stmix = 0.581929862f;
break;
}
break;
// 6581 R2
case 'J':
switch (wave)
{
case 3:
// current score 148 (61)
bestparams.threshold = 0.979544f;
bestparams.topbit = 0.f;
bestparams.distance1 = 3.98271f;
bestparams.stmix = 0.775023f;
break;
case 5:
// current score 1540 (102)
bestparams.threshold = 0.9079f;
bestparams.pulsestrength = 1.72749f;
bestparams.distance1 = 1.12017f;
bestparams.distance2 = 1.10793f;
break;
case 6:
// current score 0
bestparams.threshold = 0.905734479f;
bestparams.pulsestrength = 1.99118233f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.0996442288f;
bestparams.distance2 = 0.0730706826f;
break;
case 7:
// current score 0
bestparams.threshold = 0.95248f;
bestparams.pulsestrength = 1.51f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.07153f;
bestparams.distance2 = 1.09353f;
bestparams.stmix = 1.f;
break;
}
break;
// 6581 R2
case 'K':
switch (wave)
{
case 3:
// current score 1299 (150)
bestparams.threshold = 0.931232035f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.78504324f;
bestparams.distance2 = 2.21891737f;
bestparams.stmix = 0.692269444f;
break;
case 5:
// current score 8086 (386)
bestparams.threshold = 1.f;
bestparams.pulsestrength = 3.06605577f;
bestparams.distance1 = 0.981742382f;
bestparams.distance2 = 1.1532563f;
break;
case 6:
// current score 2608 (140)
bestparams.threshold = 0.898440778f;
bestparams.pulsestrength = 1.99839222f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.108322836f;
bestparams.distance2 = 0.096527569f;
break;
case 7:
// current score 102 (10)
bestparams.threshold = 0.931423545f;
bestparams.pulsestrength = 1.41654074f;
bestparams.topbit = 0.01f;
bestparams.distance1 = 1.14805245f;
bestparams.distance2 = 1.35858405f;
bestparams.stmix = 0.48002857f;
break;
}
break;
// 6581 R2
case 'L':
switch (wave)
{
case 3:
// current score 1356 (109)
bestparams.threshold = 0.983135f;
bestparams.topbit = 0.f;
bestparams.distance1 = 4.62089f;
bestparams.stmix = 0.778836f;
break;
case 5:
// current score 6098 (134)
bestparams.threshold = 0.924762011f;
bestparams.pulsestrength = 2.37176347f;
bestparams.distance1 = 1.04673755f;
bestparams.distance2 = 1.16099727f;
break;
case 6:
// current score 1534 (107)
bestparams.threshold = 0.927221477f;
bestparams.pulsestrength = 2.94884133f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.0910025164f;
bestparams.distance2 = 0.132933453f;
break;
case 7:
// current score 102 (16)
bestparams.threshold = 0.941179f;
bestparams.pulsestrength = 1.65307f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.22544f;
bestparams.stmix = 0.748047f;
break;
}
break;
// 6581 R2
case 'M':
switch (wave)
{
case 3:
// current score 352 (106)
bestparams.threshold = 0.938881f;
bestparams.topbit = 0.f;
bestparams.distance1 = 2.07118f;
bestparams.stmix = 0.579197f;
break;
case 5:
// current score 2434 (139)
bestparams.threshold = 0.906191885f;
bestparams.pulsestrength = 1.59146726f;
bestparams.distance1 = 1.127689f;
bestparams.distance2 = 1.1314106f;
break;
case 6:
// current score 0
bestparams.threshold = 0.893231869f;
bestparams.pulsestrength = 1.70082629f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.111504503f;
bestparams.distance2 = 0.0748674423f;
break;
case 7:
// current score 0
bestparams.threshold = 0.979779f;
bestparams.pulsestrength = 2.03635f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.30189f;
bestparams.stmix = 0.923735f;
break;
}
break;
// 6581 R2
case 'N':
switch (wave)
{
case 3:
// current score 662 (104)
bestparams.threshold = 0.981390178f;
bestparams.topbit = 0.f;
bestparams.distance1 = 4.37947226f;
bestparams.distance2 = 4.3854661f;
bestparams.stmix = 0.772289276f;
break;
case 5:
// current score 4656 (74)
bestparams.threshold = 0.945089161f;
bestparams.pulsestrength = 2.48777676f;
bestparams.distance1 = 1.02335358f;
bestparams.distance2 = 1.14071643f;
break;
case 6:
// current score 584 (18)
bestparams.threshold = 0.90864867f;
bestparams.pulsestrength = 2.22691917f;
bestparams.topbit = -0.008f; // ???
bestparams.distance1 = 0.120167315f;
bestparams.distance2 = 0.119318768f;
break;
case 7:
// current score 2 (2)
bestparams.threshold = 0.911848485f;
bestparams.pulsestrength = 1.17097521f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.991214871f;
bestparams.distance2 = 1.10500252f;
bestparams.stmix = 0.591298461f;
break;
}
break;
// 6581 R3
case 'O':
switch (wave)
{
case 3:
// current score 1100 (118)
bestparams.threshold = 0.967385352f;
bestparams.topbit = 0.f;
bestparams.distance1 = 3.22246957f;
bestparams.distance2 = 3.13088274f;
bestparams.stmix = 0.739427269f;
break;
case 5:
// current score 6052 (99)
bestparams.threshold = 0.929785728f;
bestparams.pulsestrength = 2.30605006f;
bestparams.distance1 = 1.03718281f;
bestparams.distance2 = 1.1534183f;
break;
case 6:
// current score 1012 (54)
bestparams.threshold = 0.919249177f;
bestparams.pulsestrength = 2.58188939f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.131623372f;
bestparams.distance2 = 0.158718824f;
break;
case 7:
// current score 2 (2)
bestparams.threshold = 0.901689231f;
bestparams.pulsestrength = 1.06335056f;
bestparams.topbit = 0.004f;
bestparams.distance1 = 1.04226708f;
bestparams.distance2 = 1.29957008f;
bestparams.stmix = 0.509225965f;
break;
}
break;
// 6581 R3
case 'P':
switch (wave)
{
case 3:
// current score 1814 (121)
bestparams.threshold = 0.981729865f;
bestparams.topbit = 0.001f;
bestparams.distance1 = 4.67945051f;
bestparams.distance2 = 4.70896149f;
bestparams.stmix = 0.791615963f;
break;
case 5:
// current score 3748 (113)
bestparams.threshold = 0.915575624f;
bestparams.pulsestrength = 2.57049465f;
bestparams.distance1 = 1.03338766f;
bestparams.distance2 = 1.08230126f;
break;
case 6:
// current score 269 (74)
bestparams.threshold = 0.944703519f;
bestparams.pulsestrength = 4.04210186f;
bestparams.topbit = -0.001f; // ???
bestparams.distance1 = 0.0535937659f;
bestparams.distance2 = 0.0294511318f;
break;
case 7:
// current score 181 (17)
bestparams.threshold = 0.919196963f;
bestparams.pulsestrength = 1.21124005f;
bestparams.topbit = 0.002f;
bestparams.distance1 = 1.15129697f;
bestparams.distance2 = 1.22111976f;
bestparams.stmix = 0.672436357f;
break;
}
break;
// 6581 R3
case 'Q':
switch (wave)
{
case 3:
// current score 488 (90)
bestparams.threshold = 0.982932f;
bestparams.topbit = 0.f;
bestparams.distance1 = 4.59079f;
bestparams.stmix = 0.778088f;
break;
case 5:
// current score 3740 (63)
bestparams.threshold = 1.f;
bestparams.pulsestrength = 3.62465143f;
bestparams.distance1 = 0.986276627f;
bestparams.distance2 = 1.09922075f;
break;
case 6:
// current score 748 (58)
bestparams.threshold = 0.912882149f;
bestparams.pulsestrength = 2.45562696f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.128567815f;
bestparams.distance2 = 0.148435056f;
break;
case 7:
// current score 38 (14)
bestparams.threshold = 0.901118755f;
bestparams.pulsestrength = 0.904124081f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.05176663f;
bestparams.distance2 = 1.10776162f;
bestparams.stmix = 0.618260384f;
break;
}
break;
// 6581 R4AR
case 'R':
switch (wave)
{
case 3:
// current score 2070 (341)
bestparams.threshold = 0.888629317f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.94586849f;
bestparams.distance2 = 2.01927376f;
bestparams.stmix = 0.600944996f;
break;
case 5:
// current score 7211 (272)
bestparams.threshold = 0.928046405f;
bestparams.pulsestrength = 2.5883441f;
bestparams.distance1 = 1.01187634f;
bestparams.distance2 = 1.15885961f;
break;
case 6:
// current score 23276 (420)
bestparams.threshold = 0.872620344f;
bestparams.pulsestrength = 2.25908351f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.11984051f;
bestparams.distance2 = 0.0987310335f;
break;
case 7:
// current score 274 (30)
bestparams.threshold = 0.91457653f;
bestparams.pulsestrength = 1.32809377f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.11845613f;
bestparams.distance2 = 1.16926301f;
bestparams.stmix = 0.791111946f;
break;
}
break;
// 6581 R4AR
case 'S':
switch (wave)
{
case 3:
// current score 1724 (124)
bestparams.threshold = 0.973066f;
bestparams.topbit = 0.f;
bestparams.distance1 = 3.57771f;
bestparams.stmix = 0.747192f;
break;
case 5:
// current score 6264 (226)
bestparams.threshold = 0.900257707f;
bestparams.pulsestrength = 1.89190149f;
bestparams.distance1 = 1.05784476f;
bestparams.distance2 = 1.1705128f;
break;
case 6:
// current score 2006 (131)
bestparams.threshold = 0.917820513f;
bestparams.pulsestrength = 2.8137641f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.133098751f;
bestparams.distance2 = 0.139843836f;
break;
case 7:
// current score 148 (14)
bestparams.threshold = 0.933473349f;
bestparams.pulsestrength = 1.51940262f;
bestparams.topbit = 0.0075f;
bestparams.distance1 = 1.15147519f;
bestparams.distance2 = 1.23372996f;
bestparams.stmix = 0.693227589f;
break;
}
break;
// 6581 R4AR
case 'T':
switch (wave)
{
case 3:
// current score 290 (101)
bestparams.threshold = 0.965168953f;
bestparams.topbit = 0.f;
bestparams.distance1 = 3.04781175f;
bestparams.distance2 = 3.81387138f;
bestparams.stmix = 0.609185994f;
break;
case 5:
// current score 6138 (221)
bestparams.threshold = 0.991526306f;
bestparams.pulsestrength = 2.80080104f;
bestparams.distance1 = 0.993945718f;
bestparams.distance2 = 1.19684732f;
break;
case 6:
// current score 610 (15)
bestparams.threshold = 0.9087286f;
bestparams.pulsestrength = 2.26664352f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.158760354f;
bestparams.distance2 = 0.108530171f;
break;
case 7:
// current score 0
bestparams.threshold = 0.949945092f;
bestparams.pulsestrength = 1.60713959f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.01901114f;
bestparams.distance2 = 1.03737819f;
bestparams.stmix = 0.994224012f;
break;
}
break;
// 6581 R4AR
case 'U':
switch (wave)
{
case 3:
// current score 294 (94)
bestparams.threshold = 0.983248f;
bestparams.topbit = 0.f;
bestparams.distance1 = 4.63783f;
bestparams.stmix = 0.779401f;
break;
case 5:
// current score 6454 (259)
bestparams.threshold = 0.99398762f;
bestparams.pulsestrength = 3.14190888f;
bestparams.distance1 = 0.999676824f;
bestparams.distance2 = 1.16238594f;
break;
case 6:
// current score 840 (42)
bestparams.threshold = 0.903786302f;
bestparams.pulsestrength = 2.10020733f;
bestparams.topbit = 0.f;
bestparams.distance1 = 0.142474398f;
bestparams.distance2 = 0.139588535f;
break;
case 7:
// current score 6 (4)
bestparams.threshold = 0.925804496f;
bestparams.pulsestrength = 1.36537039f;
bestparams.topbit = 0.f;
bestparams.distance1 = 1.1688062f;
bestparams.distance2 = 1.32638979f;
bestparams.stmix = 0.509957671f;
break;
}
break;
// 8580
case 'V':
switch (wave)
{
case 3:
// current score 1380 (169)
bestparams.threshold = 0.9632f;
bestparams.topbit = 0.975f;
bestparams.distance1 = 1.7467f;
bestparams.distance2 = 2.36132f;
bestparams.stmix = 0.975395f;
break;
case 5:
// current score 7981 (204)
bestparams.threshold = 0.93303f;
bestparams.pulsestrength = 1.7025f;
bestparams.distance1 = 1.0868f;
bestparams.distance2 = 1.43527f;
break;
case 6:
// current score 9596 (324)
bestparams.threshold = 0.958310068f;
bestparams.pulsestrength = 1.95269263f;
bestparams.topbit = 0.992986143f;
bestparams.distance1 = 0.00773835462f;
bestparams.distance2 = 0.184085369f;
break;
case 7:
// current score 2120 (55)
bestparams.threshold = 0.945680082f;
bestparams.pulsestrength = 1.08290601f;
bestparams.topbit = 0.996945083f;
bestparams.distance1 = 0.935811639f;
bestparams.distance2 = 2.05300689f;
bestparams.stmix = 0.558153927f;
break;
}
break;
// 6582
case 'W':
switch (wave)
{
case 3:
// current score 2201 (242)
bestparams.threshold = 0.948997259f;
bestparams.topbit = 0.982420206f;
bestparams.distance1 = 2.0006547f;
bestparams.distance2 = 2.03388166f;
bestparams.stmix = 0.992275f;
break;
case 5:
// current score 8646 (214)
bestparams.threshold = 0.936479628f;
bestparams.pulsestrength = 1.86489666f;
bestparams.distance1 = 1.08213437f;
bestparams.distance2 = 1.47512901f;
break;
case 6:
// current score 12409 (501)
bestparams.threshold = 0.921457112f;
bestparams.pulsestrength = 1.63515782f;
bestparams.topbit = 0.99865073f;
bestparams.distance1 = 0.0453318208f;
bestparams.distance2 = 0.294430673f;
break;
case 7:
// current score 2149 (110)
bestparams.threshold = 0.997233212f;
bestparams.pulsestrength = 1.69910455f;
bestparams.topbit = 0.995346427f;
bestparams.distance1 = 0.861709118f;
bestparams.distance2 = 1.48027956f;
bestparams.stmix = 0.730670393f;
break;
}
break;
default:
break;
}
if (bestparams.distance2 == 0.f)
bestparams.distance2 = bestparams.distance1;
const bool is8580 = chip >= 'V';
// Calculate current score
score_t bestscore = bestparams.Score(wave, is8580, reference, true, 4096 * 255);
std::cout << "# initial score " << bestscore << std::endl << bestparams.toString() << std::endl << std::endl;
if (bestscore.audible_error == 0)
exit(0);
/*
* Start the Monte Carlo loop: we randomly alter parameters
* and calculate the new score until we find the best fitting
* waveform compared to the sampled data.
*/
Parameters p = bestparams;
for (;;)
{
// loop until at least one parameter has changed
bool changed = false;
while (!changed)
{
for (Param_t i = Param_t::THRESHOLD; i <= Param_t::STMIX; i++)
{
// PULSESTRENGTH only affects pulse
if ((i==Param_t::PULSESTRENGTH) && ((wave & 0x04) != 0x04))
{
continue;
}
// STMIX only affects saw/triangle mix
if ((i==Param_t::STMIX) && ((wave & 0x03) != 0x03))
{
continue;
}
// TOPBIT only affects saw
if ((i==Param_t::TOPBIT) && ((wave & 0x02) != 0x02))
{
continue;
}
// change a parameter with 50% proability
if (GetRandomValue() > 1.)
{
const float oldValue = bestparams.GetValue(i);
//std::cout << newValue << " -> ";
float newValue = static_cast<float>(GetRandomValue()*oldValue);
//float newValue = oldValue + GetRandomValue();
//std::cout << newValue << std::endl;
// try to avoid too small values
if (newValue < EPSILON)
newValue += GetNewRandomValue();
// check for parameters limits
if ((i == Param_t::STMIX || i == Param_t::THRESHOLD) && (newValue > 1.f)
/*|| (i == Param_t::DISTANCE) && (newValue < 1.f)*/)
{
newValue = 1.f;
}
p.SetValue(i, newValue);
changed = changed || oldValue != newValue;
}
}
}
// check new score
const score_t score = p.Score(wave, is8580, reference, false, bestscore.audible_error);
if (bestscore.isBetter(score))
{
// accept if improvement
std::cout << "# current score " << score << std::endl << p.toString() << std::endl << std::endl;
if (score.audible_error == 0)
exit(0);
//p.reset();
bestparams = p;
bestscore = score;
}
else if (score.audible_error == bestscore.audible_error)
{
// print the rate of wrong bits
std::cout << score.wrongBitsRate() << std::endl;
// no improvement but use new parameters as base to increase the "entropy"
bestparams = p;
}
}
}
/**
* Split a file into lines.
*/
static std::vector<std::string> split(const std::string &s, char delim)
{
std::vector<std::string> elems;
std::istringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
/**
* Read sampled values for specific waveform and chip.
*/
static ref_vector_t ReadChip(int wave, char chip)
{
std::cout << "Reading chip: " << chip << std::endl;
std::ostringstream fileName;
fileName << "sidwaves/WAVE" << wave << ".CSV";
std::ifstream ifs(fileName.str().c_str(), std::ifstream::in);
std::string line;
ref_vector_t result;
while (getline(ifs, line).good())
{
std::vector<std::string> values = split(line, ',');
result.push_back(atoi(values[chip - 'A'].c_str()));
}
return result;
}
int main(int argc, const char* argv[])
{
if (argc != 3)
{
std::cout << "Usage " << argv[0] << " <waveform> <chip>" << std::endl;
exit(-1);
}
const int wave = atoi(argv[1]);
assert(wave == 3 || wave == 5 || wave == 6 || wave == 7);
const char chip = argv[2][0];
assert(chip >= 'A' && chip <= 'Z');
ref_vector_t reference = ReadChip(wave, chip);
#ifndef NDEBUG
for (ref_vector_t::iterator it = reference.begin(); it != reference.end(); ++it)
std::cout << (*it) << std::endl;
#endif
srand(time(0));
Optimize(reference, wave, chip);
}