You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

两种计算WAV文件总块数的方法为何结果不同?

问题分析与解决

你的核心问题是混淆了wave模块中「帧数」和「字节数」的概念,导致计算和实际读取的基准完全不匹配:

错误根源

  1. wave.getnframes()返回的是WAV文件的总帧数,每个帧的字节数由声道数和采样位深决定:每帧字节数 = 声道数 × 采样位深字节数(比如立体声+16位采样,每帧是2×2=4字节)。
  2. wave.readframes(n)的参数n是要读取的帧数,不是字节数。你传入的CHUNK=4096是字节数,导致每次读取了4096帧,返回的字节数据量远大于预期,因此实际读取的块数远少于错误计算的数值。
  3. calc_total_chunks函数直接用总帧数除以字节数(CHUNK),单位完全不匹配,计算结果自然错误。

修正后的代码

from custom_logging import CustomLogger
import logging
import wave
import math
import os

testing_logger = CustomLogger(log_files=["testing.log"])

CHUNK_SIZE_BYTES = 4096  # 明确标注为字节数,避免概念混淆

def calc_total_chunks(song_dir, song_name, chunk_size_bytes):
    song_path = os.path.join(song_dir, song_name)
    with wave.open(song_path) as mywav:
        nframes = mywav.getnframes()
        nchannels = mywav.getnchannels()
        sampwidth = mywav.getsampwidth()
        bytes_per_frame = nchannels * sampwidth
        # 计算每次可读取的帧数:块字节数 ÷ 每帧字节数
        frames_per_chunk = chunk_size_bytes // bytes_per_frame
        if frames_per_chunk == 0:
            frames_per_chunk = 1  # 容错:避免块字节数小于单帧字节数的极端情况
        total_chunks = math.ceil(nframes / frames_per_chunk)
    return total_chunks


def count_chunks_in_song(song_dir, song_name, chunk_size_bytes):
    song_path = os.path.join(song_dir, song_name)
    chunk_count = 0

    with wave.open(song_path) as mywav:
        nchannels = mywav.getnchannels()
        sampwidth = mywav.getsampwidth()
        bytes_per_frame = nchannels * sampwidth
        frames_per_chunk = chunk_size_bytes // bytes_per_frame
        if frames_per_chunk == 0:
            frames_per_chunk = 1

        while True:
            # 按计算好的帧数读取,保证每次读取的字节数接近设定的块大小
            song_data_chunk = mywav.readframes(frames_per_chunk)
            if not song_data_chunk:
                break
            chunk_count += 1

    return chunk_count


songs = ["american.wav", "beats.wav", "No_38.wav"]

for song in songs:
    calc = calc_total_chunks('songs', song, CHUNK_SIZE_BYTES)
    actual = count_chunks_in_song('songs', song, CHUNK_SIZE_BYTES)
    logging.info(f"total chunks calc for {song}: {calc}")
    logging.info(f"total chunks read for {song}: {actual}")

说明

  • 将原CHUNK重命名为CHUNK_SIZE_BYTES,明确标注含义,避免概念混淆。
  • 两个函数统一先计算每帧字节数,再推导每次应读取的帧数,保证计算和实际读取的基准一致。
  • 增加了容错处理,防止块字节数小于单帧字节数时出现异常。

修正后,计算的块数和实际读取的块数会完全匹配。

内容的提问来源于stack exchange,提问作者for i in range

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:28:15