C语言读取wav音频实例
时间: 2023-06-05 19:07:54 浏览: 268
你好!很高兴为你解答问题。以下是 C语言读取wav音频文件的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> // For uint8_t, etc.
#include <stdbool.h> // For true/false
/*
* Struct representing the format chunk of a wav file.
*/
typedef struct {
uint16_t audio_format;
uint16_t num_channels;
uint32_t sample_rate;
uint32_t byte_rate;
uint16_t block_align;
uint16_t bits_per_sample;
} wav_format_t;
/*
* Read a little-endian unsigned 16-bit value from a file.
*/
uint16_t read_le_u16(FILE* file) {
uint8_t lo, hi;
lo = fgetc(file);
hi = fgetc(file);
return (hi << 8) | lo;
}
/*
* Read a little-endian unsigned 32-bit value from a file.
*/
uint32_t read_le_u32(FILE* file) {
uint8_t b0, b1, b2, b3;
b0 = fgetc(file);
b1 = fgetc(file);
b2 = fgetc(file);
b3 = fgetc(file);
return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
}
/*
* Read a format chunk from a wav file.
*/
bool read_format(FILE* file, wav_format_t* format) {
uint32_t chunk_size;
uint16_t audio_format;
// Read chunk size and audio format.
if (fread(&chunk_size, 4, 1, file) != 1 ||
fread(&audio_format, 2, 1, file) != 1) {
return false;
}
format->audio_format = audio_format;
// If audio format is not PCM, we can't handle the file.
if (audio_format != 1) {
return false;
}
// Read the remaining fields of the format chunk.
format->num_channels = read_le_u16(file);
format->sample_rate = read_le_u32(file);
format->byte_rate = read_le_u32(file);
format->block_align = read_le_u16(file);
format->bits_per_sample = read_le_u16(file);
// We've read the format chunk successfully.
return true;
}
/*
* Read a data chunk from a wav file.
*/
bool read_data(FILE* file, uint8_t** data, uint32_t* num_samples, uint16_t num_channels, uint16_t bits_per_sample) {
uint32_t chunk_size;
// Read the chunk size.
if (fread(&chunk_size, 4, 1, file) != 1) {
return false;
}
// Allocate memory for the audio data.
*data = (uint8_t*)malloc(chunk_size);
if (!*data) {
return false;
}
// Read the audio data.
if (fread(*data, chunk_size, 1, file) != 1) {
free(*data);
return false;
}
// Calculate the number of audio samples.
*num_samples = chunk_size / ((bits_per_sample / 8) * num_channels);
// We've read the audio data successfully.
return true;
}
/*
* Load a wav file into memory.
*/
bool load_wav_file(const char* path, uint8_t** data, uint32_t* num_samples, wav_format_t* format) {
FILE* file;
// Open the file.
file = fopen(path, "rb");
if (!file) {
return false;
}
// Read the RIFF header.
if (fgetc(file) != 'R' || fgetc(file) != 'I' ||
fgetc(file) != 'F' || fgetc(file) != 'F') {
fclose(file);
return false;
}
// Skip the file size field.
fseek(file, 4, SEEK_CUR);
// Read the WAVE header.
if (fgetc(file) != 'W' || fgetc(file) != 'A' ||
fgetc(file) != 'V' || fgetc(file) != 'E') {
fclose(file);
return false;
}
// Read the format chunk.
if (!read_format(file, format)) {
fclose(file);
return false;
}
// Seek to the beginning of the next chunk.
while (fgetc(file) != 'd' || fgetc(file) != 'a' ||
fgetc(file) != 't' || fgetc(file) != 'a') {
if (feof(file)) {
fclose(file);
return false;
}
}
// Read the data chunk.
if (!read_data(file, data, num_samples, format->num_channels, format->bits_per_sample)) {
fclose(file);
return false;
}
// Close the file.
fclose(file);
// We've loaded the wav file successfully.
return true;
}
int main() {
uint8_t* data;
uint32_t num_samples;
wav_format_t format;
if (load_wav_file("example.wav", &data, &num_samples, &format)) {
printf("Loaded wav file with %u samples, %u channels, %u Hz, %u bits per sample\n",
num_samples, format.num_channels,
format.sample_rate, format.bits_per_sample);
// Do something with the audio data here...
free(data);
} else {
printf("Failed to load wav file\n");
}
return 0;
}
```
这段代码可以读取一个 wav 格式的音频文件,并将其缓存在内存中。如果加载成功,会输出音频的采样率、通道数、样本位数等信息。你可以在 "// Do something with the audio data here..." 这个注释后面做自己需要的处理。希望能对你有帮助!
阅读全文