cog/Frameworks/libsidplay/sidplay-residfp-code/.svn/pristine/d8/d8cb2c86d8d87446e116e0709d3...

331 lines
10 KiB
Plaintext

/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2013 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 <cstdlib>
#include <cassert>
#include <ctime>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include "parameters.h"
static double randomNextDouble()
{
return static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
}
static float GetRandomValue()
{
const float t = 1.f - (float) randomNextDouble() * 0.9f;
return (randomNextDouble() > 0.5) ? 1.f / t : t;
}
static void Optimize(const std::vector<int> &reference, int wave, char chip)
{
Parameters bestparams;
if (chip == 'D')
{
switch (wave)
{
case 3:
// current score 2740
bestparams.bias = 0.987103f;
bestparams.pulsestrength = 0.f;
bestparams.topbit = 0.f;
bestparams.distance = 37.294f;
bestparams.stmix = 0.783281f;
break;
case 5:
// current score 18404
bestparams.bias = 0.888048f;
bestparams.pulsestrength = 2.26606f;
bestparams.topbit = 0.99697f;
bestparams.distance = 0.0422943f;
bestparams.stmix = 0.f;
break;
case 6:
// current score 18839
bestparams.bias = 0.886823f;
bestparams.pulsestrength = 2.35161f;
bestparams.topbit = 1.77758f;
bestparams.distance = 0.0236612f;
bestparams.stmix = 0.f;
break;
case 7:
// current score 428
bestparams.bias = 0.928903f;
bestparams.pulsestrength = 1.4555f;
bestparams.topbit = 0.f;
bestparams.distance = 0.0791919f;
bestparams.stmix = 0.905484f;
break;
}
}
if (chip == 'E')
{
switch (wave)
{
case 3:
// current score 721
bestparams.bias = 0.957552f;
bestparams.pulsestrength = 0.f;
bestparams.topbit = 0.f;
bestparams.distance = 1.80014f;
bestparams.stmix = 0.698112f;
break;
case 5:
// current score 5552
bestparams.bias = 0.916105f;
bestparams.pulsestrength = 1.93374f;
bestparams.topbit = 1.00139f;
bestparams.distance = 0.0211841f;
bestparams.stmix = 0.f;
break;
case 6:
// current score 12
bestparams.bias = 0.935096f;
bestparams.pulsestrength = 2.64471f;
bestparams.topbit = 0.f;
bestparams.distance = 0.00538012f;
bestparams.stmix = 0.f;
break;
case 7:
// current score 120
bestparams.bias = 0.900499f;
bestparams.pulsestrength = 0.f;
bestparams.topbit = 0.f;
bestparams.distance = 0.f;
bestparams.stmix = 1.f;
break;
}
}
if (chip == 'G')
{
switch (wave)
{
case 3:
// current score 1741
bestparams.bias = 0.880592f;
bestparams.pulsestrength = 0.f;
bestparams.topbit = 0.f;
bestparams.distance = 0.327589f;
bestparams.stmix = 0.611491f;
break;
case 5:
// current score 11418
bestparams.bias = 0.892438f;
bestparams.pulsestrength = 2.00995f;
bestparams.topbit = 1.00392f;
bestparams.distance = 0.0298894f;
bestparams.stmix = 0.f;
break;
case 6:
// current score 21096
bestparams.bias = 0.863292f;
bestparams.pulsestrength = 1.69239f;
bestparams.topbit = 1.12637f;
bestparams.distance = 0.0335683f;
bestparams.stmix = 0.f;
break;
case 7:
// current score 78
bestparams.bias = 0.930481f;
bestparams.pulsestrength = 1.42322f;
bestparams.topbit = 0.f;
bestparams.distance = 0.0481732f;
bestparams.stmix = 0.752611f;
break;
}
}
if (chip == 'V')
{
switch (wave)
{
case 3:
// current score 5339
bestparams.bias = 0.979807f;
bestparams.pulsestrength = 0.f;
bestparams.topbit = 0.990736f;
bestparams.distance = 9.22678f;
bestparams.stmix = 0.824563f;
break;
case 5:
// current score 18507
bestparams.bias = 0.909646f;
bestparams.pulsestrength = 2.03944f;
bestparams.topbit = 0.958471f;
bestparams.distance = 0.175597f;
bestparams.stmix = 0.f;
break;
case 6:
// current score 16763
bestparams.bias = 0.918338f;
bestparams.pulsestrength = 2.41154f;
bestparams.topbit = 0.927047f;
bestparams.distance = 0.171891f;
bestparams.stmix = 0.f;
break;
case 7:
// current score 3199
bestparams.bias = 0.984532f;
bestparams.pulsestrength = 1.53602f;
bestparams.topbit = 0.961933f;
bestparams.distance = 3.46871f;
bestparams.stmix = 0.803955f;
break;
}
}
if (chip == 'W')
{
switch (wave)
{
case 3:
// current score 6648
bestparams.bias = 0.986102f;
bestparams.pulsestrength = 0.f; // 458120
bestparams.topbit = 0.995344f;
bestparams.distance = 8.64964f;
bestparams.stmix = 0.957502f;
break;
case 5:
// current score 24634
bestparams.bias = 0.906838f;
bestparams.pulsestrength = 2.23245f;
bestparams.topbit = 0.958234f;
bestparams.distance = 0.205228f;
bestparams.stmix = 0.0475253f;
break;
case 6:
// current score 22693
bestparams.bias = 0.889691f;
bestparams.pulsestrength = 1.64253f;
bestparams.topbit = 0.977121f;
bestparams.distance = 0.293443f;
bestparams.stmix = 0.f; // 4.65769e-013
break;
case 7:
// current score 5182
bestparams.bias = 0.956644f;
bestparams.pulsestrength = 1.50249f;
bestparams.topbit = 0.943326f;
bestparams.distance = 0.520891f;
bestparams.stmix = 0.956507f;
break;
}
}
int bestscore = bestparams.Score(wave, reference, true, 4096 * 255);
std::cout << "# initial score " << bestscore << std::endl << std::endl;
Parameters p;
for (;;)
{
bool changed = false;
while (! changed)
{
for (int i = Parameters::BIAS; i <= Parameters::STMIX; i++)
{
const float oldValue = bestparams.GetValue(i);
float newValue = oldValue;
if (randomNextDouble() > 0.5)
{
newValue *= GetRandomValue();
if ((i == Parameters::STMIX) && (newValue > 1.f))
{
newValue = 1.f;
}
}
p.SetValue(i, newValue);
changed = changed || oldValue != newValue;
}
}
const int score = p.Score(wave, reference, false, bestscore);
/* accept if improvement */
if (score <= bestscore)
{
bestparams = p;
p.reset();
bestscore = score;
std::cout << "# current score " << score << std::endl << bestparams.toString() << std::endl << std::endl;
}
}
}
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;
}
static std::vector<int> ReadChip(int wave, char chip)
{
std::cout << "Reading chip: " << chip << std::endl;
std::vector<int> result;
std::ostringstream fileName;
fileName << "sidwaves/WAVE" << wave << ".CSV";
std::ifstream ifs(fileName.str().c_str(), std::ifstream::in);
std::string line;
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');
std::vector<int> reference = ReadChip(wave, chip);
#ifndef NDEBUG
for (std::vector<int>::iterator it = reference.begin(); it != reference.end(); ++it)
std::cout << (*it) << std::endl;
#endif
srand(time(0));
Optimize(reference, wave, chip);
}