首页 > 编程问答 >我正在制作一个可以打开wav文件的python程序,我想知道wav文件的格式是什么

我正在制作一个可以打开wav文件的python程序,我想知道wav文件的格式是什么

时间:2024-07-30 04:52:09浏览次数:10  
标签:python audio wav

因此,我已经通过 网站的研究编写了验证并读取 wav 标头的代码。但我想知道,data段中的数据是如何存储的?它们位于 16 位部分中,彼此相邻放置。我认为在 Audacity 中制作 440hz 正弦波,然后导出它,会显示一些结果,并且字节确实看起来更整齐,但仍然像废话一样接缝。相信我,我已经在互联网上到处查找了,但是如果您知道,或者认为您可以找到答案,那么请务必这样做。如果您想尝试一下,这是我的代码。

## CHECK FILE VALIDIDITY ##
# Import required libarays
import sys
from numpy import take

# Make a function to read the byte data from the file
def postobytes(data, pos):
    return bytes(take(data, pos).tolist())

# Open the file
fileName = sys.argv[1]
data = list(open(fileName, 'rb').read())

# Define the checking variables
headerCorrect1 = b'RIFF'
headerCorrect2 = b'WAVEfmt \0\0\0\0\0'
range1 = [0,1,2,3]
range2 = [8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]

# Check the header data
if postobytes(data, range1) == headerCorrect1 and postobytes(data, range2) == headerCorrect2:
    print('Valid RIFF header')
else:
    raise FileExistsError('Invalid RIFF header')


## GET AND PRINT FILE LENGTH ##
# Make a function to convert big endian to little endian
def bigtolittle(data):
    return data[::-1]

def intfrompos(data, pos):
    return int.from_bytes(bigtolittle(postobytes(data, pos)))

# Get the length of the file
lengthRange = [4,5,6,7]
length = intfrompos(data, lengthRange)

# Make human readable length
print('\nFile Size:')
if length/1000 < 1000:
    print(str(round(length/100)/10)+'K')
elif length/1000000 < 1000000:
    print(str(round(length/10000)/100)+'M')
else:
    raise NotImplementedError('File to big, gigabyte and on not implemented')


## GET DATA AND FIND DATA START ##
# Get sample rate
srRange = [24,25,26,27]
sampleRate = intfrompos(data, srRange)
print('\nSample Rate:\n'+str(sampleRate)+'Hz')

# Get bits per sample
bpsRange = [34,35]
bitsPerSample = intfrompos(data, bpsRange)
print('\nBits per Sample:\n'+str(bitsPerSample)+' Bits')
if bitsPerSample != 16:
    raise ValueError('Unsupported or invalid Bits per Sample')

# Find data starter
for pos, byte in enumerate(data):
    if byte == 100:
        if data[pos+1] == 97:
            if data[pos+2] == 116:
                if data[pos+3] == 97:
                    print('\nData Header at '+str(pos))
                    dhsp = pos # Data header start position
                    break

print('\nPlaying WAV file')

audio = []
dlRange = [dhsp+4,dhsp+5,dhsp+6,dhsp+7]
dl = intfrompos(data, lengthRange)
for pt, unused in enumerate(data):
    pos = dhsp+pt+8
    if pos > dl+6:
        break
    byte = data[pos]
    audio.append(byte)

# FOR STACK OVERFLOW HELPERS: The audio list is all you need to mess with. Below is where you can do that.

我本来希望找到答案,但找不到。


当然可以!正在解码 WAV 文件格式的正确道路上。已经成功解析了标题,现在让我们解决数据部分是如何编码的:

WAV 文件中的音频数据表示

WAV 文件通常存储使用 脉冲编码调制 (PCM) 格式的音频数据。PCM 本质上是声波的数字表示。以下是它的工作原理:

  1. 采样: 采用模拟声波,并以规则的间隔对其幅度进行测量(采样)。每秒的采样数就是 采样率 (已经在代码中解析过)。
  2. 量化: 每个样本(幅度测量)都四舍五入到最接近的预定义离散值。这些值的数量由 位深度 (或每个样本的位数)确定,已正确识别为 16 位。
  3. 编码: 量化的样本表示为二进制值序列。对于 16 位音频,每个样本使用 16 位(2 个字节),这导致 65,536 个可能的幅度级别。

解释的 WAV 数据

由于已经确认的 WAV 文件使用 16 位 PCM,因此以下是解释数据部分中的字节的方法:

  • 字节对: 数据中的每个两个连续字节表示一个音频样本。
  • 字节顺序: WAV 文件通常使用 小端 字节顺序。这意味着第一个字节表示样本的最低有效字节,第二个字节表示最高有效字节。
  • 有符号整数: 每个 16 位样本表示为有符号整数。要将其转换为更易于理解的格式,需要使用的编程语言将原始字节数据转换为有符号整数。

在 Python 中将原始字节转换为音频

的 Python 代码片段中缺少的部分是如何将原始字节数据转换为实际音频值。以下是如何使用 struct 模块来实现:

import struct

# ...(现有的代码来解析标题)...

audio = []
for i in range(dhsp + 8, len(data), 2):  # 从数据块开始,每次迭代 2 个字节
    sample_bytes = bytes(data[i:i+2])  # 获取 2 个字节的样本
    sample_int, = struct.unpack('<h', sample_bytes)  # 将其解压缩为有符号短整数(小端)
    audio.append(sample_int) 

# 现在,`audio` 列表包含代表音频波形的整数样本

可视化和分析

要更好地理解数据,可以使用以下方法对其进行可视化或进一步分析:

  • Matplotlib: 使用 Matplotlib 库绘制 audio 列表以查看音频波形。
  • NumPy: 使用 NumPy 库对音频数据执行高级操作,例如计算 FFT 以进行频率分析。

其他注意事项

  • 通道: 如果的 WAV 文件有多个通道(立体声有 2 个通道),则样本将交错。这意味着左声道的一个样本后跟右声道的一个样本,依此类推。
  • 规范化: 音频样本通常在 -1 到 +1 的范围内进行规范化,以便于播放和处理。可能需要对解压缩的整数样本进行缩放以适应此范围。

请告诉我这是否有助于阐明 WAV 文件中音频数据的存储方式!

标签:python,audio,wav
From: 78809000

相关文章

  • python - 面板库 - PasswordInput 不会对回车做出反应
    我试图避免需要提交按钮。以下代码当前正在远程jupyter实验室运行。仅当光标焦点从密码小部件中移除后,才会打印该消息。我想要回车来触发消息打印。有什么线索吗?frompanel.widgetsimportPasswordInput,TextInputpn.extension()defon_enter(event=None):message_p......
  • 即使安装了软件包,也找不到 python 模块句子转换器
    对于我的python脚本(如下所示),我使用句子转换器包,其中包含SBERT模型。即使在执行“piplist”时明确列出该软件包,并且还安装了torch,所有内容都更新到最新版本,但仍然找不到该模块。脚本:importnumpyasnpimportpandasaspdfromsentence_transformersimportSenten......
  • 有没有办法在 python 中返回类实例的布尔属性?
    我想组织我玩的游戏中的汽车数据。为此,我创建了一个“Car”类。我希望将此类实例的一些属性作为布尔值,这样我就可以将此类的所有实例放入列表中并过滤它们。我当前的解决方案不起作用,因为,我收到以下错误消息:TypeError:__repr__returnednon-string(typeCar)我使用......
  • python 正则表达式匹配一行中的多个单词而不转到下一行
    我正在编写一个解析器来解析以下输出:admin@str-s6000-on-5:~$showinterfacestatusEthernet4InterfaceLanesSpeedMTUAliasVlanOperAdminTypeAsymPFC------------------------------------------......
  • 使用 Python 平滑和对称不规则形状和曲线
    我需要完成三项任务:正则化曲线曲线的对称性完成不完整的曲线例如,这里是输入和预期的输出图像:输入输出|||在一般设置中,形状可以由任何SVG曲线基元(贝塞尔曲线、直线、弧线)表示。为了统一表示,示例包含曲线的折线近似。这些折线保存为......
  • 在Python中通过绝对路径引用数据文件夹
    我有一个大型python项目,其中数据太大,无法每次都以相同的方式共享。不同的人可能会使用网络位置或将某些内容复制到本地驱动器。该路径由不同子文件夹中的脚本和笔记本使用。例如,我将创建一个config.py来定义数据文件夹的路径。importsyssys.path.append('../'......
  • python三天速成记(看完你就会)day3 满满干货~
    续上文啦~EXCEL表的操作上一篇文章讲了怎么读取和操作txt和csv文档,但其实我们生活中还有一个常用的文本格式那就是excel文件,特别是在对大量数据进行处理的时候。excel文件的用处和广泛。其实在python中有很多库可以处理excel文件,但是本文主要介绍使用最实用最广泛的库pan......
  • Python输入验证改进的其他方式
    题目[题目来源:Python编程快速上手——让繁琐工作自动化(第二版)第三章实践项目,下面的解答程序为我自己完成的,仅供参考。]编写一个名为collatz()的函数,他有一个名为number的参数。如果参数是偶数,那么collatz()就输出number//2,并返回该值。如果参数是奇数,那么collatz()就......
  • Python的PyInputPlus模块
    PyInputPlus模块简介PyInputPlus模块的功能:PyInputPlus模块是一个Python第三方模块,需要自己对它进行安装。包含与input()函数类似的、用于多种数据(如日期、数字、电子邮箱地址等)的函数。如果,用户输入了无效的内容,例如格式错误的日期或超过预期范围的数字,那么PyInputPlus模......
  • 用Python实现二进制搜索(二分查找)
    二进制搜索(binarysearch,又称二分搜索)是一种快速有效的搜索方法,用于搜索有序列表中的元素。importmathdefbinary_search(sorted_list,target):"""在有序列表sorted_list中查找目标值target的位置使用二分查找算法"""lower_bound=0#初始......