来源: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 pythonipython导入它们:

$ 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 库。 在这样做时,你使用了一些你应该非常熟悉的命令行工具:brewpipwhichcdlspython等等...

现在是时候把所有这些放在一个简单的 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...

信号在'yy2`变量中。 现在,改变播放声音的语句,以便在播放之前将信号添加到一起:

...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.pyplay.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 包。 当您编写越来越复杂的程序时,这将是您将一次又一次地使用的东西。