c语言读取wav音频文件输出浮点内容
时间: 2023-12-08 20:02:55 浏览: 154
你可以使用C语言中的文件操作函数和音频处理函数来实现该任务。下面是一个简单的示例代码,以读取16位PCM格式的wav文件为例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define WAV_HEADER_SIZE 44
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "usage: %s <wav file>\n", argv[0]);
return 1;
}
const char *filename = argv[1];
FILE *file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "could not open file: %s\n", filename);
return 1;
}
// read WAV header
uint8_t buf[WAV_HEADER_SIZE];
size_t n = fread(buf, 1, WAV_HEADER_SIZE, file);
if (n != WAV_HEADER_SIZE) {
fprintf(stderr, "could not read WAV header: %s\n", filename);
fclose(file);
return 1;
}
// check WAV format
if (buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F') {
fprintf(stderr, "not a WAV file: %s\n", filename);
fclose(file);
return 1;
}
uint32_t chunk_size = *(uint32_t *)(buf + 4);
if (buf[8] != 'W' || buf[9] != 'A' || buf[10] != 'V' || buf[11] != 'E') {
fprintf(stderr, "not a WAV file: %s\n", filename);
fclose(file);
return 1;
}
uint32_t fmtchunk_size = *(uint32_t *)(buf + 16);
if (buf[12] != 'f' || buf[13] != 'm' || buf[14] != 't' || buf[15] != ' ') {
fprintf(stderr, "invalid format chunk: %s\n", filename);
fclose(file);
return 1;
}
uint16_t audio_format = *(uint16_t *)(buf + 20);
if (audio_format != 1) {
fprintf(stderr, "unsupported audio format: %d\n", audio_format);
fclose(file);
return 1;
}
uint16_t num_channels = *(uint16_t *)(buf + 22);
uint32_t sample_rate = *(uint32_t *)(buf + 24);
uint16_t bits_per_sample = *(uint16_t *)(buf + 34);
uint32_t data_size = 0;
while (buf[36] != 'd' || buf[37] != 'a' || buf[38] != 't' || buf[39] != 'a') {
if (buf[36] == 'f' && buf[37] == 'a' && buf[38] == 'c' && buf[39] == 't') {
data_size = *(uint32_t *)(buf + 44);
}
uint32_t chunk_size = *(uint32_t *)(buf + 4);
fseek(file, chunk_size, SEEK_CUR);
n = fread(buf, 1, 8, file);
if (n != 8) {
fprintf(stderr, "could not read WAV chunk: %s\n", filename);
fclose(file);
return 1;
}
}
data_size = *(uint32_t *)(buf + 40);
// read WAV data
size_t num_samples = data_size / (num_channels * bits_per_sample / 8);
float *samples = (float *)malloc(sizeof(float) * num_samples);
if (!samples) {
fprintf(stderr, "could not allocate memory\n");
fclose(file);
return 1;
}
if (bits_per_sample == 16) {
int16_t sample16;
for (size_t i = 0; i < num_samples; i++) {
for (size_t j = 0; j < num_channels; j++) {
n = fread(&sample16, 2, 1, file);
if (n != 1) {
fprintf(stderr, "could not read WAV data: %s\n", filename);
fclose(file);
free(samples);
return 1;
}
samples[i] += (float)sample16 / 32768.0f;
}
}
} else if (bits_per_sample == 32) {
int32_t sample32;
for (size_t i = 0; i < num_samples; i++) {
for (size_t j = 0; j < num_channels; j++) {
n = fread(&sample32, 4, 1, file);
if (n != 1) {
fprintf(stderr, "could not read WAV data: %s\n", filename);
fclose(file);
free(samples);
return 1;
}
samples[i] += (float)sample32 / 2147483648.0f;
}
}
} else {
fprintf(stderr, "unsupported bits per sample: %d\n", bits_per_sample);
fclose(file);
free(samples);
return 1;
}
fclose(file);
// print samples
for (size_t i = 0; i < num_samples; i++) {
printf("%f\n", samples[i]);
}
free(samples);
return 0;
}
```
其中,`fread` 函数用于从文件中读取数据,`fseek` 函数用于定位文件指针,可通过 WAV 文件格式规范了解更多细节。
阅读全文