1. 多通道音频同步基础框架搭建

任务目标

搭建一个多通道音频基础处理框架,实现音频文件的读取、多通道数据存储与播放,为后续通道间同步算法提供统一的数据访问接口。本案例以4通道WAV文件为输入,框架输出各通道独立波形数据,并支持回放验证。

环境依赖

Python 3.8+,仅需标准库 wave、struct、math 以及 sounddevice(用于播放验证)。安装命令:pip install sounddevice。

核心实现

import wave
import struct
import math
import sounddevice as sd
import numpy as np

class MultiChannelAudio:
    """多通道音频基础框架:读取、存储、播放"""
    
    def __init__(self, filepath=None):
        self.filepath = filepath
        self.sample_rate = 0
        self.sample_width = 0
        self.num_channels = 0
        self.num_frames = 0
        self.channels = []  # 每个元素为对应通道的采样值列表(float)
    
    def load(self, filepath):
        """读取WAV文件,按通道分离数据"""
        self.filepath = filepath
        with wave.open(filepath, 'rb') as wf:
            self.num_channels = wf.getnchannels()
            self.sample_width = wf.getsampwidth()
            self.sample_rate = wf.getframerate()
            self.num_frames = wf.getnframes()
            raw_data = wf.readframes(self.num_frames)
        
        # 解析原始字节为多通道交错数据
        fmt = f'<{self.num_frames * self.num_channels}{"h" if self.sample_width == 2 else "b"}'
        samples = struct.unpack(fmt, raw_data)
        
        # 按通道分离
        self.channels = []
        for ch in range(self.num_channels):
            self.channels.append(
                [samples[i] / 32768.0 for i in range(ch, len(samples), self.num_channels)]
            )
        return self
    
    def get_channel(self, idx):
        """获取指定通道的归一化浮点数据"""
        if 0 <= idx < self.num_channels:
            return self.channels[idx]
        raise IndexError(f'通道索引超出范围: {idx}')
    
    def get_frame(self, idx):
        """获取指定帧的所有通道采样值"""
        if 0 <= idx < self.num_frames:
            return [ch[idx] for ch in self.channels]
        raise IndexError(f'帧索引超出范围: {idx}')
    
    def play(self, start=0, duration=None):
        """播放指定范围(秒),默认播放全部"""
        if not self.channels:
            raise RuntimeError('无音频数据,请先调用load()')
        end = self.num_frames if duration is None else min(
            self.num_frames, start * self.sample_rate + int(duration * self.sample_rate)
        )
        start_frame = int(start * self.sample_rate)
        # 重组为播放所需的交错数组
        play_data = np.array([
            [ch[i] for ch in self.channels] 
            for i in range(start_frame, end)
        ], dtype=np.float32)
        sd.play(play_data, self.sample_rate)
        sd.wait()
    
    def info(self):
        """返回音频参数摘要"""
        return {
            '采样率': self.sample_rate,
            '位深': self.sample_width * 8,
            '通道数': self.num_channels,
            '总帧数': self.num_frames,
            '时长(秒)': round(self.num_frames / self.sample_rate, 3)
        }

# 最小调用入口
if __name__ == '__main__':
    # 生成4通道测试信号(440Hz正弦波,2秒)
    sr = 44100
    t = [i / sr for i in range(sr * 2)]
    test_channels = [
        [0.5 * math.sin(2 * math.pi * 440 * ti) for ti in t],   # 左前
        [0.5 * math.sin(2 * math.pi * 440 * ti + 0.5) for ti in t],  # 右前
        [0.3 * math.sin(2 * math.pi * 180 * ti) for ti in t],   # 左后
        [0.3 * math.sin(2 * math.pi * 180 * ti + 0.5) for ti in t]   # 右后
    ]
    
    # 写入临时WAV文件
    with wave.open('test_4ch.wav', 'wb') as wf:
        wf.setnchannels(4)
        wf.setsampwidth(2)
        wf.setframerate(sr)
        for i in range(len(t)):
            frame = []
            for ch in test_channels:
                frame.append(struct.pack('<h', int(ch[i] * 32767)))
            wf.writeframes(b''.join(frame))
    
    # 使用框架读取并验证
    audio = MultiChannelAudio()
    audio.load('test_4ch.wav')
    print('音频参数:', audio.info())
    print('通道0前5个采样:', [round(v, 4) for v in audio.get_channel(0)[:5]])
    print('帧0所有通道:', [round(v, 4) for v in audio.get_frame(0)])
    
    # 播放验证(取消注释以试听)
    # audio.play(duration=2)

运行与验证

  1. 将上述代码保存为 audio_framework.py,在命令行执行 python audio_framework.py。
  2. 程序自动生成4通道测试WAV文件并加载,控制台输出音频参数与采样数据。
  3. 通过条件:输出显示采样率44100、通道数4、时长2秒;通道0前5个采样值接近 [0.0, 0.0312, 0.0622, 0.0922, 0.1205](440Hz正弦波理论值,允许±0.002浮点误差);帧0各通道值接近 [0.0, 0.4794, 0.0, 0.4794](对应相位偏移0.5弧度)。
  4. 播放验证:取消 audio.play() 注释后运行,应听到4个通道混合的立体声效果(左前/右前为440Hz,左后/右后为180Hz)。

框架扩展点

本框架的 channels 列表为后续同步算法提供直接访问接口:get_channel(i) 获取单通道完整数据用于延迟估计,get_frame(i) 获取多通道瞬时帧用于样本级同步。后续算法只需基于这两个方法即可实现通道间时间偏移检测与校正,无需关心底层文件解析细节。

WAV文件 4通道交错 load() 解析+通道分离 channels[] 按通道存储 get_channel(i) get_frame(i) play() 同步算法数据源 帧级访问/回放