一、音频怎么变成数据
声卡以固定的频率采样声波的电压值,每次采样得到一个数值。这些数值按时间顺序排列就是 PCM 数据。
声波(模拟信号): ╱╲ ╱╲ ╱╲ ╱╲
╱ ╲ ╱ ╲ ╱ ╲ ╱ ╲
采样(数字信号): █ █ █ █ █ █
↑ ↑ ↑ ↑ ↑ ↑
t0 t1 t2 t3 t4 t5
每隔 1/44100 秒采一次
二、三个关键参数
// 采样率(Sample Rate):每秒采多少次
// 44100 Hz = CD 音质
// 48000 Hz = 视频/DVD 标准
// 96000 Hz = 高解析度音频
// 位深(Bit Depth):每次采样用多少 bit 表示
// 16 bit = CD 音质,每个样本范围 -32768 ~ 32767
// 24 bit = 录音室级别
// float 32 = 音频处理内部格式
// 声道数(Channels):
// 1 = Mono
// 2 = Stereo(左右声道交织)
// 6 = 5.1 环绕声
// PCM 数据量计算
void calc_pcm_size(int sample_rate, int bit_depth, int channels, int duration_sec) {
int bytes_per_sample = bit_depth / 8;
int bytes_per_sec = sample_rate * bytes_per_sample * channels;
int total_bytes = bytes_per_sec * duration_sec;
printf("PCM 参数: %dHz/%dbit/%dch\n", sample_rate, bit_depth, channels);
printf("每秒: %d bytes (%.1f KB)\n", bytes_per_sec, bytes_per_sec / 1024.0);
printf("1 分钟: %d bytes (%.1f MB)\n", total_bytes, total_bytes / 1024.0 / 1024);
}
// calc_pcm_size(48000, 16, 2, 60);
// 输出:
// 每秒: 192000 bytes (187.5 KB)
// 1 分钟: 11520000 bytes (11.0 MB)
// 对比:同样的 1 分钟 AAC 128kbps → 约 1MB,压缩率约 11x
三、音频在内存中的布局
// Stereo 16-bit PCM 的内存布局(交织模式 Interleaved):
// [L][R][L][R][L][R]...
// 采样0 采样1 采样2
// 每个样本是 int16_t(小端序)
#include <cstdint>
struct Stereo16Sample {
int16_t left;
int16_t right;
};
// 生成一个 440Hz 的正弦波测试音(A4 音)
void generate_sine_wave(int16_t* buffer, int num_samples, int sample_rate) {
double freq = 440.0; // A4
for (int i = 0; i < num_samples; i++) {
double t = (double)i / sample_rate;
double value = sin(2.0 * M_PI * freq * t) * 32767.0; // 归一化到 16bit 范围
buffer[i] = (int16_t)value;
}
}
// 混音:把两个音频叠加(注意防止溢出)
void mix_audio(const int16_t* a, const int16_t* b, int16_t* out, int count) {
for (int i = 0; i < count; i++) {
int mixed = (int)a[i] + (int)b[i];
// 防止溢出:钳制到 int16_t 范围
if (mixed > 32767) mixed = 32767;
if (mixed < -32768) mixed = -32768;
out[i] = (int16_t) mixed;
}
}