使用 fopen_s读取一个wav文件并对其求WVD并输出WVD结果不使用库函数C语言并解释代码
时间: 2024-06-08 21:08:32 浏览: 140
首先,需要了解以下WVD(Wigner-Ville Distribution)的概念和计算方法。WVD是一种时频分析方法,可以将信号在时间和频率两个维度上进行分析,得到时频分布图。
下面是一个简单的C语言程序,用于读取wav文件并对其求WVD:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PI 3.1415926
typedef struct
{
char RIFF[4];
unsigned long ChunkSize;
char WAVE[4];
char fmt[4];
unsigned long Subchunk1Size;
unsigned short AudioFormat;
unsigned short NumChannels;
unsigned long SampleRate;
unsigned long ByteRate;
unsigned short BlockAlign;
unsigned short BitsPerSample;
char data[4];
unsigned long Subchunk2Size;
} WavHeader;
// 计算WVD
void wvd(double *x, int N, double *wvd_out)
{
int k, l, n;
double tau, t, f, re, im, tmp;
// 初始化输出数组
memset(wvd_out, 0, sizeof(double)*N*N);
for (k = 0; k < N; k++)
{
for (l = 0; l < N; l++)
{
for (n = 0; n < N; n++)
{
tau = (double)(n - N / 2);
t = (double)(k - N / 2);
f = (double)(l - N / 2);
re = x[n] * x[n + (int)tau];
im = 0.0;
tmp = cos(2 * PI * f * tau / N) + sin(2 * PI * f * tau / N);
re *= tmp;
im *= tmp;
wvd_out[l*N+k] += re;
}
}
}
}
int main()
{
FILE *fp;
WavHeader header;
double *data, *wvd_out;
int i, j, N;
fp = fopen("test.wav", "rb");
if (fp == NULL)
{
printf("Failed to open file.\n");
return -1;
}
// 读取头部信息
fread(&header, sizeof(WavHeader), 1, fp);
// 获取采样率和采样点数
N = header.Subchunk2Size / header.NumChannels / (header.BitsPerSample / 8);
// 分配内存
data = (double*)malloc(sizeof(double)*N);
wvd_out = (double*)malloc(sizeof(double)*N*N);
// 读取音频数据
for (i = 0; i < N; i++)
{
if (header.BitsPerSample == 16)
{
short s;
fread(&s, sizeof(short), 1, fp);
data[i] = (double)s / 32768.0; // 将数据归一化到[-1, 1]区间
}
else if (header.BitsPerSample == 8)
{
unsigned char c;
fread(&c, sizeof(unsigned char), 1, fp);
data[i] = ((double)c - 128.0) / 128.0; // 将数据归一化到[-1, 1]区间
}
}
fclose(fp);
// 计算WVD
wvd(data, N, wvd_out);
// 输出WVD结果
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf("%lf ", wvd_out[i*N+j]);
}
printf("\n");
}
// 释放内存
free(data);
free(wvd_out);
return 0;
}
```
程序中的WavHeader结构体用于存储wav文件的头部信息,包括RIFF标志、文件大小、文件格式等。在读取wav文件时,先读取头部信息,然后根据采样率和采样点数计算出数据长度N,再根据数据长度动态分配内存。
读取音频数据时,根据采样位数来读取数据,如果是16位采样,则读取一个short类型的数据;如果是8位采样,则读取一个unsigned char类型的数据。
计算WVD时,通过三重循环遍历所有时频点,然后根据Wigner-Ville分布的公式计算每个时频点的值,最后将所有时频点的值存储在一个二维数组中,即为WVD结果。
输出WVD结果时,只需要将二维数组中的值逐个输出即可。
阅读全文