• 【算法】—— 随机音乐的播放算法


    随机播放音乐,这个功能太普通以至于以前从未考虑过其背后实现逻辑。

    Random还是shuffle

    我们经常使用的随机播放功能,在外国同行口中并不是叫Random播放,而是叫Shuffle,洗牌的意思。

    为什么不是Random?来看两个例子。

    在Spotify成立之初,他们使用一种叫「Fisher-Yates shuffle」的算法去产生一个完全随机(perfectly random )的播放列表,这个算法据说非常简单,只需3行代码搞定,不过它存在致命弱点。

    上图中,每种颜色代表一位歌手,也就是说我的列表里有绿色歌手的4首歌,红色歌手的2首歌,黑色歌手的2首歌。

    图中上下两行都是运行Fisher-Yates算法可能产生的播放列表,请问这两个列表出现的概率哪个更大呢?

    答案是一样大,完全随机算法下,每一首歌出现在每个位置的概率是一样的。你可能认为这怎么可能,前面已经出现3次绿色歌手的歌了,下一次出现概率应该很小了吧。错了,算法是没有记忆的,除非你告诉它,下一首不允许播放绿色歌手的歌,否则它播放绿色歌手的歌的概率还是50%。

    再来看个例子,假设你播放列表里有10首摇滚乐(A),11首乡村乐(B),11首爵士乐(C),下面是我自己用Python的random函数生成的序列:

    A A A A C C C B C B B A C B C B B B B A B C B A C A C C A A C B

    可以看出,这个列表里前半段和后半段基本上没有B出现,尤其是前面连续4个A和3个B,这样的结果是无法令人满意的,一点均衡性都没有。

    回头再想,我们为什么要随机播放?因为我们不知道要听什么,我们想要一个随性的播放列表,我们不想专门听某一位歌手的或某一张专辑的曲目,我们不想按照平常循环的顺序播放,我们想换换口味有点新意,所以我们把这个选择权交给软件本身去做,如果软件接连给你播放同一个歌手或同一张专辑的曲目,那就违背我们随机的目的了。所以好的随机播放列表应该做到均衡分布,同一个流派、同一个歌手、同一种专辑下的音乐彼此之间相距越远越好。

    还是上面这个例子,好的播放列表应该是下面这样的:

    A B C B C A B A C B A C B C A B C A C B A B C A C B A C B C A B

    shuffle播放算法

    那么如何生成上面这个均衡的播放列表呢?博主Martin Fiedler给了一个思路。

    1)将列表中的歌曲按流派、歌手、专辑等逻辑范式分组,给这个组里的音乐设定一个随机播放顺序;
    2)接下来把每个分组的曲目通过合并算法组成一个完整的播放列表。

    很简单吧,仅仅两步而已。接下来看看合并算法是怎么一回事。假设在第一步我们得到了下面的分组:

    将每个分组扩充到和最大分组相等的长度,比如给绿色分组填充8首「静默」歌曲,让该组长度等于12。填充的时候应尽量让组中的音乐均衡分布列表中。

    每个分组都填充完毕后,就开始合并新列表了,从每个分组的第1列按随机顺序取出歌曲放在新列表中。

    再取出第2列按随机顺序取出歌曲放在新列表中。

    第3列。需要注意的是,假如第2次取出的是黄-红-蓝,第3次取出蓝-黄-红-绿,那么就会有两个蓝色分组的歌曲接连出现的情况,这个时候需要把第3次拿出的歌曲首尾互换,最后得出绿-黄-红-蓝的顺序。

    就是shuffle播放背后的大概逻辑了,难的不是合并算法,而是填充分组的算法,个人感觉。

  • 相关阅读:
    ip聚合(百度之星资格赛1003)
    encoding(hdoj1020)
    Candy Sharing Game(hdoj1034)
    you can Solve a Geometry Problem too(hdoj1086)
    Holding Bin-Laden Captive!(hdoj1085)代码并未完全看懂
    Computer Transformation(hdoj 1041)
    Digital Roots(hdoj1013)
    humble number(hd1058)
    FatMouse' Trade(hdoj1009)
    1021 Fibonacci Again (hdoj)
  • 原文地址:https://www.cnblogs.com/bopo/p/9263007.html
Copyright © 2020-2023  润新知