音频处理二:(左右声道分离)

程序设计二

完整工程文件:

链接:https://pan.baidu.com/s/1dcoTGhIeDxsRz-RUr2Paxw 
提取码:jy48

一:需求分析

实现语音左右声道数据分离

wav2txt -i xxx.wav -o yyy.txt (-R/-L/-all/-mix)

将输入文件xxx.wav的采样数据读出保存在文本文件yyy.txt中。如无-o项则输出到屏幕上。yyy.txt的格式:

所有数据为整数(16bit 0–2^16-1=65565),每行一个采样值。如

1
2
3
4
5
...
100

双声道语音每行两个值,用空格分隔

二:参考知识

1.所需文件知识

转换语音频率和声道数

ffmpeg -i lanTian.mav -ac 2 -ar 16000 -y lanTian2.mav

其中:
-ac 1 设置声道数为
-ar 16000 设置采样率为16000Hz

文件信息

lanTian.mav 声道数1 采样率8000
lanTian2.mav 声道数2 采样率16000
BAC009S0003W0121.wav 声道数1 采样率16000
2.sys 模块

在 Python 中,sys 模块是一个非常常用且十分重要的模块,通过模块中的 sys.argv 就可以访问到所有的命令行参数,它的返回值是包含所有命令行参数的列表(list),

参数个数: len(sys.argv)
脚本名: sys.argv[0]
参数1: sys.argv[1]
参数2: sys.argv[2]
options, args = getopt.getopt(args, shortopts, longopts=[])
参数args:一般是sys.argv[1:]。过滤掉sys.argv[0],它是执行脚本的名字,不算做命令行参数。
参数shortopts:短格式分析串。例如:"hp:i:",h后面没有冒号,表示后面不带参数;p和i后面带有冒号,表示后面带参数。
参数longopts:长格式分析串列表。例如:["help", "ip=", "port="]help后面没有等号,表示后面不带参数;ip和port后面带冒号,表示后面带参数。返回值options是以元组为元素的列表,每个元组的形式为:(选项串, 附加参数),如:('-i', '192.168.0.1')返回值args是个列表,其中的元素是那些不含'-''--'的参数。
3.参考文章
https://blog.csdn.net/ouyang_peng/article/details/79390920
http://www.eemaker.com/python-wav-pcm.html
https://www.cnblogs.com/LXP-Never/p/10078200.html
https://www.jianshu.com/p/e568f94cdf6a
https://blog.csdn.net/Samaritan_x/article/details/84146029
https://blog.csdn.net/qinglingLS/article/details/83218638
https://blog.csdn.net/sinat_33588424/article/details/80239375

三:python代码

holiday02.py
import wave
import numpy as np
import sys
import getopt

def main(argv):
    """
        通过 getopt模块 来识别参数demo
    """

    try:
        """
            options, args = getopt.getopt(args, shortopts, longopts=[])

            参数args:一般是sys.argv[1:]。过滤掉sys.argv[0],它是执行脚本的名字,不算做命令行参数。
            参数shortopts:短格式分析串。例如:"hp:i:",h后面没有冒号,表示后面不带参数;p和i后面带有冒号,表示后面带参数。
            参数longopts:长格式分析串列表。例如:["help", "ip=", "port="],help后面没有等号,表示后面不带参数;ip和port后面带冒号,表示后面带参数。

            返回值options是以元组为元素的列表,每个元组的形式为:(选项串, 附加参数),如:('-i', '192.168.0.1')
            返回值args是个列表,其中的元素是那些不含'-'或'--'的参数。
        """
        #opts, args = getopt.getopt(argv, "hi:p:rl", ["help", "input=", "password=","right","left"])
        opts, args = getopt.getopt(argv, "hi:o:lrA", ["help", "input=", "output=","left","right","all"])
    except getopt.GetoptError:
        print('双声道:python holiday02.py -i lanTian2.wav -o wavData.txt -l')
        print('or双声道:python holiday02.py --input=lanTian2.wav --output=wavData.txt --all')
        print('单身道:python holiday02.py -i BAC009S0003W0121.wav -o wavData.txt')
        sys.exit(2)

    # 处理 返回值options是以元组为元素的列表。
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            print('双声道:python holiday02.py -i lanTian2.wav -o wavData.txt -l')
            print('or双声道:python holiday02.py --input=lanTian2.wav --output=wavData.txt --all')
            print('单身道:python holiday02.py -i BAC009S0003W0121.wav -o wavData.txt')
            sys.exit()
        elif opt in ("-i", "--input"):
            input = arg
        elif opt in ("-o", "--output"):
            output = arg

            f = wave.open(input, 'rb')
            params = f.getparams()  # get wave file params
            nchannels, sampwidth, framerate, nframes = params[:4]
            print("wav params is :", params)

            # open a txt file
            #file = open("wavData.txt", 'w')
            file = open(output, 'w')
            data = f.readframes(nframes)
            # 将字符串转换为数组,得到一维的short类型的数组
            data = np.fromstring(data, dtype=np.short)
            # 整合左声道和右声道的数据
            data = np.reshape(data, [nframes, nchannels])
            j=0#用j来判断左右声道数据
            length=len(data)#该段语音有多少个采样点


            #左声道j=0
        elif opt in ("-l", "--left"):
            #data=data[:,0]
            j=0
        elif opt in ("-r", "--right"):
            #data=data[:,1]
            j=1#右声道j=1
        elif opt in ("-A", "--all"):
            for i in range(length):
                # s = str(data[i, 0]).replace('[', ").replace('[',")
                #同时打印左右声道数据,中间空格分开
                s = str(data[i, 0]).replace('[', ").replace('[',")+' '+str(data[i, 1]).replace('[', ").replace('[',")
                s = s.replace("'", ").replace(',',") + '\n'  # 去除单引号,逗号,每行末尾追加换行符
                file.write(s)
            file.close()
            f.close()
            exit()#为了不影响下面的,如若没有exit,打完双声道左右数据,还会打印单声道一列数据
            #file.close()
            '''
            在这里需要考虑到左右声道数据同时打印在txt文件,和分别打印,只定义j没能实现,定义了两次for循环
            将file和f关闭,防止下面打印左右声道又关闭依次,不然报错ValueError: I/O operation on closed file.
            '''
            #f.close()  # close wave file
            #break

    for i in range(length):
        # s = str(bins[i,0]).replace('[',").replace('[',")+'\t'+str(data[i]).replace('[',").replace('[',")#去除[],这两行按数据不同,可以选择
        # s = str(data[i, 0]).replace('[', ").replace('[',")
        s = str(data[i,j]).replace('[', ").replace('[',")
        s = s.replace("'", ").replace(',',") + '\n'  # 去除单引号,逗号,每行末尾追加换行符
        file.write(s)
    file.close()

    f.close()  # close wave file


if __name__ == "__main__":
    # sys.argv[1:]为要处理的参数列表,sys.argv[0]为脚本名,所以用sys.argv[1:]过滤掉脚本名。
    main(sys.argv[1:])


#python holiday02.py -i BAC009S0003W0121.wav
#python holiday02.py -i lanTian2.wav -l
#python holiday02.py -i lanTian2.wav -o wavData.txt -l

四:实现结果

1.请求帮助

python holiday02.py -h
双声道:python holiday02.py -i lanTian2.wav -o wavData.txt -l
or双声道:python holiday02.py --input=lanTian2.wav --output=wavData.txt --all
单身道:python holiday02.py -i BAC009S0003W0121.wav -o wavData.txt

在这里插入图片描述

2.单声道

python holiday02.py -i BAC009S0003W0121.wav -o wavData(single).txt

在这里插入图片描述

3.左声道数据

python holiday02.py -i lanTian2.wav -o wavData(left).txt -l

在这里插入图片描述

4.右声道数据

python holiday02.py -i lanTian2.wav -o wavData(right).txt -r

在这里插入图片描述

5.左右声道数据

python holiday02.py -i lanTian2.wav -o wavData(all).txt --all

在这里插入图片描述

五:结果对比

以双声道lanTian2.wav,自己实现的数据和matlab对比,打印数据有多少行,值大小情况,结果对比一致

matlab程序

filename='G:\python\holiday\lanTian2.wav';%这个声音文件在该程序根目录
[signal,fs] = audioread(filename,'native');%读取wav文件,读完是去除了文件头的采样点,而且归一化了,是浮点数。
%[signal,fs] = audioread(filename)
info=audioinfo(filename)%看这个文件的信息。
whos signal%显示name size bytes class 等等

python实现结果如下

在这里插入图片描述
matlab实现结果如下

ead(filename,‘native’);%读取wav文件,读完是去除了文件头的采样点,而且归一化了,是浮点数。
%[signal,fs] = audioread(filename)
info=audioinfo(filename)%看这个文件的信息。
whos signal%显示name size bytes class 等等

matlab实现结果如下

在这里插入图片描述

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐维康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值