百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

python音乐可视化:好玩的matplotlib南丁格尔玫瑰图版

off999 2024-11-10 10:35 27 浏览 0 评论

效果图:

操作演示:

技术要点:

1 matplotlib的南丁格尔玫瑰图,用极坐标polar制作,并动画显示。

2 pygame新版的播放mp3,但本机的操作系统不能播放mp3,我用pydub做些格式转换。

3 用librosa获取音乐的相关数据和采样。

4 参考代码,并对源代码进行修改,增加,删减,排版和注释,感谢原作者,如有侵权,请联系,定删除。

https://github.com/hahacyd/SimpleMusicVisualizer

====下面分步,讲解代码====

第1步:模块导入

import os
import time
import pygame
import librosa
import numpy as np
from pydub import AudioSegment
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

第2步:窗口的初始化设置

print("开始格式转换,请等待,一会马上就会播放音乐,请欣赏音乐和可视化")
plt.rcParams['axes.unicode_minus']=False  # 负号显示

# 画布的大小和背景颜色设置
fig = plt.figure(facecolor='black',edgecolor='black',figsize=(12,7))
ax = plt.subplot(projection='polar')
ax.patch.set_facecolor('black') #图形背景颜色设置
# 设置显示界面的位置
mngr = plt.get_current_fig_manager()
mngr.window.wm_geometry("+500+200")

第3步:参数设置

# 设置显示的柱状图的个数
bin_nums = 24
# 设置显示的频率范围:(0 ~ 1350 Hz)
frequency_threshold = 1350
# 音乐时长(s)
music_length = 0.0
# 帧时长,即每一帧所需的时长
# 简而言之就是每隔‘sampling_interval’ 秒刷新一次
sampling_interval = 0.05
temp = np.tile(0, bin_nums)  #重复数组,角度
music_play_start_time = 0
current_time = 0
music_fft = np.empty(0)  #创建空数组
bins = np.empty(0)

第4步:核心代码:

# =======polar柱状图,如果是垂直柱状图,就是适当进行修改=======
# 可视化柱子和上头线设置
# 比如选择了'RdBu'色谱,选择分为24段
colors = plt.get_cmap('RdPu',24)
#cmap即colormaps 
#获取图谱使用plt.get_cmap(‘xxx’) 
# 扇形柱子的宽度
width = 2 * np.pi / bin_nums
# 角度和数据
rad = np.cumsum([width] * bin_nums)  # 每个扇形的起始角度
# 扇形柱状图
rects = ax.bar(rad, temp,width=width,color=colors(range(0, bin_nums)),alpha=1,bottom=900)
# 初始化柱状图中的 横线跌落效果
line,= ax.plot(rad, temp, '*', color='white', linewidth=10)

ax.set_theta_zero_location('N')  # 设置极坐标的起点(即0度)在正上方向
ax.grid(False)  # 不显示极轴
ax.spines['polar'].set_visible(False)  # 不显示极坐标最外的圆形
ax.set_yticks([])  # 不显示坐标间隔
ax.set_thetagrids([])  # 不显示极轴坐标

#=======核心代码部分=======

第5步:filter类

class ExpFilter:
    def __init__(self, val=0.0, alpha_decay=0.5, alpha_rise=0.5):
        self.alpha_decay = alpha_decay
        self.alpha_rise = alpha_rise
        self.value = val

    def update(self, value):
        if isinstance(self.value, (list, np.ndarray, tuple)):
            alpha = value - self.value
            alpha[alpha > 0.0] = self.alpha_rise
            alpha[alpha <= 0.0] = self.alpha_decay
        else:
            alpha = self.alpha_rise if value > self.value else self.alpha_decay
        self.value = alpha * value + (1.0 - alpha) * self.value
        return self.value

# 使用filter,来使得柱形图中的变化平缓一些
# alpha_decay和alpha_rise,其值需在0~1之间,分别表示下降和上升的反应速度
# 越大越灵敏,如果都设为1,将失去滤波的效果
# 这里选择了0.3 和 0.6,即下降时较慢,而上升较快
filter = ExpFilter(np.tile(0,bin_nums),alpha_decay=0.30, alpha_rise=0.60)

第6步:函数定义

# 初始化
def init():
    global y_max
    ax.set_ylim(0, y_max)
    return rects

# 更新函数
def update(frame):
    current_time = time.time()
    # 获知当前歌曲的播放进度,以选择此进度下的fft数据
    current_frame = ((current_time - music_play_start_time) //
                     sampling_interval)
    
    # 播放完了,处理
    if current_frame == FRAMES - 1:
        exit()

    # 这里的music_fft是从getBin()获得的
    source = music_fft[int(current_frame)-1]  # 注意这里一般可能不需要-1,根据不同mp3而定
    index_max = y_max - (y_max // 80) < source
    source[index_max] = y_max - (y_max // 80)

    # 更新柱状图
    bins = filter.update(source)

    # 更新柱状图中的横线跌落效果
    line_ydata = line.get_ydata()
    line_ydata -= int(y_max // 30)
    line_index = line_ydata  - int(y_max // 100) < bins
    line_ydata[line_index] = bins[line_index] + int(y_max // 100)
    line.set_ydata(line_ydata)

    for rect, h in zip(rects, bins):
        rect.set_height(h)

    fig.canvas.flush_events()  #刷新
    fig.canvas.draw()   # 重新绘图
    # 图像更新后将保持一帧的时间
    time.sleep(sampling_interval)

    fig.canvas.manager.set_window_title("总共:%d秒;已经播放时间:%d秒"%(round(music_length),
    round(current_time- music_play_start_time, 0))) #窗口标题名设置

# 处理音乐中的每一帧数据
def getBin(y,sr,sampling_interval):
    time1 = time.time()
    # 计算每一帧有多少“采样“,用于计算fft
    fft_interval = int(sr * sampling_interval)
    length = fft_interval // 2
    nums = (sr * bin_nums) // (frequency_threshold * 2)
    batch = length // nums
    result = np.atleast_2d(np.tile(0, bin_nums))

    for i in range(int(music_length // sampling_interval)):
        fft = np.fft.fft(y[fft_interval * i: fft_interval * (i + 1)])

        freqbin = np.array([np.abs(fft[batch * x: batch * (x + 1)]).sum() // sampling_interval
                            for x in range(bin_nums)])
        result = np.vstack([result, freqbin])
    time2 = time.time()
    return result

# 播放指定的歌曲
def play(): 
    pygame.init()
    pygame.mixer.music.stop()
    # 播放音乐
    music = pygame.mixer.music.load(n_audio_path)  # 转换成ogg的临时文件
    pygame.mixer.music.play()

第7步:启动主函数

if __name__ == "__main__":
    # 设置音乐文件的路径
    audio_path = './cwsk.mp3'   #本操作系统,新版pygame不支持mp3,需要转换
    sound = AudioSegment.from_file(audio_path)
    # 转换后放在临时主目录下
    file=sound.export("newsong.ogg", format="ogg")  
    n_audio_path='./newsong.ogg'   #临时文件
    
    y, sr = librosa.load(n_audio_path, sr=None)
    music_length = len(y) / sr
    
    print("时长: %g s 采样率: %g kHz " % (music_length, sr/1000))

    music_fft = getBin(y=y, sr=sr, sampling_interval=sampling_interval)
    y_max = music_fft.max() // 3
    FRAMES = music_fft.shape[0]
    
    ani = FuncAnimation(fig, update, init_func=init, blit=False, interval=0,
                        frames=FRAMES + 1, repeat=False)
    
    play()

    # 记录音乐开始播放的时间
    music_play_start_time = time.time()
    plt.tight_layout()  # 紧凑布局,缩小外边距

    plt.show()  #显示

    plt.pause(music_length)

自己整理,分享出来,希望大家喜欢。

相关推荐

53短视频全部解锁版(五三软件)

欢乐五子棋53关残局解法如下:首先,观察棋盘上的情况,寻找可以利用的棋子。在53关残局中,你可能需要利用棋盘上的已有棋子,构建出连续五子连线。其次,要注意对方的棋子布局,尽量避免被对方阻止。在放置棋子...

cf单机版手机版破解版(cf单机版手游破解版)

想玩这个游戏在应用宝中下载就可以了,应用宝它可是目前面对安卓系统开放的最专业的软件下载平台,里面几乎什么样的软件都有的,而且还都是支持一键下载和自动安装的呢。穿越火线是一款热门的网络游戏,但是如果想要...

腾讯会议下载(腾讯会议下载的文件保存在什么地方了)
腾讯会议下载(腾讯会议下载的文件保存在什么地方了)

1.打开电脑浏览器搜索【腾讯会议】,选择打开软件官网,往下滑动点击【立即下载】。2.在弹出的页面上选择要下载的【安装版本】,支持【windows系统】和【macOS】系统。3.接下来选择文件的【保存位置】,点击【下载】保存安装包。4.下载完...

2026-01-17 11:15 off999

游戏盒子电脑版(电脑板游戏盒子)
游戏盒子电脑版(电脑板游戏盒子)

除了Steam之外,比较有名的电脑游戏盒子有WeGame。WeGame是腾讯游戏平台的升级版本,该平台面向全球及国内玩家,直接将游戏开发者与用户连接起来,为两者创造更多的沟通与互动。WeGame平台提供一站式服务,包括游戏的资讯、购买、下载...

2026-01-17 11:03 off999

欢乐斗地主下载安装(欢乐斗地主下载安装免费 app)

您可以按照以下步骤在华为手机上下载欢乐斗地主游戏:1.打开华为手机上的应用商店(一般为华为应用市场或者AppGallery)。2.在应用商店的搜索栏中输入"欢乐斗地主",然后点击搜...

腾讯游戏全部停服一天(明天腾讯游戏停服一天)

关服停运的游戏通常是没有收益的原因。腾讯游戏通常关服停运的游戏是因为没有成本收益,无法支持游戏的正常运行,所以会进行关服停运,这是最重要的原因。一人之下手游停止运营了,原因是氪金太严重。3年的等待,中...

设置来电铃声50首(免费手机铃声100首)

1.首先找到并点击打开华为手机桌面上的【设置】,2.在设置菜单下点击进入【声音】选项,3.点击【来电铃声】进行设置,如果有两张卡,这里会显示卡1来电铃声、卡2来电铃声,点击选择需要设置电话铃声的卡即可...

10个比1688便宜的拿货网(比阿里巴巴便宜的货源网站)

 比1688便宜的进货渠道有:1、53货源网53货源网主要经营的是3c电子数码。产品的质量及售都是不错的,做3C的朋友可以去看看。2、58食品网该网站主要经营奶制品、饮品等批发;还有许多小零...

诺基亚8800(诺基亚8800e真假图片)

这部手机定位就是高端机,它的做功和机身材质都比较好,用料有皮料,宝石等,还是金属外壳,它卖的不是功能,就是身价,它的定位不同于n73这种街机,价格高买的人就相对比较少,再加上不会大量生产.买8800a...

winkawaks模拟器中文版(winkawaks1.45模拟器)

这个要求汉化包的支持,具体在于WinKawaksRomCenter.dat这个文件要经过汉化才能显示中文的游戏列表。你用英文原版是怎么调也没用的。首先,要下载Winkawaks模拟器软件,然后在模拟...

wps电脑版官方下载(wps电脑版官方下载入口)
  • wps电脑版官方下载(wps电脑版官方下载入口)
  • wps电脑版官方下载(wps电脑版官方下载入口)
  • wps电脑版官方下载(wps电脑版官方下载入口)
  • wps电脑版官方下载(wps电脑版官方下载入口)
木马查杀软件下载(常用的木马查杀工具)

若需鉴定手机是否有病毒,建议您:1.部分手机支持智能管理器(内存管理器),可以通过其中的"设备安全"扫描设备,对设备内存进行检测,查找设备是否存在威胁或有恶意软件。2....

免费ppt软件官方下载(免费ppt软件有哪些)
免费ppt软件官方下载(免费ppt软件有哪些)

1.第一个是优品ppt,首先网站设计的很漂亮,ppt的质量不错,重点是免费;2.第二个是51ppt,里面的模板也都可以免费下载,可以说是非常的良心了,...3.第三个是officeplus,是office的官方网站,出品的模板质量不错,.....

2026-01-17 08:51 off999

免费下载电影的网站(免费下载电影的网站或者app)
免费下载电影的网站(免费下载电影的网站或者app)

电影天堂很多高清电影可以下载1.打开片库网,点击需要下载的影视进入。2.进入到视频播放页面,直接点击屏幕中的下载按钮即可.在电驴里面有这种蓝光电影,你可以去下载。以前用过一个80s电影网,不知道现在还能不能用了,好久没用了,刚出的电影也有的...

2026-01-17 08:43 off999

ie浏览器官网入口(ie浏览器中文版官方下载)

没有手机版本的IE浏览器,所以就没有官方入口这一说法。用户还是使用手机自带的浏览器,或者在应用商店中下载其他的浏览器,比如夸克浏览器、X浏览器、QQ浏览器等等。1、进入手机浏览器,选择三字形的按钮。...

取消回复欢迎 发表评论: