有些设备采集的音频文件格式为pcm格式,其本身就为ad转化后的产物,在我的嵌入式实现中为节省计算资源,直接对其进行声道分离。
如何使用python语言将pcm音频流文件转为数值矩阵,多声道进行声道分离,便于对每个单声道进行观察,下面我写了一个函数(借用了AudioSegment)用于解决这个问题。
需提前下载的模块有AudioSegment,matplotlib,numpy
#pcm数据可以这样读取
from pydub import AudioSegment
import numpy as np
#import wave
#from matplotlib import pyplot
pcm_path = 'mic_demo_vvui_ori.pcm'#改
def voice_devide(pcm_path,sound_num,invalid_sound,fs,data_type):
'''
多声道分离转化,pcm_path为文件路径,sound_num为声道数
invalid_num为无效声道数(用于消除回声),没有则为0
fs为采样频率,data_type为数据位数(8位,16位,32位)
支持任意多通道
'''
#多声道分离,fs为采样频率,data_type为数据位数(8位,16位,32位)
#根据pcm精度选择读取类型
if data_type==32:
with open(pcm_path, 'rb') as f:
audioData = np.fromfile(f, dtype=np.uint32)
elif data_type==16 :
with open(pcm_path, 'rb') as f:
audioData = np.fromfile(f, dtype=np.uint16)
else:
with open(pcm_path, 'rb') as f:
audioData = np.fromfile(f, dtype=np.uint8)
audioData.shape = -1, sound_num #有sound_num个声道,即排成sound_num列,一行即为一帧(采样一次)
audioData = audioData.T
#分离每个声道
for i in range(sound_num):#笨方法,挨个导出,方便导入
ch_x=audioData[i,:]
ch_x.tofile('ch_%d.pcm'%(i))
num = len(audioData[1])
ch_data=np.zeros((sound_num-invalid_sound,num))#减去invalid_sound个无效声道,没有抵消声道可删去
for i in range(0,sound_num-invalid_sound):#依次将各个声道的数据读入,转为浮点数
ch_x='ch_%d.pcm'%(i)#文件名的格式
voice_data = AudioSegment.from_file(file=ch_x,sample_width=data_type/8, frame_rate=fs,channels=1,)
a=voice_data.get_array_of_samples()
ch_data[i,:] = np.array(voice_data.get_array_of_samples())
ch_data[i,:] = ch_data[i,:]/2**(data_type-1)#转为浮点数 使其缩小到0-1的范围内
return ch_data
测试一下:(没有无效声道invalid_sound就写0)
import format_conversion
import matplotlib.pyplot as plt
pcm_path='mic_demo_vvui_ori.pcm'
data=format_conversion.voice_devide(pcm_path,sound_num=8,invalid_sound=0,fs=16000,data_type=32)