设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

用Python绘制音乐图谱

2015-4-4 00:32| 发布者: joejoe0332| 查看: 7426| 评论: 0|原作者: 伯乐在线|来自: 伯乐在线

摘要: 在本文中,我们将探讨一种简洁的方式,以此来可视化你的MP3音乐收藏。此方法最终的结果将是一个映射你所有歌曲的正六边形网格地图,其中相似的音轨将处于相邻的位置。不同区域的颜色对应不同的音乐流派(例如:古典 ...

  在本文中,我们将探讨一种简洁的方式,以此来可视化你的MP3音乐收藏。此方法最终的结果将是一个映射你所有歌曲的正六边形网格地图,其中相似的音轨将处于相邻的位置。不同区域的颜色对应不同的音乐流派(例如:古典、嘻哈、重摇滚)。举个例子来说,下面是我所收藏音乐中三张专辑的映射图:Paganini的《Violin Caprices》、Eminem的《The Eminem Show》和Coldplay的《X&Y》。


  为了让它更加有趣(在某些情况下更简单),我强加了一些限制。首先,解决方案应该不依赖于MP3文件中任何已有的ID3标签(例如,Arist,Genre),应该仅仅使用声音的统计特性来计算歌曲的相似性。无论如何,很多我的MP3文件标记都很糟糕,但我想使得该解决方案适用于任何音乐收藏文件,不管它们的元数据是多么糟糕。第二,不应使用其他外部信息来创建可视化图像,需要输入的仅仅是用户的MP3文件集。其实,通过利用一个已经被标记为特定流派的大型歌曲数据库,就能提高解决方案的有效性,但是为了简单起见,我想保持这个解决方案完全的独立性。最后,虽然数字音乐有很多种格式(MP3、WMA、M4A、OGG等),但为了使其简单化,这里我仅仅关注MP3文件。其实,本文开发的算法针对其他格式的音频也能很好地工作,只要这种格式的音频可以转换为WAV格式文件。


  创建音乐图谱是一个很有趣的练习,它包含了音频处理、机器学习和可视化技术。基本步骤如下所示:

  1. 转换MP3文件为低比特率WAV文件。
  2. 从WAV元数据中提取统计特征。
  3. 找到这些特征的一个最佳子集,使得在这个特征空间中相邻的歌曲人耳听起来也相似。
  4. 为了在一个XY二维平面上绘图,使用降维技术将特征向量映射到二维空间。
  5. 生成一个由点组成的六角网格,然后使用最近邻技术将XY平面上的每一首歌曲映射六角网格上的一个点。
  6. 回到原始的高维特征空间,将歌曲聚类到用户定义数量的群组中(k=10能够很好地实现可视化目的)。对于每个群组,找到最接近群组中心的歌曲。
  7. 在六角网格上,使用不同的颜色对k个群组中心的那首歌曲着色。
  8. 根据其他歌曲在XY屏幕上到每个群组中心的距离,对它们插入不同的颜色。

  下面,让我们共同看看其中一些步骤的详细信息。


MP3文件转换成WAV格式

  将我们的音乐文件转换成WAV格式的主要优势是我们可以使用Python标准库中的“wave”模块很容易地读入数据,便于后面使用NumPy对数据进行操作。此外,我们还会以单声道10kHz的采样率对声音文件下采样,以使得提取统计特征的计算复杂度有所降低。为了处理转换和下采样,我使用了众所周知的MPG123,这是一个免费的命令行MP3播放器,在Python中可以很容易调用它。下面的代码对一个音乐文件夹进行递归搜索以找到所有的MP3文件,然后调用MPG123将它们转换为临时的10kHz WAV文件。然后,对这些WAV文件进行特征计算(下节中讨论)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import subprocess
import wave
import struct
import numpy
import csv
import sys
 
def read_wav(wav_file):
    """Returns two chunks of sound data from wave file."""
    w = wave.open(wav_file)
    n = 60 * 10000
    if w.getnframes() < n * 2:
        raise ValueError('Wave file too short')
    frames = w.readframes(n)
    wav_data1 = struct.unpack('%dh' % n, frames)
    frames = w.readframes(n)
    wav_data2 = struct.unpack('%dh' % n, frames)
    return wav_data1, wav_data2
 
def compute_chunk_features(mp3_file):
    """Return feature vectors for two chunks of an MP3 file."""
    # Extract MP3 file to a mono, 10kHz WAV file
    mpg123_command = '..mpg123-1.12.3-x86-64mpg123.exe -w "%s" -r 10000 -m "%s"'
    out_file = 'temp.wav'
    cmd = mpg123_command % (out_file, mp3_file)
    temp = subprocess.call(cmd)
    # Read in chunks of data from WAV file
    wav_data1, wav_data2 = read_wav(out_file)
    # We'll cover how the features are computed in the next section!
    return features(wav_data1), features(wav_data2)
 
# Main script starts here
# =======================
 
for path, dirs, files in os.walk('C:/Users/{敏感词}/Music/'):
    for f in files:
        if not f.endswith('.mp3'):
            # Skip any non-MP3 files
            continue
        mp3_file = os.path.join(path, f)
        # Extract the track name (i.e. the file name) plus the names
        # of the two preceding directories. This will be useful
        # later for plotting.
        tail, track = os.path.split(mp3_file)
        tail, dir1 = os.path.split(tail)
        tail, dir2 = os.path.split(tail)
        # Compute features. feature_vec1 and feature_vec2 are lists of floating
        # point numbers representing the statistical features we have extracted
        # from the raw sound data.
        try:
            feature_vec1, feature_vec2 = compute_chunk_features(mp3_file)
        except:
            continue



酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部