Hi - I'm not extremely versed in digital modes, but I am well versed in
optimization. I think that HAM radio should be something open source, which
is why Codec2 appeals to me.

Before I post a large blob of C code, I wanted to mention that I have a
program that I have written a genetic optimizer to move spline knots around
- and I'd be happy to run the optimizer based on BER/PER ... however ... I
need someone to explain to me how I might generate quantities to optimize
on. I don't need bunches of help, just enough so that I can write it myself.

I found that the 16-sample clamped endpoint spline with log-spaced samples
worked the best, so I'll chop out the higher sample density parts of the
code. My hope was faster AND more accurate, but I think all I got was
faster and LESS accurate. Perhaps wiser eyes than mine can help me out.

The test script that I was using was:
#!/bin/sh
./ldpc_enc /dev/zero - --sd --code HRA_112_112 --testframes 100 \
    | ./ldpc_noise - - 1 \
    | ./ldpc_dec - /dev/null --code HRA_112_112 --sd --testframes

The code is (simply replace phi0.c with this):
// phi0.c
#include <stdint.h>
#include <stddef.h>

float coeffs_clamped_16[16] = {
    7.93223341e+07, 1.55433768e+07, 3.60871810e+06, 7.33752374e+05,
    1.65434845e+05, 3.44055511e+04, 7.62050634e+03, 1.60695364e+03,
    3.52218272e+02, 7.50245180e+01, 1.64584579e+01, 3.63755151e+00,
    8.75888035e-01, 1.72673513e-01, 6.76273536e-03, -7.75296180e-03};

float x_16[16] = {
    1.00000000e-04, 2.15443469e-04, 4.64158883e-04, 1.00000000e-03,
    2.15443469e-03, 4.64158883e-03, 1.00000000e-02, 2.15443469e-02,
    4.64158883e-02, 1.00000000e-01, 2.15443469e-01, 4.64158883e-01,
    1.00000000e+00, 2.15443469e+00, 4.64158883e+00, 1.00000000e+01};

float y_16[16] = {
    9.90348755e+00, 9.13595919e+00, 8.36843084e+00, 7.60090254e+00,
    6.83337448e+00, 6.06584753e+00, 5.29832570e+00, 4.53082768e+00,
    3.76344015e+00, 2.99656512e+00, 2.23206146e+00, 1.47840690e+00,
    7.71936833e-01, 2.32985688e-01, 1.92853284e-02, 9.07998596e-05};


static size_t
bisect(float x, float *restrict x_data, size_t size)
{
    size_t left = 0;
    size_t right = size - 1;
    int max_iterations = 32; /* waay higher than we need */

    while (right - left > 1 && max_iterations--) {
        size_t middle = left + (right - left)/2;
        float xm = x_data[middle];
        if (x < xm)
            right = middle;
        else if (xm < x)
            left = middle;
    }

    return left;
}


static float
spline_interpolate(float x,
                   float *restrict x_data,
                   float *restrict y_data,
                   float *restrict M,
                   size_t size) {
    size_t i = bisect(x, x_data, size);
    float h = x_data[i + 1] - x_data[i];
    float z = (x - x_data[i])/h;
    float h2 = h * h;

    float c1 = (M[i + 1] - M[i]) * h2 / 6.0;
    float c2 = M[i] * h2 / 2.0;
    float c3 = y_data[i + 1] - y_data[i] - (M[i + 1] + 2.0 * M[i]) * h2 /
6.0;

    return ((c1 * z + c2) * z + c3) * z + y_data[i];
}


extern float
phi0(float x) {
    if (x <= x_16[0])
        return 10.0f;
    if (x >= x_16[15])
        return 0.0f;

    return spline_interpolate(x, x_16, y_16, coeffs_clamped_16, 16);
}
_______________________________________________
Freetel-codec2 mailing list
Freetel-codec2@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freetel-codec2

Reply via email to