python将两个单声道wav音频合成一个双声道wav音频_立体声感
在以下内容中,若有任何错误和不足,欢迎读者进行指正,不尽感激!
环境相关
python==3.6.13 numpy==1.19.2 scipy==1.5.2 PyAudio==0.2.11 wave time …… 缺啥补啥
编写目的
- 在实验过程中,发现经常需要双声道的音频,但之前录制得到的音频都是单声道的,即便是通过pyaudio指定了录制双声道音频,但录制结果中左声道和右声道的信息是一样的 (这一点受限于硬件和代码,现在已经解决了这个问题,后续会进行更新)。
- 现在我需要的是一个左声道和右声道的音频内容不同的双声道音频,故编写了此代码进行测试,在测试过程中,左声道使用的是语音“1”的内容,右声道使用的是语音“2”的内容,即读三个1或者三个2。
- 得到的合成音频,能够听出左右声道具有不同的音频信息,我可以听出左边耳朵在朗读“1”,右边耳朵在朗读“2”。
- 但目前的代码仍有一些缺陷,比如有一些固有限制:目前要求两个单声道音频的参数都相同(时间、采样频率、采样宽度,压缩格式等)
- 目前采用的左右声道的音频都是基于同样的录音参数进行录制的,录音部分的代码也将在下面放出。
录音代码
在这个部分中,将展示我使用的录音代码,使用的录音设备是默认,经测试需要在电脑中进行设置,当前展示的是仅录制一个声道的音频的代码,即便修改了通道参数,两个声道的内容仍是一样的(非立体声效果)。该部分的代码编写参考于博客https://blog.csdn.net/weixin_45973679/article/details/121709190 的内容进行改写。
import wave
import time
from pyaudio import PyAudio, paInt16
framerate = 16000
num_samples = 2000
channels = 1
sampwidth = 2
def save_wave(filepath, data):
wf = wave.open(filepath, 'wb')
wf.setnchannels(channels)
wf.setsampwidth(sampwidth)
wf.setframerate(framerate)
wf.writeframes(b''.join(data))
wf.close()
def record(filepath, record_time):
pa = PyAudio()
stream = pa.open(format=paInt16, channels=channels,
rate=framerate, input=True, frames_per_buffer=num_samples)
my_buf = []
t = time.time()
print('正在录音...')
while time.time() < t + record_time:
string_audio_data = stream.read(num_samples)
my_buf.append(string_audio_data)
print('录音结束.')
save_wave(filepath, my_buf)
stream.close()
if __name__ == '__main__':
record('2channel_merge_channel1.wav', 5)
若是在Jetson中进行操作的话,可以同时录制两个不同声道的音频信息,但使用以上代码是无法完美完成的,这部分的代码将在后续的工作中更新。
单通道音合成双通道音频代码
- 这里附上由两个单通道的wav文件合成一个双通道wav文件的代码;
- 在编写过程中,我读取一个双通道音频进行测试,查看其数据格式,并测试了拼接方法,让读取的单通道音频的数据通过组合与调整,得到双通道的格式;
- 所使用的录音代码如上一节所示;
- 经测试,由上述录音代码,分别录制音频内容不同的两段参数相同的音频(在录音代码中仅修改文件名即可,然后录制两次音频,说话内容不同)。经过合成后,能够得到左右耳内容不同的双声道音频。
- 对代码内容进行了注释,帮助理解,若有错误和不足,欢迎读者进行指正。
代码如下:
"""
将两个单声道音频合成为一个双声道音频的测试
@author: shy
@contact: hy_shu@qq.com
@application:
@file: 2channel_merge.py
@time: 2022/6/21 15:10
"""
import scipy.io.wavfile as wavfile
import numpy as np
import wave
class merge_2channels():
"""
用于将两个已经存在的单声道wav音频,合成一个双声道wav音频
根据两个单声道wav音频的不同之处,能够生成左右声道内容不同的双声道wav文件
目前还有一些限制,在后续的版本上会进行更新
限制:目前要求两个单声道音频的参数都相同(时间、采样频率、采样宽度,压缩格式等)
"""
def __init__(self, merge_framerate, merge_samples, merge_sampwidth=2, merge_channels=2):
self.merge_framerate = merge_framerate
self.merge_samples = merge_samples
self.merge_sampwidth = merge_sampwidth
self.merge_channels = merge_channels
def save_file(self, filepath, data):
"""
保存录音文件
:param filepath: 用于保存的路径(str)
:param data: 音频数据(2列的ndarray)
:return:
"""
wf = wave.open(filepath, 'wb')
wf.setnchannels(self.merge_channels)
wf.setsampwidth(self.merge_sampwidth)
wf.setframerate(self.merge_framerate)
wf.writeframes(data.tostring())
wf.close()
def merge(self, audio_left, audio_right, merge_audio):
"""
基于两个单声道音频合成一个双声道音频
:param audio_left: 左声道音频的路径(str)
:param audio_right: 右声道音频的路径(str)
:param merge_audio: 合成音频的路径(str)
:return:
"""
fs_left, data_left = wavfile.read(audio_left)
fs_right, data_right = wavfile.read(audio_right)
data = np.vstack([data_left, data_right])
data = data.T
self.save_file(merge_audio, data)
if __name__ == '__main__':
a = merge_2channels(merge_framerate=16000, merge_samples=2000, merge_sampwidth=2)
a.merge('2channel_merge_channel1.wav', '2channel_merge_channel2.wav', '2channel_class_merge.wav')
代码中如果有任何可以继续改进和完善的地方,望大家不吝赐教?(*?)?!
|