亲爱的,据我了解您在寻找什么,您正在进入一个称为数字信号处理 (DSP) 的理论领域。这个工程领域来自对离散时间信号的简单分析到复杂的自适应滤波器。一个好主意是将离散时间信号视为一个向量,其中该向量的每个元素都是原始连续时间信号的采样值。一旦你得到向量形式的样本,你就可以对这个向量应用不同的数字信号技术。
不幸的是,在 Python 上,从音频文件转移到 NumPy 数组向量相当麻烦,您可能会注意到……如果您不崇拜一种编程语言,我强烈建议您尝试 MatLab/Octave。Matlab 使从文件中访问样本变得简单。audioread()
为您完成这项任务:) 还有很多专门为 DSP 设计的工具箱。
不过,如果您真的打算为此进入 Python,我将逐步指导您。
1. 获取样品
从文件中获取样本的最简单方法.wav
是:
from scipy.io import wavfile
sampling_rate, samples = wavfile.read(f'/path/to/file.wav')
或者,您可以使用wave
andstruct
包来获取示例:
import numpy as np
import wave, struct
wav_file = wave.open(f'/path/to/file.wav', 'rb')
# from .wav file to binary data in hexadecimal
binary_data = wav_file.readframes(wav_file.getnframes())
# from binary file to samples
s = np.array(struct.unpack('{n}h'.format(n=wav_file.getnframes()*wav_file.getnchannels()), binary_data))
回答你的问题:binary_data
是一个bytes
对象,它不是人类可读的,只能对机器有意义。您可以验证此语句键入type(binary_data)
。如果你真的想了解更多关于这群奇怪的字符,点击这里。
如果您的音频是立体声的(即有 2 个通道),您可以重塑此信号以实现与使用scipy.io
s_like_scipy = s.reshape(-1, wav_file.getnchannels())
每一列都是一个香奈儿。无论哪种方式,从.wav
文件中获得的样本都可用于绘制和理解信号的时间行为。
在这两种备选方案中,从文件中获得的样本都以线性脉冲编码调制 (LPCM)的形式表示
2. 对音频样本进行数字信号处理
我会把这部分留给你 :) 但这是一本带你了解 DSP 的好书。不幸的是,我不知道关于 Python 的好书,它们通常是可怕的书......但不用担心,只要你使用任何编程语言,该理论都可以以相同的方式应用。
不管你拿起什么书,坚持读经典作者,比如 Proakis、Oppenheim 等等……不要在意他们使用的语言编程。有关使用 Python 进行音频 DPS 的更实用指南,请参阅此页面。
3.播放过滤后的音频样本
import pyaudio
p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(wav_file.getsampwidth()),
channels = wav_file.getnchannels(),
rate = wav_file.getframerate(),
output = True)
# from samples to the new binary file
new_binary_data = struct.pack('{}h'.format(len(s)), *s)
stream.write(new_binary_data)
其中wav_file.getsampwidth()
是每个样本的字节数,wav_file.getframerate()
是采样率。只需使用输入音频的相同参数即可。
4. 将结果保存在新.wav
文件中
wav_file=wave.open('/phat/to/new_file.wav', 'w')
wav_file.setparams((nchannels, sampwidth, sampling_rate, nframes, "NONE", "not compressed"))
for sample in s:
wav_file.writeframes(struct.pack('h', int(sample)))
其中nchannels
是通道数,sampwidth
是每个样本的字节数,sampling_rate
是采样率,nframes
是样本总数。