`
mmdev
  • 浏览: 12845915 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

音乐随机播放算法

 
阅读更多

常见的音乐随机播放算法主要有两种:一是Shuffle算法;二是Random算法。

一Shuffle算法

Shuffle算法和排序算法正好相反,是从有序到乱序的一个过程,俗称洗牌算法。它将播放列表中的歌曲顺序打乱,变成一个和原来歌曲顺序没有任何关系的乱序的播放列表,之后进行歌曲的播放,并支持当用户点击“上一首”时,能够回到刚刚播放的那一首歌曲。

二Random算法

Random算法是在选取即将播放的歌曲时,进行一个随机数的运算,得到即将播放的歌曲在播放列表中的索引,播放列表本身并没有被打乱,只是利用随机函数从播放列表中选取一首歌曲进行播放而已。

现在比较普遍的随机数生成算法是基于线性同余算法实现的,例如C语言标准库函数rand()就是利用它产生随机数的。线性同余算法能够产生均匀分布的随机数,但是它依赖于给定的随机数的上限,如果上限越小,产生的随机数重复的概率就越大。

Random算法另一个缺陷是当点击“上一首”时,跟“下一首”功能完全一样,都是重新生成随机数,并利用它从播放列表中选取歌曲进行播放,而不会回到刚刚播放的那一首歌。当然,这个缺陷可以通过提供历史记录来弥补,只是需要花费额外的空间。

三随机函数

上面两种算法的关键都是随机函数,下面介绍Java和C两种语言中随机函数的使用。

3.1)Java中的随机函数

Java是采用线性同余算法产生随机数的,优点是随机性好,周期长,速度快,易于计算机软件实现,缺点是产生的随机数受数学规律的制约,具有周期性和相关性,只能产生伪随机序列。JDK提供的随机数生成方式有两种:

3.1.1)Math.random()函数

该函数返回0到1区间中的某个double值,源码实现如下:

    private static Random randomNumberGenerator;

    private static synchronized Random initRNG() {
        Random rnd = randomNumberGenerator;
        return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd;
	}
	
    public static double random() {
        Random rnd = randomNumberGenerator;
        if (rnd == null) rnd = initRNG();
        return rnd.nextDouble();
    }
可见,该函数底层是调用Random类实现的,首次调用random函数时,静态成员变量randomNumberGenerator为空,因此将调用Random类的构造函数进行初始化,随后每次调用random函数randomNumberGenerator不再为空,将不会再实例化Random类,因此,每次调用Math.random()函数用到的都是同一个种子,也就是首次调用的系统时间产生的种子。

3.1.2)Random类

位于Java.util包中,该类有两个构造函数,实现如下:

    public Random() {
        this(seedUniquifier() ^ System.nanoTime());
	}
    public Random(long seed) {
        this.seed = new AtomicLong(initialScramble(seed));
    }
可见,构造函数默认使用当前的系统时间产生种子,用于初始化Random对象。之后就可以调用各种next*函数来获取各种类型的随机数,如nextBytes,nextInt,nextDouble,nextGaussian等等。

3.2)C/C++中的随机函数

C/C++中最常用的生成伪随机数的方法是C标准库提供的rand()函数,它定义在stdlib.h文件中,能够返回0~RAND_MAX之间均匀分布的伪随机数(RAND_MAX至少为32767,一般默认为32767)。

直接调用rand(),每次生成的伪随机序列是相同的,因为rand()在生成随机数时会使用一个种子(默认值是1),作为计算随机数的初始值,如果种子相同,那么生成的伪随机序列也将是一样的。解决的办法很简单,就是每次使用不同的种子来调用rand()函数,srand()函数就是用来设置rand()函数产生随机数时使用的种子的。

srand()函数原型如下:

void srand(
   unsigned int seed 
);
srand()和rand()配合使用的示例如下:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main( void )
{
   int i;

   /* Seed the random-number generator with current time so that
    * the numbers will be different every time we run.
    */
   srand( (unsigned)time( NULL ) );

   /* Display 10 numbers. */
   for( i = 0;   i < 10;i++ )
      printf( "  %6d\n", rand() );
}
需要注意的一点是,上面代码在生成多个随机数时,要将srand()放到for循环的外面,否则上面输出的10个随机数都将是一样的,因为计算机运行速度太快,导致time()函数执行的结果没来得及改变。详见下图。




四音乐随机播放算法的Shuffle实现

4.1)C/C++版本

#include <cstdlib>  
#include <iostream>  
using namespace std;  
 
//得到范围start~end之间的随机数 
int rand(int start, int end)  
{  
    return rand()%(end - start) + start;  
}  
  
void swap(int* a, int* b)  
{  
    *a = *a ^ *b;  
    *b = *a ^ *b;  
    *a = *a ^ *b;  
}  
void shuffle(int a[], int len)  
{  
    int key;  
    srand((unsigned int)time(NULL));//srand应该放在for循环之外 
    for(int i = 0; i< len; i++)  
    {  
        key = rand(0, len);  
        printf("key = %d\n", key);
        swap(a[i], a[key]);  //乱序 
    }  
}  
  
int main(int argc, char *argv[])  
{  
    int a[8]={3, 5, 7, 2, 12, 1, 8, 6};  
    shuffle(a, 8);  
    for(int i = 0; i < 8; i++)  
    {  
        printf("%d\n", a[i]);  
    }  
    system("pause");  
    return 0;  
}

4.2)Java版本
import java.util.Random;

public class ASCE {

	public static void main(String arg[]) {
		String[] musicUrl = { "/music/1.mp3", "/music/2.mp3", "/music/3.mp3",
				"/music/4.mp3", "/music/5.mp3", "/music/6.mp3", "/music/7.mp3",
				"/music/8.mp3", "/music/9.mp3", "/music/10.mp3" };

		shuffle(musicUrl);
		for (String music : musicUrl) {
			System.out.println(music);
		}
	}

	public static void shuffle(String[] musicUrl) {
		int key;
		String temp;
		Random rand = new Random();

		for (int i = 0; i < musicUrl.length; i++) {
			key = rand.nextInt(musicUrl.length - 1);
			temp = musicUrl[i];
			musicUrl[i] = musicUrl[key];
			musicUrl[key] = temp;
		}
	}
}

现成的Shuffle库算法

其实无论在C++还是Java中,都已经实现了Shuffle算法,在实际项目开发中,如果不是有特殊要求的话,完全没有必要自己去实现Shuffle算法,下面就来看看已有的Shuffle算法。

5.1)C++中的Shuffle算法

C++STL中的函数random_shuffle()就是用来对一个元素序列进行随机重新排序的算法,函数原型如下:

template<class RandomAccessIterator>
   void random_shuffle(
      RandomAccessIterator _First, //指向序列首元素的迭代器
      RandomAccessIterator _Last  //指向序列最后一个元素的下一个位置的迭代器
   );
template<class RandomAccessIterator, class RandomNumberGenerator>
   void random_shuffle(
      RandomAccessIterator _First,
      RandomAccessIterator _Last,
      RandomNumberGenerator& _Rand //调用随机数产生器的函数
   );

具体用法可参见:http://blog.csdn.net/ACE1985/article/details/5868682


5.2)Java中的Shuffle算法

Collections类中实现了Shuffle算法,这个类位于java.util包中,有两个重载函数,下面直接看源码:

    public static void shuffle(List<?> list) {
        Random rnd = r;
        if (rnd == null)
            r = rnd = new Random();
        shuffle(list, rnd);
    }
    private static Random r;

    public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));

            // Dump array back into list
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

参考文献:

1)http://www.ifanr.com/29498从随机播放算法看iPod的细节之美

2)http://blog.csdn.net/cstn_kdlx/article/details/7326516随机数生成问题小结

3)http://blog.csdn.net/hcy0727/article/details/7581671洗牌算法

4)http://blog.csdn.net/chosen0ne/article/details/6129315随机播放CD

5)http://blog.csdn.net/ACE1985/article/details/5868682random_shuffle()和transform算法


分享到:
评论

相关推荐

    spotify-true-shuffle:用于 Spotify 的开源音乐随机播放和播放器 Web 应用程序

    TrueShuffle:用于 Spotify 的开源音乐随机播放 Web 应用程序和播放器 动机 在让 Spotify 从我的播放列表中重复播放相同的 40-50 首歌曲(总共超过 1000 首歌曲)之后,我完成了他们的随机播放算法。 TrueShuffle 是...

    定时播放音乐系统

    该款软件是为学校、工矿等单位专门设计的全自动音乐打铃软件,定时播出功能强大,以周为单位,可以在任意天任意时间设定播放音乐铃声。...支持目录播放,可自由选择是否搜索子目录,顺序或乱序播放目录内的音乐;

    【毕业设计】基于大数据个性化音乐推荐算法分析.rar

    本文针对传统基于用户或者基于物品的协同过滤推荐方法在复杂场景下对用户进行音乐推荐占用内存大计算速度慢等缺点,提出一种基于LightGBM决策树算法的音乐推荐算法,使用相关性分析和稳定性选择中的随机逻辑回归进行...

    和声搜索(HS) 全局优化算法 的纯 Python 实现

    在 HS 算法中,每个音乐家(= 决策变量)演奏(= 生成)一个音符(= 一个值),以便一起找到最佳和声(= 全局最优)。 pyHarmonySearch 支持连续变量和离散变量,并且可以利用Python 的 multiprocessing 模块进行...

    Karplus-Strong算法输出音乐泛音

    在吉他上拨弦时,乐器产生了不同强度...我们还会创建一种方式,随机演奏它们,并学习如何做到以下几点:用Python的deque类实现环形缓冲区:使用numpy数组和ufuncs;用pygame播放WAV文件;用matplotlib绘图;演奏五声音阶。

    粒子群优化算法及其在SAT问题matlab源码

    粒子群优化算法由Dr.Eberhart 和Dr.Kenney 于1995年提出,它是受到鸟群或者鱼群的社会行为的启发而形成的一种基于种群的随机优化技术。粒子群优化算法属于进化算法,具有进化计算的基本特征。例如这个系统也是最初被...

    【matlab】基于BP算法和遗传算法的自适应噪声抵消器

    变异率也是影响新个体产生的一个因素,变异率小,产生个体少,变异率太大,又会使遗传算法变成随机搜索,一般取变异率为0.0001~0.1。 由仿真结果得知,GA与BP算法的混合算法不论是在运行速度还是在运算精度上都较...

    一种新的高效大型音乐数据库查询算法 (2006年)

    在基于哼唱的音乐信息检索领域中,查询处理算法一直是一个重要的研究课题。根据人对乐曲相似理解的实验结果,设计了新的基于单侧连续匹配的可容错的近似匹配的算法。此算法采用n-gram的顺序hash索引加快了可容错的...

    用Rust实现 的算法音乐创作/制作 DSL_rust_代码_下载

    DAWPL 翻译为 SuperCollider,一种流行且功能强大的面向 DSP 的算法音乐创作语言。DAWPL 旨在作为 SuperCollider 的音频/DSP 功能与 Rust 的句法功能、其宏系统以及 DAWPL 的音乐理论和组织抽象之间的桥梁。 可能的...

    AIComposer使用遗传算法和 MIDI 文件输入来 创作音乐_Swift_代码_下载

    要收听预先存在的乐曲的播放,请在表中选择它并单击“播放”。 要创作一部新作品,请输入多个基因(20-60 最好)和世代(300-500 最好,但需要很长时间) 单击“撰写”。 该字段将在运行算法时显示信息。 笔记: ...

    论文研究-基于特征旋律挖掘的二阶马尔可夫链在算法作曲中的研究与应用.pdf

    首先针对算法作曲领域内已有的各类研究做了资源整合、归纳,在此基础上,结合平时的探究与思考尝试设计和提出一种新的用于音乐片段分析与特征旋律挖掘的ISM(interval sequence mining)算法,即音程序列挖掘算法。...

    MATLAB源码:图挖掘算法论文的解析

    随机归类算法是通过从子图集中随机地抽取一定数量的子图进行同构分类,是一种近似的算法;Hamilton子图的挖掘算法旨在挖掘特定类型(具有Hamilton回路)的子图,以减少搜索结果集。最后对5个真实生物网络进行了仿真实验...

    Julia中的算法音乐创作_julia_代码_下载

    Stochatto 是一个 Julia 包,旨在促进算法音乐创作的有效研究。这个名字的意思是玩文字游戏,混合术语stochastic,一个描述随机过程的数学术语,和staccato,一个表示简短和标点符号发音的音乐术语。

    基于Android手机平台的音乐播放器-毕业论文

    音乐播放器还包括一系列自定义选项,例如创建播放列表、随机播放歌曲和调整均衡器设置以适应个人偏好等。总的来说,我的毕业论文旨在为音乐发烧友提供一款不仅功能强大而且使用愉悦的音乐播放器。

    粒子群函数论文中产生随机数的matlab代码

    本文提出了一种改进的PSO算法,具体信息在音乐论文www.xyclww.com/post/30.html在算法中重新定义最优粒子并且采用适应度定标缩放粒子适应度值来控制粒子选作最优粒子的概率。从仿真结果看出改进方法的优化精度比较好...

    基于Java(JSP)+MySQL实现深度学习的音乐推荐系统【100013097】

    个性化推荐模型使用了 随机梯度下降(SGD)、 K近邻分类算法(KNN)、协同过滤等传统机器学习领域算法进行音乐推荐的,同时使用了类似于Word2vec的词袋模型和词向量模型来对歌词进行文本处理,构建了异构文本网络,...

    大一时做的java五子棋(人机+双人+网络对战+聊天+JMF音乐播放)

    大一时做的五子棋(人机+双人+网络对战+聊天+JMF音乐播放) 可能代码有点乱,但是注释还挺多的,今天偶然发现,课供初学者学习, 人机对战使用自己编写的算法 棋盘完全是图形界面 可以双人游戏 可以显示下棋顺序 可以...

    Android-Music-App-Beta:插入耳机时自动播放音乐。音乐类型将基于偏好运动水平

    Android-Music-App-Beta 插入耳机时自动播放音乐。... 因此,如果用户在锻炼时听金属,而在坐下时听说唱,学习算法将检测这种关系的强度,并相应地播放音乐。 随着收集到的数据越来越多,算法变得“更智能

    论文研究-支持得分矩阵的音乐检索技术.pdf

    此外,基于得分矩阵提出NA匹配算法和两种加速分段计分方法,分别是顺序前瞻计分SLS算法和置换矩阵前瞻计分PLA算法。实验结果表明所提出的基于得分矩阵的音乐检索技术能够快速有效地返回查询结果,同时PLA算法具有更...

    音调聚类和音乐推荐系统

    我们利用诸如Logistic回归,朴素贝叶斯分类器,神经网络和随机森林分类器之类的分类算法来识别音乐曲目的流派。 我们还应用了K-means聚类算法来创建歌曲簇,并推荐用户最可能喜欢的歌曲。 储存库内容: 音乐分析...

Global site tag (gtag.js) - Google Analytics