17 Feb 2017
学会如何处理二进制文件,以wav文件举例。
补充:自己下载了一个wav的文件,但是因为下载的文件和老师实例中的不同,所以第4步
>>> f = open("demo.wav", "rb") >>> info = f.read(44) >>> info 'RIFFv\xea\xda\x01WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00D\xac\x00\x00\x10\xb1\x02\x00\x04\x00\x10\x00LIST\x1a\x00\x00\x00'
“b”mode使用二进制模式打开文件,默认是text模式(t)
根据wav的文件格式,我们知道前44个字节是文件信息
>>> import struct # 解包info数据,通过切片获得声道数值 # 因为采样频率是2个字节,使用h->short类型(c中的数据类型) >>> struct.unpack("h", info[22:24]) (2,) # 获取采样频率数值 # 因为采样频率数值是4个字节,使用i->int类型(c中的数据类型) >>> struct.unpack("i", info[24:28]) (44100,) # 获取编码宽度数值 >>> struct.unpack("h",info[34:36]) (16,)
之所以不使用struct来获取data部分信息,是对于data部分数据,进行处理的话,如果是字符串,不如数值来的方便
所以,我们将data部分数据储存到数组当中
>>> import array ## 获取文件的长度,用来推算数组长度 >>> f.seek(0, 2) # 0代表offset为0,2代表文件末尾,也就是说我们将指针调整到文件末尾 # 使用f.tell()来获取目前指针位置 >>> f.tell() 31124094 # 计算数组长度(这里计算中的2是根据声道数来确定的) >>> array_len = (f.tell() - 44) / 2 # 创建一个初始化长度为array_len的数组 >>> buf = array.array('h', (0 for _ in xrange(array_len))) # 将data部分数据读入到buf这个数组中去 >>> f.seek(44) >>> f.readinto(buf) 31124050
# 给每个采样做强度缩减操作 >>> for i in xrange(array_len): ... buf[i] /= 8 ... >>> fnew = open('demo2.wav', 'wb') >>> fnew.write(info) >>> buf.tofile(fnew) >>> fnew.close()
此时可以打开demo2.wav文件,发现声音变小,因为我们给每个采样做了长度缩减操作