使用 fopen_s读取一个wav文件并对其求WVD并输出WVD结果不使用库函数C语言并解释代码
时间: 2024-05-01 19:22:29 浏览: 140
以下是使用 C 语言实现读取 WAV 文件并计算其 WVD 的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#define PI 3.14159265358979323846
typedef struct {
char ChunkID[4];
uint32_t ChunkSize;
char Format[4];
char Subchunk1ID[4];
uint32_t Subchunk1Size;
uint16_t AudioFormat;
uint16_t NumChannels;
uint32_t SampleRate;
uint32_t ByteRate;
uint16_t BlockAlign;
uint16_t BitsPerSample;
char Subchunk2ID[4];
uint32_t Subchunk2Size;
} wav_header_t;
int read_wav_header(FILE *fp, wav_header_t *header) {
if (fread(header, sizeof(wav_header_t), 1, fp) != 1) {
return -1;
}
return 0;
}
int32_t read_sample(FILE *fp, uint16_t bits_per_sample) {
int32_t sample = 0;
if (bits_per_sample == 8) {
uint8_t value;
if (fread(&value, sizeof(uint8_t), 1, fp) != 1) {
return 0;
}
sample = ((int32_t)value - 128) * (1 << 23);
} else if (bits_per_sample == 16) {
int16_t value;
if (fread(&value, sizeof(int16_t), 1, fp) != 1) {
return 0;
}
sample = (int32_t)value * (1 << 15);
} else if (bits_per_sample == 24) {
uint8_t buf[3];
if (fread(buf, sizeof(uint8_t), 3, fp) != 3) {
return 0;
}
sample = (((int32_t)buf[2] << 16) | ((int32_t)buf[1] << 8) | buf[0]) * (1 << 7);
} else if (bits_per_sample == 32) {
int32_t value;
if (fread(&value, sizeof(int32_t), 1, fp) != 1) {
return 0;
}
sample = value;
}
return sample;
}
void calc_wvd(int32_t *samples, int32_t num_samples, int32_t *wvd, int32_t num_wvd) {
const double alpha = 1.0 / (sqrt(2.0) * num_samples);
for (int32_t n = 0; n < num_wvd; n++) {
for (int32_t k = 0; k < num_samples; k++) {
double t = (double)n * k / num_wvd;
double w = alpha * exp(-2.0 * PI * pow((double)k / num_samples, 2.0));
double x = (double)samples[k] / (1 << 31);
wvd[n] += x * x * w * cos(2.0 * PI * t * k / num_samples);
}
}
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s input.wav output.wvd\n", argv[0]);
return EXIT_FAILURE;
}
FILE *input_file = NULL, *output_file = NULL;
if (fopen_s(&input_file, argv[1], "rb") != 0) {
fprintf(stderr, "Failed to open input file: %s\n", argv[1]);
return EXIT_FAILURE;
}
if (fopen_s(&output_file, argv[2], "wb") != 0) {
fprintf(stderr, "Failed to open output file: %s\n", argv[2]);
fclose(input_file);
return EXIT_FAILURE;
}
wav_header_t header;
if (read_wav_header(input_file, &header) != 0) {
fprintf(stderr, "Failed to read WAV header\n");
fclose(input_file);
fclose(output_file);
return EXIT_FAILURE;
}
if (header.NumChannels != 1) {
fprintf(stderr, "Only mono WAV files are supported\n");
fclose(input_file);
fclose(output_file);
return EXIT_FAILURE;
}
if (header.AudioFormat != 1) {
fprintf(stderr, "Only PCM WAV files are supported\n");
fclose(input_file);
fclose(output_file);
return EXIT_FAILURE;
}
int32_t num_samples = header.Subchunk2Size / (header.BitsPerSample / 8);
int32_t *samples = (int32_t *)malloc(num_samples * sizeof(int32_t));
if (samples == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
fclose(input_file);
fclose(output_file);
return EXIT_FAILURE;
}
for (int32_t i = 0; i < num_samples; i++) {
samples[i] = read_sample(input_file, header.BitsPerSample);
}
int32_t num_wvd = num_samples;
int32_t *wvd = (int32_t *)calloc(num_wvd, sizeof(int32_t));
if (wvd == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
free(samples);
fclose(input_file);
fclose(output_file);
return EXIT_FAILURE;
}
calc_wvd(samples, num_samples, wvd, num_wvd);
fwrite(wvd, sizeof(int32_t), num_wvd, output_file);
free(wvd);
free(samples);
fclose(input_file);
fclose(output_file);
return EXIT_SUCCESS;
}
```
代码的执行流程如下:
1. 打开输入文件和输出文件;
2. 读取 WAV 文件头信息;
3. 分配内存并读取 WAV 文件中的 PCM 数据;
4. 计算 WVD;
5. 将 WVD 结果写入输出文件;
6. 释放内存并关闭文件。
其中,`wav_header_t` 结构体定义了 WAV 文件的头信息。函数 `read_wav_header` 用于读取 WAV 文件头,函数 `read_sample` 用于读取一个样本。函数 `calc_wvd` 用于计算 WVD。在主函数中,首先根据命令行参数打开输入文件和输出文件,然后读取 WAV 文件头信息,接着读取 PCM 数据并计算 WVD,最后将 WVD 结果写入输出文件。注意,这里只支持单声道、PCM 编码的 WAV 文件。
阅读全文
相关推荐
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![pdf](https://img-home.csdnimg.cn/images/20241231044930.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)