基于三次样条插值(自然边界)实现的上采样

该程序定义了一系列宏来处理32位浮点数与样本值之间的转换,并使用样条插值方法进行数据计算。通过Spline_CaculateM函数计算样条多项式,然后在Spline函数中应用这些多项式来获取特定x值的插值。主函数中,程序从文件读取样本数据,进行转换和插值计算,然后将结果写入新文件。
摘要由CSDN通过智能技术生成
#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#define SOX_INT_MAX(bits) (((unsigned)-1)>>(33-(bits)))
#define SOX_INT_MIN(bits) (1 <<((bits)-1))

#define SOX_SAMPLE_MAX (long)SOX_INT_MAX(32)
#define SOX_SAMPLE_MIN (long)SOX_INT_MIN(32)

#define SOX_FLOAT_32BIT_TO_SAMPLE(d,clips) (long)((d)*(SOX_SAMPLE_MAX+1.)<SOX_SAMPLE_MIN?++(clips),SOX_SAMPLE_MIN:(d)*(SOX_SAMPLE_MAX+1.)>=SOX_SAMPLE_MAX+1.?(d)*(SOX_SAMPLE_MAX+1.)>SOX_SAMPLE_MAX+1.?++(clips),SOX_SAMPLE_MAX:SOX_SAMPLE_MAX:(d)*(SOX_SAMPLE_MAX+1.))

#define SOX_SAMPLE_TO_FLOAT_32BIT(d,clips) (float)((d)>SOX_SAMPLE_MAX-64?++(clips),1:((((d)+64)&~127)*(1./(SOX_SAMPLE_MAX+1.))))

void Spline_CaculateM(const double *arr, const int len, double *M, double *h)
{
    // double *h = (double *)calloc(sizeof(double), len); 
    double *b = (double *)calloc(sizeof(double), len);
    double *c = (double *)calloc(sizeof(double), len);
    double *d = (double *)calloc(sizeof(double), len);
    double *u = (double *)calloc(sizeof(double), len);
    double *v = (double *)calloc(sizeof(double), len);
	double *y = (double *)calloc(sizeof(double), len);

    M[0] = M[len-1] = 0;

    h[0] = 1.0;
    for (int i = 1; i < len; i++) {
        h[i] = 1.0;
        b[i] = h[i] / (h[i] + h[i - 1]);
        c[i] = 1 - b[i];
        d[i] = 6 * ((arr[i + 1]- arr[i]) / h[i] - (arr[i] - arr[i - 1]) / h[i - 1]) / (h[i] + h[i - 1]);
    }

    d[1] -= c[1] * M[0];
    d[len - 1] -= b[len - 1] * M[len - 1];
    b[len - 1] = 0; c[1] = 0; v[0] = 0;
    for (int i = 1; i < len; i++) {
        u[i] = 2 - c[i] * v[i - 1];
        v[i] = b[i] / u[i];
        y[i] = (d[i] - c[i] * y[i - 1]) / u[i];
	}
    for (int i = 1; i < len; i++) {
        M[len - i] = y[len - i] - v[len - i] * M[len - i + 1];
    }

    free(b);
    free(c);
    free(d);
    free(u);
    free(v);
    free(y);
}

double Spline(const double *arr, const double *M, const double *h, double spline_x) 
{
    double p, q, S;

    // while (spline_x >= points[k].x) k++;
    int k = ceil(spline_x);

    p = k - spline_x;
    k = k - 1;
    q = spline_x - k;
    S = (p* p* p* M[k] + q* q* q* M[k + 1]) / (6 * h[k]) + (p* arr[k] + q*arr[k + 1]) / h[k] - h[k] * (p* M[k] + q* M[k + 1]) / 6;

    return S;
}

int main(int argc, char *argv[])
{
    FILE *fin  = fopen(argv[1], "r");
    FILE *fout = fopen(argv[2], "wb+");

    double data[6];
    double M[6];
    double h[6];
    short s[6];
    int clip = 0;
    while (1)
    {
        int len = fread(s, sizeof(short), 6, fin);
        for (int i = 0; i < 6; i++) {
            data[i] = SOX_SAMPLE_TO_FLOAT_32BIT(s[i] << 16, clip);
            printf("%lf %d ", data[i], s[i]);
        }

        Spline_CaculateM(data, 6, M, h);
        double ret = Spline(data, M, h, 0.5);
        short new = (SOX_FLOAT_32BIT_TO_SAMPLE(ret, clip)) >> 16;
        printf("(%lf, %d)\n", ret, new);
        fwrite(&s[0], sizeof(short), 1, fout);
        fwrite(&new, sizeof(short), 1, fout);

        if (feof(fin))
            break;

        fseek(fin, -5*sizeof(short), SEEK_CUR);
    }

    fclose(fin);
    fclose(fout);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值