一. 什么是wav
保存的音频文件是wav(waveform audio file format),wav是一种用于存储音频数据的文件格式,由微软和ibm联合开发。wav文件是无损的,存储的是原始音频数据,没有经过任意压缩或丢失信息。WAV 文件通常用于专业音频编辑、录音和音频播放。
wav文件格式
wav文件由多个块(chunk)组成,每个块都有特定的功能。以下是wav文件的基本结构:
char riff[4]; // "RIFF"
int filesize; // 文件大小
char wave[4]; // "WAVE"
char fmt_chunk_marker[4]; // "fmt "
int fmt_chunk_len; // 格式块长度 (通常是16)
short audio_format; // 音频格式 (1 表示 PCM)
short num_channels; // 声道数 (1 单声道, 2 立体声)
int sample_rate; // 采样率 (例如 44100 Hz)
int byte_rate; // 每秒字节数 (sample_rate * num_channels * (bits_per_sample/8))
short frame_size; // 每个样本的字节数 (num_channels * (bits_per_sample/8))
short bits_per_sample; // 每个样本的位数 (例如 16)
fmt_chunk_len 是用于标识 fmt 块长度的字段,通常是 16,它告诉解析 WAV 文件的软件或库,fmt 块中包含了多少字节的数据。这有助于正确解析音频格式信息。
num_channels 字段表示音频数据的声道数。
3. data块(数据块):包含实际的音频数据,大小取决于音频数据的长度
char data_chunk_header[8]; // "data"
int data_bytes; // 数据字节数
二. 音频专业词的解释
常见的声道数包括:单声道 (Mono): 一个声道、立体声 (Stereo): 两个声道
单声道 (Mono)
立体声 (Stereo)
在大多数情况下,单声道 是语音识别的首选。原因如下:
采样频率(sample rate)是一个非常重要的参数,它决定了每秒钟从模拟信息中提取多少个样本。常见的采样频率包括有8,000 Hz (8 kHz)、16,000 Hz (16 kHz)、22,050 Hz (22.05 kHz)和44,100 Hz (44.1 kHz)等
8,000 Hz (8 kHz)特点:低采样率,数据量小。质量:音质较低,通常只适用于语音通信,如电话和无线电通话。应用场景:电话网络、语音识别系统、低带宽通信
16,000 Hz (16 kHz)特点:中等采样率,数据量适中。质量:比 8 kHz 好,但仍主要用于语音通信。
应用场景:语音识别、语音助手、一些视频会议系统
22,050 Hz (22.05 kHz)特点:中等偏高的采样率,数据量较大。质量:音质较好,适合某些音乐和高质量语音应用。应用场景:CD 音频的一半速率(CD 音频标准是 44.1 kHz),有时用于压缩音频文件、某些专业录音设备、一些广播和流媒体应用
44,100 Hz (44.1 kHz)特点:高采样率,数据量大。质量:高质量音频,几乎可以完美再现大部分人类听觉范围内的声音。应用场景:CD 音轨和数字音频文件、音乐制作和专业录音、多媒体应用、高质量音频流媒体
还可以一个一个试,就这几个常见的采样频率。
修改采样频率的代码
从原始音频数据生成一个具有指定采样率的新音频数据。它通过线性插值的方法实现重采样,并更新音频缓冲区的相应属性(数据、帧数和采样率)。
int resample_audio(audio_buffer_t *audio, int desired_sample_rate) {
int original_sample_rate = audio->sample_rate;
int original_length = audio->num_frames;
int out_length = (int)round((double)original_length * (double)desired_sample_rate / (double)original_sample_rate);
printf("Resampling: %d Hz -> %d Hz\n", original_sample_rate, desired_sample_rate);
// 分配新的数据缓冲区
float *resampled_data = (float *)malloc(out_length * sizeof(float));
if (!resampled_data) {
fprintf(stderr, "Memory allocation failed\n");
return -1;
}
for (int i = 0; i < out_length; ++i) {
double src_index = i * (double)original_sample_rate / (double)desired_sample_rate;
int left_index = (int)floor(src_index);
int right_index = (left_index + 1 < original_length) ? left_index + 1 : left_index;
double fraction = src_index - left_index;
// 边界检查
if (left_index < 0) left_index = 0;
if (right_index >= original_length) right_index = original_length - 1;
resampled_data[i] = (1.0f - fraction) * audio->data[left_index] + fraction * audio->data[right_index];
}
// 更新 audio 缓冲区
free(audio->data);
audio->data = resampled_data;
audio->num_frames = out_length;
audio->sample_rate = desired_sample_rate;
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容