音频数据可以进行很多处理,音量变化是其中一种。尝试将单声道16位采样精度的wav文件的音量,进行大小变化。
目录
- 功能要求
- 程序效果
- 实现步骤
- 代码示例
功能要求
将单声道16位采样精度的wav文件的音量,进行大小变化。 最小实现,输入直接在代码中给定。 1.输入: 转换前文件:a.wav 转换后文件:b.wav 音量增大倍数:3
2.wav文件头 使用标准头部结构:
类型 | 大小 | 值 |
资源交换文件标志 | 4字节 | “RIFF” |
文件总大小 | 4字节 | 与文件大小相关 |
WAV文件标志 | 4字节 | “WAVE” |
波形文件标志 | 4字节 | “fmt ” |
wav格式描述块大小 | 4字节 | 18 |
PCM波形格式种类 | 2字节 | 1,表示线性PCM编码 |
通道数 | 2字节 | 1,表示单声道 |
采样频率 | 4字节 | 40000次/秒 |
波形数据传输速率 | 4字节 | 80000字节/秒 |
每帧大小 | 2字节 | 2字节 |
采样精度 | 2字节 | 16位 |
额外描述信息 | 2字节 | 空,表示没有额外信息 |
PCM数据开始标志 | 4字节 | “data” |
PCM数据大小 | 4字节 | 与数据大小相关 |
程序效果
音量大小变为原来的3倍。
实现步骤
wav头直接读取拷贝,PCM数据帧部分,每一帧分别乘以系数3之后,写入转换后文件。
代码示例
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- //wav文件头结构
- struct WavHead
- {
- char RIFFId[4];//资源交换文件标志
- unsigned long int RIFFSize;//从下个地址到文件尾的总字节数
- char RIFFType[4];//WAV文件标志
- char formatId[4];//波形格式标志
- char formatSize[4]; //wav格式表述块大小
- short int audioFormat; //格式种类,“1”表示“线性PCM编码”
- short int numChannels; //通道数,“1”表示“单声道”,“2”表示“双声道”
- unsigned long int sampleRate; //采样频率
- unsigned long int byteRate; //波形数据传输速率(每秒平均字节数)
- short int blockAlign; //DATA数据块长度
- short int bitsPerSample; //PCM位宽
- short int cbSize; //可选部分,额外的描述信息
- char dataId[4];//PCM音频数据部分开始标志
- unsigned long int dataSize; //PCM音频数据部分大小
- }wavHead;
-
//文件操作用的指针 - FILE *fp_source = NULL;
- FILE *fp_target = NULL;
- unsigned int frame_size = 16; //帧大小为16bits,根据实际情况调整
- short int *frame_buffer = NULL; //读取每帧的指针,根据实际情况调整
- int vol = 3; //变化系数,3表示变为原来的3倍
- fp_source = fopen("a.wav", "rb"); //以只读方式打开a.wav文件
- fp_target = fopen("c.wav", "wb+"); //以刷新写入方式打开b.wav文件
- //打开失败时返回错误
- if ((NULL==fp_source) || (NULL==fp_target))
- {
- printf("open file error.\n");
- return -1;
- }
- //读取wav头并写入新文件
- fread(&wavHead, 1, sizeof(wavHead), fp_source);
- fwrite(&wavHead, 1, sizeof(wavHead), fp_target);
- //读取每一帧音频数据,并进行系数变化
- frame_buffer = (short int*)malloc(frame_size);
- while (frame_size == fread(frame_buffer, 1, frame_size, fp_source))
- {
- *frame_buffer = *frame_buffer*vol;
- //如果超过了最大值,或小于最小值,直接赋成极值情况
- if (*frame_buffer < -0x8000)
- {
- *frame_buffer = -0x8000;
- }else if (*frame_buffer > 0x7FFF)
- {
- *frame_buffer = 0x7FFF;
- }
- fwrite(frame_buffer, 1, frame_size, fp_target);
- }
- //释放文件资源,释放动态内存指针
- fclose(fp_source);
- fclose(fp_target);
- free(frame_buffer);
- return 0;
- }