音乐随机播放算法

常见的音乐随机播放算法主要有两种:一是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算法


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python音乐协同过滤算法是一种基于用户行为的推荐算法,其目的是根据用户的历史行为习惯,通过数据分析和挖掘,推荐符合用户兴趣的音乐内容。它利用大量的用户数据作为输入,通过和其他用户相似的行为模式,计算出与目标用户最相似的一组用户,并根据这些用户对音乐的评分和偏好,推荐新的音乐信息给目标用户。 Python音乐协同过滤算法的主要优点在于它使用已经产生的完全数据,而不是假设或者假定数据。它可以比其他基于用户模型或者商品模型的推荐算法更加精准的推荐符合用户兴趣的音乐内容。不过,它也有一些局限性,比如它的推荐结果依赖于已经存在的评分数据,如果数据集大小不够大,则推荐结果可能不够准确。 总的来说,Python音乐协同过滤算法是一种非常有效和广泛应用于音乐推荐领域的算法,它可以通过挖掘大量的用户数据,实现针对不同用户的个性化推荐服务。随着大数据和机器学习技术的不断发展,它将成为人们更加喜爱的音乐推荐算法。 ### 回答2: Python 音乐协同过滤算法是一种基于用户相似度和音乐相似度的推荐算法。在该算法中,首先通过分析用户的历史行为和喜好,计算出不同用户之间的相似度。然后基于用户相似度,选取与当前用户相似度较高的一组“邻居用户”,并找到他们所听的音乐。最后,对于邻居用户中曾经听过但当前用户未曾试听过的音乐,根据它们与当前用户已经听过的音乐之间的相似度,给出推荐值,即推荐程度大小。 具体实现上,可以使用Python中的推荐算法库Surprise实现音乐协同过滤算法。Surprise中主要的类是SVD,它可以用于训练模型,通过随机梯度下降算法优化训练数据,使得模型的预测误差最小化。在训练过程中,可以设置一些模型参数,比如学习率、正则化系数等,以达到更好的训练效果。此外,Surprise还提供了一些评估指标,如RMSE等,可以用于评估模型的性能。 除了Surprise之外,Python中还有其他的音乐推荐算法库,比如LightFM、tffm等,它们也可以实现协同过滤、内容过滤等不同种类的推荐算法,并支持多种不同的数据源,如用户历史行为数据、音乐流派信息、歌词文本等。 总之,Python音乐协同过滤算法是一种高效、灵活、可扩展的推荐算法,可以根据不同的应用场景和需求来进行定制。在实际应用中,需要综合考虑数据质量、算法效率、系统响应速度等因素,以构建出更加优秀的音乐推荐体验。 ### 回答3: Python音乐协同过滤算法是一种机器学习算法,用于对音乐数据进行分析并推荐相似的音乐给用户。该算法是根据用户的兴趣和喜好,以及其他用户的行为数据来推荐相似的音乐。 在Python音乐协同过滤算法中,数据的处理是非常重要的一步。首先,必须对音乐数据进行收集和分类。然后,在计算相似度之前,必须通过数据清洗来处理数据集。这包括去掉重复的音乐数据、去掉没有评分的音乐数据、去掉评分数不足的音乐数据等。 接着,可以使用Python中的scikit-learn 或 pandas对数据进行预处理。这包括从数据集中提取有用的信息,如用户评分、歌曲信息等,并将其转换为机器学习算法可以处理的格式。在处理数据时,可以采用不同的技术,如机器学习的聚类、分类、回归等方法,以及数据挖掘、文本处理等技术,来提高算法的准确性和性能。 最后,使用Python中的协同过滤算法来预测音乐推荐。协同过滤算法是一种基于相似度的算法,它可以通过比较用户的喜好和行为数据来推荐相似的音乐。这里,可以使用CF的两种方法:基于用户的CF 和基于物品的CF 。基于用户的CF是根据用户的历史记录和偏好来推荐相似的音乐,而基于物品的CF是根据音乐的特征和属性来推荐相似的音乐。 总之,Python音乐协同过滤算法是一种有效的方式,用于通过分析和预测用户行为来推荐相似的音乐。这种算法可以被应用于在线音乐服务和社交媒体等领域,以提高用户体验和满意度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值