来源:ApacheCN『USF MSDS501 计算数据科学中文讲义』翻译项目原文:Playing sounds
译者:飞龙
协议:CC BY-NC-SA 4.0
本实验的目标是让您感到惊讶,您可以使用 Python 处理一些音频文件。您将无法获得所有详细信息,但您可以剪切并粘贴此实验来启动 Python 会话。作为次要目标,您将习惯于安装 Python 包和命令行工具。
首先,下载以下两个音频文件,以便我们拥有一些要处理的原材料。
- 来自 Kiss by Prince的初始序列,
Kiss.aiff
- ahhh 声音,
ahhh.mp3
我建议你将它们存储在如下目录中:
/Users/YOURID/msan501/labs/sound
其中YOURID
是您的计算机登录名。 例如,我的登录名是parrt
。在 Linux 上它会像:
/home/YOURID/msan501/labs/sound
安装命令行工具
事实证明,我们将在 Python 中使用的声音库,不知道如何处理 mp3 文件。 我们需要将ahhh.mp3
文件转换为ahhh.wav
,这些库知道如何处理它。 为此,我们将使用名为 mpg123 的工具。
要在 Mac 上安装大多数免费软件,我们使用一个名为 homebrew(家酿啤酒)的程序(从命令行访问只是brew
)。它可能已预先安装在您的计算机上,但如果没有,请阅读说明并进行安装。这是一个切割和粘贴以/usr/bin/ruby...
开头的单行的问题
一旦安装完毕,我们就可以用它来安装mpg123
。 从终端运行以下brew
命令,该命令应该给出指示的输出:
$ brew install mpg123...==> Downloading https://homebrew.bintray.com/bottles/mpg123-1.25.0.el_capitan.bottle.tar.gz######################################################################## 100.0%==> Pouring mpg123-1.25.0.el_capitan.bottle.tar.gz==> Using the sandbox /usr/local/Cellar/mpg123/1.25.0: 26 files, 765.2KB
在 Linux 上,mpg123 的安装是:
sudo apt-get install mpg123
或者:
$ sudo yum install mpg123
将mp3
转换为wav
文件
现在,我们安装了 mpg123,我们可以使用它将.mp3
转换为.wav
文件。 使用cd
(更改目录)命令进入保存ahhh.mp3
文件的目录,并使用ls
列出文件:
$ cd /Users/YOURID/msan501/labs/sound$ lsKiss.aiff ahhh.mp3
使用以下命令转换文件:
$ mpg123 -w ahhh.wav ahhh.mp3 High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3 version 1.25.0; written and copyright by Michael Hipp and others free software (LGPL) without any warranty but with best wishesTerminal control enabled, press 'h' for listing of keys and functions.Playing MPEG stream 1 of 1: ahhh.mp3 ...MPEG 1.0 L III cbr192 44100 j-sComment: 00000000 00000210 000009F5 000000000004FF7B 00000000 0002AB44 00000000 00000000 00000000 00000000 00000000 00000000[0:07] Decoding of ahhh.mp3 finished.
在那个输出中有很多乱码,我们并不关心,但要确保它表示“完成”,并且看起来没有任何错误。 看一下当前目录中的文件,看看是否出现了ahhh.wav
:
$ lsKiss.aiff ahhh.mp3 ahhh.wav
如果您无法弄清楚如何转换为ahhh.wav
,请不要担心。 你可以从我的笔记下载它。
此时,我们已经学会了使用cd
跳转到文件系统中的不同位置,并使用ls
列出目录中的文件。 我们使用brew
作为非 Python 包的install
命令。
安装 Python 包
为了从 Python 读取和播放声音文件,我们需要利用一些现有的 Python 代码。 代码通常以包含库或包的形式提供;这些术语或多或少在实践中同义使用。
- 对于读取声音文件,我们需要 [pysoundfile](http://pysoundfile.readthedoc...。
- 对于播放声音文件,我们需要 [sounddevice](http://python-sounddevice.rea...。
如果我们在安装包之前尝试使用包,那么 Python 执行器会向我们显示如下错误。
---------------------------------------------------------------------------ImportError Traceback (most recent call last)<ipython-input-61-b5992dda2a80> in <module>()----> 1 import soundfile as sfImportError: No module named soundfile
关键是在import
语句中,我们得到错误No module named soundfile
。这不应该搞砸你的一天 - 这只是意味着我们必须安装该软件包。
要安装 Python 包,我们使用pip
(或稍后,conda
)程序。通常这个程序可以快速轻松地完成我们想要的操作,但是很多事情都可能出错。最常见的是你的pip
程序与python
程序不匹配。首先使用which
验证它们是否来自同一个bin
目录:
$ which pip/Users/parrt/anaconda3/bin/pip$ which python/Users/parrt/anaconda3/bin/python$ which python3/Users/parrt/anaconda3/bin/python3
现在,让我们安装pysoundfile
包:
$ pip install pysoundfileCollecting pysoundfile Downloading PySoundFile-0.9.0.post1-py2.py3.cp26.cp27.cp32.cp33.cp34.cp35.cp36.pp27.pp32.pp33-none-macosx_10_5_x86_64.macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.whl (573kB) 100% | | 573kB 1.4MB/s Requirement already satisfied: cffi>=0.6 in /Users/parrt/anaconda2/lib/python2.7/site-packages (from pysoundfile)Requirement already satisfied: pycparser in /Users/parrt/anaconda2/lib/python2.7/site-packages (from cffi>=0.6->pysoundfile)Installing collected packages: pysoundfileSuccessfully installed pysoundfile-0.9.0.post1
LINUX用户:你需要执行conda install libgcc
来使这个声音组件生效。
同样安装其他包:
$ pip install sounddeviceCollecting sounddevice...
为了确保我们已正确安装软件包,我们可以尝试使用交互式 Python shell python
或ipython
导入它们:
$ pythonPython 3.6.5 | packaged by conda-forge | (default, Mar 30 2018, 00:00:55) [GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> import soundfile as sf>>> import sounddevice as sd
这一次,我们的import
语句没有出错。
用 Python 播放声音
此时,您已经转换了一个文件,以便我们的 Python 库可以使用它,并且您已经安装了这些 Python 库。 在这样做时,你使用了一些你应该非常熟悉的命令行工具:brew
,pip
,which
,cd
,ls
,python
等等...
现在是时候把所有这些放在一个简单的 Python 程序中,你可以剪切和粘贴来播放声音。 让我们从代码开始播放Kiss.aiff
文件。 在音频文件的同一目录中创建一个名为play.py
的文件。 您可以使用nano
或其他文本编辑器。 这是代码:
import soundfile as sf # Use this packageimport sounddevice as sd # and this onekiss, samplerate = sf.read('Kiss.aiff') # load Kiss.aiff into kiss variablesd.play(kiss, samplerate) # start playing the musicsd.wait() # wait until music finishes before exiting
使用以下命令从命令行运行此程序:
$ python play.py
现在编辑程序并将'Kiss.aiff'
字符串更改为'ahhh.wav'
:
...kiss, samplerate = sf.read('ahhh.wav')...
再次执行程序,您应该听到播放其他声音文件。
最常见的错误是声音文件没有与代码位于同一目录中。
生成我们自己的声音
在声音章节中,我们看到了如何产生正弦波,当我们将它扔给扬声器时,正弦波会产生纯音。 创建一个puretone.py
文件并在其中放入以下代码。
import numpyimport sounddevice as sdfs = 44100 # sampling frequencyT = 1.5 # secondst = numpy.linspace(0, T, int(T*fs), endpoint=False) # time variabley = numpy.sin(2*numpy.pi*440*t) # pure sine wave at 440 Hzsd.play(y, fs)sd.wait()
从命令行运行它。通过归纳其他程序的执行,您应该知道如何运行这个新程序,它是:
$ python puretone.py
将440
更改为更高的值,如1000
:
...y = numpy.sin(2*numpy.pi*1000*t) # pure sine wave at 1000 Hz...
再次运行时,您应该听到更高的音调。
正如我们在演讲中所做的那样,让我们一起添加两个音调来产生更酷的声音。 带有两个正弦波结构的正弦波代码如下所示:
...y = numpy.sin(2*numpy.pi*440*t) # pure sine wave at 440 Hzy2 = numpy.sin(2*numpy.pi*1000*t) # pure sine wave at 1000 Hz...
信号在'y和
y2`变量中。 现在,改变播放声音的语句,以便在播放之前将信号添加到一起:
...sd.play(y+y2, fs)...
保存程序并运行它。 您应该听到两个声音一起播放为一个声音。
现在,让我们看看这个信号在视觉上是什么样的。 创建一个名为twotonesplot.py
的文件并输入以下代码:
import numpyimport sounddevice as sdimport matplotlib.pyplot as pltfs = 44100 # sampling frequencyT = 1.5 # secondst = numpy.linspace(0, T, int(T*fs), endpoint=False) # time variabley = numpy.sin(2*numpy.pi*440*t) # pure sine wave at 440 Hzy2 = numpy.sin(2*numpy.pi*1000*t) # pure sine wave at 1000 Hzplt.scatter(t[0:1000],(y+y2)[0:1000],s=1)plt.show()
看看您是否可以看到此代码与之前代码之间的关系。 我们有另一个import
语句,它引入了一些绘图代码,我们用它来生成一个散点图,用最后两行替换play
/wait
序列。 除此之外,代码是相同的。 运行该代码,你应该看到一个漂亮的摇摆正弦波,这是两个不同频率的纯正弦波:
<img src="https://gitee.com/wizardforce...; width="100%">
声音处理
减小音量
为了让你相信声波只是数字,让我们从音频文件加载的数字更小。当我们演奏它时会产生什么声音?是的,它应该变得更安静。这是一个名为softer.py
的play.py
程序的版本,它有一个额外的行来减少振幅:
import soundfile as sf # Use this packageimport sounddevice as sd # and this onekiss, samplerate = sf.read('Kiss.aiff') # load Kiss.aiff into kiss variablekiss = kiss * .1 # Reduce amplitude to make quietersd.play(kiss, samplerate) # start playing the musicsd.wait() # wait until music finishes before exiting
该行将数字信号中的每个值除以 10:
kiss = kiss * .1 # Reduce amplitude to make quieter
事实证明,当我们将信号强度除以 10 时,我们的耳朵听到的声音减小一半。(术语分贝(decibel)应该是个双关语,Decimate
意味着除以 10。)
减慢音频(并改变音高)
让我们说我们想加深 Prince 的声音。 我们所要做的就是减慢音乐速度。 要做到这一点,我们所要做的就是玩一玩采样率。 将play.py
文件复制到slow.py
并将play
行更改为:
sd.play(kiss, samplerate*.8) # play the music at 80% speed
现在运行slow.py
并且 Prince 的声音在最后听起来很怪异。 整个东西听起来很慢。 直观地说,降低播放时的采样率会降低速度,因为播放器每秒消耗更少的样本。 这会使声音延长,就像用手指放慢唱片转盘一样。
可以减慢音乐速度并且不更改音高,这在尝试将音乐从音频转换为乐谱时非常有用。构建我所使用的转录软件的人,很好的描述了不改变音高并减慢音乐所涉及的技巧。
答案
您可以在 msan501 类库中找到本实验的所有代码。 这是声音文件。
总结
声音处理是一个非常有趣的迷人话题,你刚刚在这里做了一些尝试。我希望这个实验可以激励您深入了解编程的细节,以便您可以学习为自己构建这些类型的程序。 在第一个项目中,您将了解图像处理,您猜对了,一切都是数字。
您还了解了如何使用命令行安装其他命令行程序和 Python 包。 当您编写越来越复杂的程序时,这将是您将一次又一次地使用的东西。