简单易用利用python来产生音频所需的一些波形

基本的波形产生

数字波形数组的产生

python要产生波形肯定是数字波形了
而我们听到的音乐的频率则是模拟频率。
模拟频率和数字频率之间的关系由采样率决定

我们先来尝试生成一个模拟频率为100Hz的正弦波,采样率22050Hz,那么其数字域的周期应该是采样率除以模拟频率
S a m p l e _ R a t e / A n a l o g _ F r e q u e n c e Sample\_Rate / Analog\_Frequence Sample_Rate/Analog_Frequence
数字角频率则是
ω = 2 π T d i g i t a l \omega = \frac{2\pi}{T_{digital}} ω=Tdigital2π

如果我们的采样时间为t,则采样点数为

N = t × S a m p l e _ R a t e N = t \times Sample\_Rate N=t×Sample_Rate

ok根据以上知识我们先来产生一个数组

import numpy as np
from numpy import pi
import matplotlib.pyplot as plt
import wave

sample_rate=22050 # 采样率
fa = 100 # 模拟频率

T = sample_rate / fa  #周期

D_Omega = 2*pi/T # 数字角频率

t_length = 10 # 音频时长,秒

D_num = t_length * sample_rate# 对应的数字波形点数

x = np.arange(0,D_num)

y = np.sin(D_Omega * x)

尝试绘制一下这个波形,如下添加时间轴数组(让横轴显示的是模拟信号的真实时间)

t = x/sample_rate

plt.plot(t,y)  #画出一个周期的波形图
plt.show()

可以绘制出来音频的波形图,放大某一区域可以看到其周期为0.01s,也就是频率为100Hz

在这里插入图片描述

向wav文件写入

向wav文件写入用wav的库就很简单了

file=wave.open(r'wave.wav','wb')
file.setnchannels(1)#设置通道数
file.setsampwidth(2)#设置采样宽
file.setframerate(sample_rate)#设置采样
file.setcomptype('NONE','not compressed')#设置采样格式  无压缩

按如上方式设置保存音频的通道数、采样宽、采样率等等,就完成了相关的配置。
参考官方文档可知,

Wave_write.setnchannels(n)
设置声道数。(1 为单声道,2 为立体声)
Wave_write.setsampwidth(n)
设置采样字节长度为 n。
Wave_write.setframerate(n)
设置采样频率为 n。
Wave_write.setcomptype(type, name)
设置压缩格式。目前只支持 NONE 即无压缩格式。

接下来向文件中写入波形,首先要将数据转换成字节码,然后再写,官方文档中有

Wave_write.writeframes(data)
写入音频帧并确保 nframes 是正确的。

因此我们将数组里的数值映射到整型数的整个区间,再写入文件中。

y=y*32768
y_data=y.astype(np.int16).tobytes()#将类型转为字节
file.writeframes(y_data)
file.close()

接下来用一个叫wave editor的软件查看波形

wave editor波形查看软件

百度云地址 提取码: jht6

在这里插入图片描述
可以看到效果刚好是1Hz的正弦波,以上的操作没有问题。

几种波形的生成 Based on Python

接下来把波形生成、写入文件这些封装成函数。
我们每次生成波形需要的参数有模拟频率、采样率、时间长度以及波形,以此作为函数参量。

def createWave(sample_rate= 22050,fa = 100,t_length = 10,mode="square25"):
    T = sample_rate / fa  #周期
    D_Omega = 2*pi/T # 数字角频率
    D_num = int(t_length * sample_rate)# 对应的数字波形点数
    x = np.arange(0,D_num)
    y = np.ones(D_num)
     # 基波
    if mode == "square125": # 方波占空比12.5%
        high = T//8
        y[x%T > high] = -1
    elif mode == "square25": # 方波占空比25%
        high = T//4
        y[x%T > high] = -1
    elif mode == "square50": # 方波占空比50%
        y = np.sin(D_Omega * x)
        y[y>0] = 1
        y[y<0] = -1
    elif mode == "square75": # 方波占空比75%
        high = 3*T//4
        y[x%T > high] = -1
    elif mode == "triangle": # 三角波
        for i in range(len(x)):
            y[i] = abs(1-i%T/T*2)
        y = y - 1 # 向下平移
    elif mode == "noise": # 噪声
        y = np.random.normal(0,1,D_num) ## 我也不知道应该是什么分布的噪声,先用这个吧
    t = x/sample_rate
    return y,t

接下来试着生成这五种波形看看

if __name__ == "__main__":
    mode = ["square125","square25","square50","square75","triangle","noise"]
    for i in range(6):
        y,t = createWave(sample_rate= 22050,fa = 100,t_length = 0.05,mode=mode[i])
        plt.subplot(2,3,i + 1)
        plt.plot(t,y)  #画出一个周期的波形图
    plt.show()

在这里插入图片描述
效果还可以。

接下来是保存波形的函数

def saveWave(y,sample_rate,path = r'wave.wav'):
    file=wave.open(path,'wb')
    file.setnchannels(1)#设置通道数
    file.setsampwidth(2)#设置采样宽
    file.setframerate(sample_rate)#设置采样
    file.setcomptype('NONE','not compressed')#设置采样格式  无压缩
    y=y*32768
    y_data=y.astype(np.int16).tobytes()#将类型转为字节
    file.writeframes(y_data)
    file.close()

我试了试把几个波形叠加起来保存
结果大概是这样的

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

豆沙粽子好吃嘛!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值