音频格式中 规定了使用多少 bits 来对信号进行编码。
微软 和 IBM 于 1991 年 提出的资源交换的文件格式 RIFF( resource interchange File Format);
wav 是 属于RIFF 中的一个应用实例;
RIFF的其他实例还包含了其他的音视频格式 AVI, 图像动画ANI;
RIFF 文件由一个表头 header, 多个区块 chunk 组成;
打开该网址:
http://soundfile.sapp.org/doc/WaveFormat/
wav 的 Header : 使用 32 位正整数表示整个文件的大小, 故wav 大小不超过 4 GB;
第一个区块,格式子块,Format chunk: 记录了音频的相关格式信息包括如下:
编码格式, 通道数,采样率,Byte Rate 传输速率(字节每秒), 块对齐,
第二个区块,数据子块,data chunk :开始存储音频的数据,
注意到在数据块中,左通道和右通道的数据有依次间隔存放的,按照
左通道1,右通道1,左通道2, 右通道2 这样的顺序依次交替存放;
调用 struct
module,
https://docs.python.org/3/library/struct.html?highlight=struct#struct.unpack_from
注意,使用 struct.unpack(),
其中,关键点:
<
表示, 低位在前;
>
表示,高位在前;
H unsigned short integer 2
H 表示无符号的短整形, integer, 占2 个字节;
I unsigned int integer 4
I: 表示无符号的整形, integer占4 个字节;
注意到根据字节序来判断使用的场景,
byteorder 是big
: 即高位在前时, 使用 f.read()
直接打开;
byteorder 是little
: 即低位在前时, 使用 struct.unpack()
函数打开;
import struct
f = open("./male_audio.wav", mode = "rb") # 以二进制的只读模式打开该文件;
chunk_id = f.read(4) # 文件的前4byte 字节代表 RIFF;
print("the chunk id:", chunk_id)
# < 代表 低位在前, I:代表无符号的整数, 4byte;
chunk_size = struct.unpack(', f.read(4))[0]
print("the chunk size :", chunk_size)
wav_format = f.read(4)
print("the wav format", wav_format)
sub_chunck_1_id = f.read(4)
print("the first sub chunk id:", sub_chunck_1_id)
sub_chunck_1_size = struct.unpack(', f.read(4))[0]
print("the sub chunk 1 size: ", sub_chunck_1_size)
# < 代表 低位在前, H:代表无符号的短整数, 2个字节;
audio_format = struct.unpack(', f.read(2))[0]
print("the audio format", audio_format)
# PCM = 1 (i.e. Linear quantization)
# Values other than 1 indicate some form of compression.
# Mono = 1, Stereo = 2, etc.
num_channel = struct.unpack(', f.read(2))[0]
print(" the num channel of audio:", num_channel)
# sampel rate 8000, 44100, etc.
sample_rate = struct.unpack(', f.read(4))[0]
print("the sample rate: ", sample_rate)
#ByteRate == SampleRate * NumChannels * BitsPerSample / 8
byte_rate = struct.unpack(', f.read(4))[0]
print("the byte rate: ", byte_rate)
# BlockAlign == NumChannels * BitsPerSample/8
# The number of bytes for one sample including
# all channels. I wonder what happens when
# this number isn't an integer?
block_align = struct.unpack(', f.read(2))[0]
print(" the block align:", block_align)
# BitsPerSample 8 bits = 8, 16 bits = 16, etc.
bits_per_sample = struct.unpack(', f.read(2))[0]
print("the bits per sample:", bits_per_sample)
# ---- the following data sub chunk---
sub_chunck_2_id = f.read(4)
print("\n the sub chunk 2:", sub_chunck_2_id)
sub_chunck_2_size = struct.unpack(', f.read(4))[0]
print("the sub chunk_2_size:", sub_chunck_2_size)
data0 = struct.unpack(', f.read(2))[0]
print("the first data:", data0)
# 这里需要注意, 第一个前4 个字节中, 前两个
字节代表左声道, 后两字节代表右声道;
f.read()
函数的使用:# ”读“的细节操作
# 1. # f.read(字节数):读取的是字节
# 字节数默认是文件长度;下标会自动后移
# f = open('test.txt','r')
# print(f.read())
# f.close()
# 2.f.readline([limit])
# 读取一行数据
# limit
# 限制的最大字节数
# f = open('test.txt', 'r')
#
# content = f.readline()#只读取一行
# print(content)
#
# content = f.readline()#只读取一行
# print(content)
# f.close()
# 3.f.readlines()
# 会自动的将文件按照换行符进行处理
# 将处理好的每一行组成一个列表返回
f = open('test.txt', 'r')
cn = f.readlines()
for line in cn:
print(line, end='')
f.close()
RIFF: 由微软和IBM提出;
AIFF : 苹果公司提出;
无损格式: FLAC
free lossless audio codec;
lossy : 有损格式
MP3, mostly for music, based on:
• Modified discrete cosine transform (MDCT)
• Sub-band coding
• Advanced Audio Coding (AAC)
• OPUS
• Speex