发布时间:2026-07-21阅读(1)
PCM(Pulse Code Modulation,脉冲编码调制),PCM音频数据是指经过采样、量化、编码转换成的未压缩数字音频数据。
WAV最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。
WAV格式组成

RIFF(Resource Interchange File Format,资源交换档案标准),是一种把资料储存在被标记的区块(tagged chunks)中的档案格式(meta-format),不同编码的音频/视频流按照RIFF所定义的存储规则保存,在读取播放时,就可以按照RIFF规则分析文件,正常解析出音频/视频流。
示例代码
按照上述定义,声明如下数据结构
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
struct RIFF_t { char ID[4]; uint32_t size; char format[4];};struct FMT_t { char ID[4]; uint32_t size; uint16_t audio_format; uint16_t channels; uint32_t sample_rate; uint32_t byte_rate; uint16_t block_align; uint16_t bits_per_sample;};struct DATA_t { char ID[4]; uint32_t size; //void*data;//此处因为数据需要从文件中边读取边存储,因此为了方便操作,不声明data};struct PCM_to_WAV_t { char *in_file_name; char *out_file_name; FILE *in_file; FILE *out_file; uint16_t pcm_data;//保存从PCM文件中读取的数据,因为PCM数据大小必然是16的倍数,所以声明为uint16_t struct RIFF_t riff; struct FMT_t fmt; struct DATA_t data;};
int PCM_to_WAV_Init(PCM_to_WAV_t *p2w, int argc, char** argv){ if (argc == 3) { p2w->in_file_name = argv[1]; p2w->fmt.sample_rate = 44100; p2w->fmt.channels = 2; p2w->fmt.bits_per_sample = 16; p2w->out_file_name = argv[2]; } else if (argc == 6) { p2w->in_file_name = argv[1]; p2w->fmt.sample_rate = atoi(argv[2]); p2w->fmt.channels = atoi(argv[3]); p2w->fmt.bits_per_sample = atoi(argv[4]); p2w->out_file_name = argv[5]; } else { printf("$.exe $.pcm $sample_rate $channels $bits_per_sample $.wav\n"); printf("Example: $.exe in.pcm 44100 2 16 out.wav\n"); printf("$.exe $.pcm $.wav\n"); printf("Example: $.exe in.pcm out.wav\n"); return -1; } p2w->pcm_data = 0; p2w->in_file = NULL; p2w->out_file = NULL; memcpy(p2w->riff.ID, "RIFF", 4); memcpy(p2w->riff.format, "WAVE", 4); p2w->riff.size = 36; memcpy(p2w->fmt.ID, "fmt ", 4); p2w->fmt.size = 16; p2w->fmt.audio_format = 1; p2w->fmt.byte_rate = p2w->fmt.sample_rate * p2w->fmt.channels * p2w->fmt.bits_per_sample / 8; p2w->fmt.block_align = p2w->fmt.channels * p2w->fmt.bits_per_sample / 8; memcpy(p2w->data.ID, "data", 4); p2w->data.size = 0; return 0;}
int PCM_to_WAV(PCM_to_WAV_t *p2w){ p2w->in_file = fopen(p2w->in_file_name, "rb "); p2w->out_file = fopen(p2w->out_file_name, "wb "); if (p2w->in_file == NULL || p2w->out_file == NULL) { printf("open file error\n"); return -1; } fseek(p2w->out_file, sizeof(struct RIFF_t), 1); fwrite(&p2w->fmt, sizeof(struct FMT_t), 1, p2w->out_file); fseek(p2w->out_file, sizeof(struct DATA_t), 1); fread(&p2w->pcm_data, sizeof(uint16_t), 1, p2w->in_file); while (! feof(p2w->in_file) ) { p2w->data.size = 2; fwrite(&p2w->pcm_data, sizeof(uint16_t), 1, p2w->out_file); fread(&p2w->pcm_data, sizeof(uint16_t), 1, p2w->in_file); } p2w->riff.size = p2w->data.size; rewind(p2w->out_file); fwrite(&p2w->riff, sizeof(struct RIFF_t), 1, p2w->out_file); fseek(p2w->out_file, sizeof(struct FMT_t), 1); fwrite(&p2w->data, sizeof(struct DATA_t), 1, p2w->out_file); fclose(p2w->in_file); fclose(p2w->out_file); return 0;}
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
void PCM_to_WAV_Info(PCM_to_WAV_t *p2w){ printf("in file: %s\nout file: %s\n", p2w->in_file_name, p2w->out_file_name); printf("RIFF: \n\tID: %4.4s\n\tsize: %d\n\tformat: %4.4s\n", p2w->riff.ID, p2w->riff.size, p2w->riff.format); printf("FMT: \n\tID: %4.4s\n\tSize: %d\n\tAudio fmt: %d\n\tChannels: %d\n", p2w->fmt.ID, p2w->fmt.size, p2w->fmt.audio_format, p2w->fmt.channels); printf("\tsample rate: %d\n\tByte Rate: %d\n\tBlock Align: %d\n\tBits Per Sample: %d\n", p2w->fmt.sample_rate, p2w->fmt.byte_rate, p2w->fmt.block_align, p2w->fmt.bits_per_sample); printf("DATA: \n\tID: %4.4s\n\tSize: %d\n", p2w->data.ID, p2w->data.size);}
int main(int argc, char **argv){ struct PCM_to_WAV_t pcm2wav; if (PCM_to_WAV_Init(&pcm2wav, argc, argv) != 0) return -1; if (PCM_to_WAV(&pcm2wav) != 0) return -1; PCM_to_WAV_Info(&pcm2wav); return 0;}
Copyright © 2024 有趣生活 All Rights Reserve吉ICP备19000289号-5 TXT地图HTML地图XML地图