背景
笔者最近在做的系统需要从SD卡读取wav音频数据然后进行处理。
最近在调试SD卡读取音频和分帧的Verilog代码,需要做功能仿真,所以打算先用ROM来存wav数据测试一下功能。
正文
下图是我的音频在SD卡里的存储形式。使用winhex软件。
我要将其中的数据以8位位宽存入ROM中去。所以需要将该wav的有效音频数据转换为二进制写入coe文件中。代码如下:
读者在使用时只需要修改define_data_long的数值。
import wave
from intToBin import intToBin
# 打开wav文件 ,open返回一个的是一个Wave_read类的实例,通过调用它的方法读取WAV文件的格式和数据。
f = wave.open(r"a0001.wav", "rb")
# 读取格式信息
# 一次性返回所有的WAV文件的格式信息,它返回的是一个组元(tuple):声道数, 量化位数(byte单位), 采
# 样频率, 采样点数, 压缩类型, 压缩类型的描述。wave模块只支持非压缩的数据,因此可以忽略最后两个信息
params = f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
print("采样点数",nframes)
print("量化位宽",sampwidth) # 我这里是2字节的量化位宽,也就是每个采样点有16位位宽
# 读取波形数据
str_data = f.readframes(nframes*sampwidth) # 总共有nframes*sampwidth个字节的音频数据
print(type(str_data))
str_data=str_data.hex() # 将bytes类型转换为16进制
f.close()
define_data_long=2 # 用户设置自己的输出数据长度(每4个bits为一个单位长度)
print(type(str_data))
f_wr=open("wav_data.coe",'w')
f_wr.write("memory_initialization_radix=2;\n")
f_wr.write("memory_initialization_vector =\n")
for i in range(nframes*sampwidth):
data_hex=str_data[i*define_data_long:i*define_data_long+define_data_long]
print(data_hex)
data_bin=intToBin((int(data_hex,16)),define_data_long*4,feature=True) # 把16进制的数据转换为二进制数据(固定8位位宽)
print(data_bin)
f_wr.write(data_bin+'\n')
def intToBin(number,index,feature=True):
if (feature==True):#十进制转换为二进制
if(number>=0):
b=bin(number)
b = '0' * (index+2 - len(b)) + b
else:
b=2**(index)+number
b=bin(b)
b = '1' * (index+2 - len(b)) + b #注意这里算出来的结果是补码
b=b.replace("0b",'')
b=b.replace('-','')
return b
elif(feature==False):#二进制转换为十进制
i=int(str(number),2)
if(i>=2**(index-1)):#如果是负数
i=-(2**index-i)
return i
else:
return i
测试
python的转换结果和wav内真实数据:
注:wav格式的有效音频数据从偏移地址第44位(2C)开始。