cog/Frameworks/libsidplay/sidplay-residfp-code/combined-waveforms/old/combined.cs

384 lines
12 KiB
C#
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
namespace sidwaveforms {
class Parameters {
public float bias, pulsestrength, topbit, distance, stmix;
public int Score(int wave, int[] reference, bool print, int bestscore) {
var score = 0;
var wa = new float[12 + 12 + 1];
for (var i = 0; i <= 12; i ++) {
wa[12-i] = wa[12+i] = 1.0f / (1.0f + i * i * distance);
}
for (var j = 4095; j >= 0; j --) {
/* S */
var bitarray = new float[12];
for (var i = 0; i < 12; i ++)
bitarray[i] = (j & (1 << i)) != 0 ? 1f : 0f;
/* T */
if ((wave & 3) == 1) {
var top = (j & 2048) != 0;
for (var i = 11; i > 0; i --) {
if (top) {
bitarray[i] = 1f - bitarray[i-1];
} else {
bitarray[i] = bitarray[i-1];
}
}
bitarray[0] = 0;
}
/* ST */
if ((wave & 3) == 3) {
bitarray[0] *= stmix;
for (var i = 1; i < 12; i ++) {
bitarray[i] = bitarray[i-1] * (1f - stmix) + bitarray[i] * stmix;
}
}
bitarray[11] *= topbit;
SimulateMix(bitarray, wa, wave > 4);
var simval = GetScore8(bitarray);
var refval = reference[j];
score += ScoreResult(simval, refval);
if (print) {
float analogval = 0;
for (int i = 0; i < 12; i ++) {
float val = (bitarray[i] - bias) * 512 + 0.5f;
if (val < 0)
val = 0;
if (val > 1)
val = 1;
analogval += val * (1 << i);
}
analogval /= 16f;
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", j, refval, simval, analogval));
}
if (score > bestscore) {
return score;
}
}
return score;
}
private void SimulateMix(float[] bitarray, float[] wa, bool HasPulse) {
var tmp = new float[12];
for (int sb = 0; sb < 12; sb ++) {
var n = 0f;
var avg = 0f;
for (var cb = 0; cb < 12; cb ++) {
var weight = wa[sb - cb + 12];
avg += bitarray[cb] * weight;
n += weight;
}
if (HasPulse) {
var weight = wa[sb - 12 + 12];
avg += pulsestrength * weight;
n += weight;
}
tmp[sb] = bitarray[sb] * 0.50f + avg / n * 0.50f;
}
for (var i = 0; i < 12; i ++)
bitarray[i] = tmp[i];
}
private int GetScore8(float[] bitarray) {
var result = 0;
for (var cb = 0; cb < 8; cb ++) {
if (bitarray[4+cb] > bias)
result |= 1 << cb;
}
return result;
}
private static int ScoreResult(int a, int b) {
var v = a ^ b;
return v;
/* var c = 0;
while (v != 0) {
v &= v - 1;
c ++;
}
return c;
*/
}
public override string ToString() {
return string.Format(CultureInfo.InvariantCulture,
@"bestparams.bias = {0}f;
bestparams.pulsestrength = {1}f;
bestparams.topbit = {2}f;
bestparams.distance = {3}f;
bestparams.stmix = {4}f;
new waveformconfig_t({0}f, {1}f, {2}f, {3}f, {4}f)",
bias, pulsestrength, topbit, distance, stmix
);
}
}
class Optimizer {
static readonly Random random = new Random();
private static float GetRandomValue() {
var t = 1f - (float) random.NextDouble() * 0.9f;
if (random.NextDouble() > 0.5) {
return 1f / t;
} else {
return t;
}
}
private static void Optimize(int[] reference, int wave, char chip)
{
var bestparams = new Parameters();
if (chip == 'D') {
switch (wave) {
case 3:
// current score 240
bestparams.bias = 0.9634957f;
bestparams.pulsestrength = 0f;
bestparams.topbit = 0f;
bestparams.distance = 4.165269f;
bestparams.stmix = 0.8020396f;
break;
case 5:
// current score 600
bestparams.bias = 0.8931507f;
bestparams.pulsestrength = 2.483499f;
bestparams.topbit = 1.0f;
bestparams.distance = 0.03339716f;
bestparams.stmix = 0f;
break;
case 6:
// current score 613
bestparams.bias = 0.8869214f;
bestparams.pulsestrength = 2.440879f;
bestparams.topbit = 1.680824f;
bestparams.distance = 0.02267573f;
bestparams.stmix = 0f;
break;
case 7:
// current score 32
bestparams.bias = 0.9842906f;
bestparams.pulsestrength = 2.772751f;
bestparams.topbit = 0f;
bestparams.distance = 0.4342486f;
bestparams.stmix = 1f;
break;
}
}
if (chip == 'E') {
switch (wave) {
case 3:
// current score 112
bestparams.bias = 0.9689716f;
bestparams.pulsestrength = 0f;
bestparams.topbit = 0f;
bestparams.distance = 3.088513f;
bestparams.stmix = 0.7588146f;
break;
case 5:
// current score 166
bestparams.bias = 0.9161022f;
bestparams.pulsestrength = 1.879311f;
bestparams.topbit = 1.0f;
bestparams.distance = 0.02331964f;
bestparams.stmix = 0f;
break;
case 6:
// current score 10
bestparams.bias = 0.879145f;
bestparams.pulsestrength = 1.30156f;
bestparams.topbit = 0f;
bestparams.distance = 0.006426161f;
bestparams.stmix = 0f;
break;
case 7:
// current score 8
bestparams.bias = 0.911324f;
bestparams.pulsestrength = 2.959469E-07f;
bestparams.topbit = 0f;
bestparams.distance = 4.148929E-06f;
bestparams.stmix = 1f;
break;
}
}
if (chip == 'G') {
switch (wave) {
case 3:
// current score 188
bestparams.bias = 0.9506974f;
bestparams.pulsestrength = 0f;
bestparams.topbit = 0f;
bestparams.distance = 2.104169f;
bestparams.stmix = 0.7887034f;
break;
case 5:
// current score 360
bestparams.bias = 0.8924618f;
bestparams.pulsestrength = 2.01122f;
bestparams.topbit = 1.0f;
bestparams.distance = 0.03133072f;
bestparams.stmix = 0f;
break;
case 6:
// current score 668
bestparams.bias = 0.8952018f;
bestparams.pulsestrength = 2.213601f;
bestparams.topbit = 1.705941f;
bestparams.distance = 0.01260567f;
bestparams.stmix = 0f;
break;
case 7:
// current score 12
bestparams.bias = 0.9527834f;
bestparams.pulsestrength = 1.794777f;
bestparams.topbit = 0f;
bestparams.distance = 0.09806272f;
bestparams.stmix = 0.7752482f;
break;
}
}
if (chip == 'V') {
switch (wave) {
case 3:
// current score 5546
bestparams.bias = 0.9781665f;
bestparams.pulsestrength = 0f;
bestparams.topbit = 0.9899469f;
bestparams.distance = 8.077209f;
bestparams.stmix = 0.8226412f;
break;
case 5:
// current score 628
bestparams.bias = 0.9236207f;
bestparams.pulsestrength = 2.19129f;
bestparams.topbit = 1f;
bestparams.distance = 0.1108298f;
bestparams.stmix = 0f;
break;
case 6:
// current score 593
bestparams.bias = 0.9248214f;
bestparams.pulsestrength = 2.232846f;
bestparams.topbit = 0.9491023f;
bestparams.distance = 0.1313893f;
bestparams.stmix = 0f;
break;
case 7:
// current score 168
bestparams.bias = 0.9845552f;
bestparams.pulsestrength = 1.381085f;
bestparams.topbit = 0.9621315f;
bestparams.distance = 1.699522f;
bestparams.stmix = 1f;
break;
}
}
if (chip == 'W') {
switch (wave) {
case 3:
// current score 315
bestparams.bias = 0.9686383f;
bestparams.pulsestrength = 0f;
bestparams.topbit = 0.9955494f;
bestparams.distance = 2.141501f;
bestparams.stmix = 0.9635284f;
break;
case 5:
// current score 784
bestparams.bias = 0.9069195f;
bestparams.pulsestrength = 2.203437f;
bestparams.topbit = 1f;
bestparams.distance = 0.129717f;
bestparams.stmix = 0f;
break;
case 6:
// current score 757
bestparams.bias = 0.9075199f;
bestparams.pulsestrength = 2.180424f;
bestparams.topbit = 0.9760311f;
bestparams.distance = 0.1208313f;
bestparams.stmix = 0f;
break;
case 7:
// current score 211
bestparams.bias = 0.9882526f;
bestparams.pulsestrength = 1.736355f;
bestparams.topbit = 0.9395381f;
bestparams.distance = 2.698372f;
bestparams.stmix = 1f;
break;
}
}
var bestscore = bestparams.Score(wave, reference, true, 4096 * 255);
Console.Write("# initial score {0}\n\n", bestscore);
var p = new Parameters();
while (true) {
var changed = false;
while (! changed) {
foreach (var el in new string[] { "bias", "pulsestrength", "topbit", "distance", "stmix" }) {
var field = typeof(Parameters).GetField(el);
var oldValue = (float) field.GetValue(bestparams);
var newValue = oldValue;
if (random.NextDouble() > 0.5) {
newValue *= GetRandomValue();
if (el == "stmix") {
if (newValue > 1f)
newValue = 1f;
}
}
field.SetValue(p, newValue);
changed = changed || oldValue != newValue;
}
}
var score = p.Score(wave, reference, false, bestscore);
/* accept if improvement */
if (score <= bestscore) {
bestparams = p;
p = new Parameters();
bestscore = score;
Console.Write("# current score {0}\n{1}\n\n", score, bestparams);
}
}
}
private static int[] ReadChip(int wave, char chip) {
Console.WriteLine("Reading chip: {0}", chip);
var result = new int[4096];
var i = 0;
foreach (var line in
File.ReadAllLines(string.Format("sidwaves/WAVE{0:X}.CSV", wave))
) {
var values = line.Split(',');
result[i ++] = Convert.ToInt32(values[chip - 'A']);
}
return result;
}
public static void Main(string[] args) {
var wave = int.Parse(args[0]);
Debug.Assert(wave == 3 || wave == 5 || wave == 6 || wave == 7);
var chip = char.Parse(args[1]);
Debug.Assert(chip >= 'A' && chip <= 'Z');
var reference = ReadChip(wave, chip);
Optimize(reference, wave, chip);
}
}
}