音频引擎

游戏声音系统——音频图 (source→filter→mixer→output), DSP 基础, 空间音频。

概念

音频引擎是游戏的”声音内核”。它将离散的音频资源 (wav, mp3, ogg) 转换为实时音频流。核心挑战包括: 多音源混音、实时 DSP 效果、3D 空间化、以及严格的时间预算 (音频缓冲区欠载 → 爆音, 用户立即可感知)。与图形渲染不同,音频对延迟极为敏感。

核心组件

组件职责关键技术
声源 (Source)解码/播放音频文件流式加载, 缓冲队列
DSP 效果器实时信号处理: 滤波、混响、延迟FIR/IIR 滤波器, 卷积
混音器 (Mixer)将多个声源混合为单一输出流增益控制, 总线和子混音
空间化3D 声场模拟: 方向、距离衰减、遮挡HRTF, Panning
输出驱动将音频帧数据写入硬件PortAudio, OpenAL, WASAPI, ALSA
音频图节点连接模型: 声源 → 效果 → 总线 → 输出类似 Blender Shader Nodes

音频图

音频图 (Audio Graph) — 节点连接模型:

    声源层:
        Source "BGM"          Source "Footstep"     Source "Gunshot"
            |                      |                      |
    效果层:  |                Effect "Reverb"       Effect "Echo"
            |                      |                      |
    总线层:  +---------+-----------+---------+------------+
                       |                     |
                    Bus "SFX"           Bus "Music"
                       |                     |
    混音:              +----------+----------+
                                  |
                            Master Bus
                                  |
                            硬件输出 (Speaker / Headphone)

DSP 基础

卷积混响 (Convolution Reverb):
    录制真实空间 (如音乐厅) 的脉冲响应 (IR)
    IR 是一个声音样本, 表示一个极短脉冲在该空间中的回响
    将任意输入音频与 IR 做卷积 → 得到"像在那个空间中播放"的效果

    output[t] = sum(input[t - k] * IR[k])  for k = 0..N
    // 这是 O(N^2), 通常通过 FFT 优化为 O(N log N)

延迟 (Delay):
    简单的回声效果:
    output[t] = input[t] + feedback * output[t - delay_samples]

滤波 (Filter):
    低通滤波 (Low-Pass): 去除高频 → 模拟隔着墙的声音 (遮挡)
    高通滤波 (High-Pass): 去除低频 → 模拟小型扬声器

    简单一阶 IIR 低通:
    output[t] = output[t-1] + cutoff * (input[t] - output[t-1])
    // cutoff 越小 → 越"闷" (更多高频被去除)

空间音频

3D 音频空间化:
    听者位置: (ear_x, ear_y, ear_z), 朝向 (forward, up)
    声源位置: (src_x, src_y, src_z)

    衰减模型:
        distance = |src - ear|
        gain = 1 / (1 + rolloff * distance)
        // 也可以使用更复杂的: min_distance, max_distance, curve

    声相 (Panning):
        根据声源和听者的相对角度, 控制左右声道音量
        例如: 声源在右前方 45° → 右声道略大

    HRTF (Head-Related Transfer Function):
        模拟人耳、头部和肩膀对声音的滤波效应
        每个方向有一对 FIR 滤波器 (左耳 + 右耳)
        比简单的 panning 更真实的空间定位感

    遮挡与衍射:
        射线检测: 声源和听者之间是否有遮挡物
        有遮挡 → 启用低通滤波器 (模拟声音穿过墙壁)

PortAudio / OpenAL 框架

PortAudio 回调模型 (拉模式):
    int audio_callback(void *outputBuffer, unsigned long framesPerBuffer, ...) {
        float *out = (float *)outputBuffer;

        for (int i = 0; i < framesPerBuffer; i++) {
            float sample = 0.0f;

            // 混音所有活跃声源
            for each active source:
                sample += source->get_next_sample();

            // 应用 Master 总线效果
            sample = master_compressor(sample);

            // 输出立体声
            out[2*i]   = sample;   // 左声道
            out[2*i+1] = sample;   // 右声道
        }
        return 0; // 继续
    }

    Pa_OpenDefaultStream(&stream, 0, 2, paFloat32, SAMPLE_RATE,
                         FRAMES_PER_BUFFER, audio_callback, NULL);
    Pa_StartStream(stream);