音乐频谱可视化
现成的projectM项目能做到这件事情。
自己写出来的代码,应该能在linux系统上运行。就是播放现成的音频文件,同时读取音频数据,绘制频谱图
from pydub import AudioSegment
from pydub.playback import play
import multiprocessing
import wave
import numpy as np
import scipy
import matplotlib.pyplot as plt
import matplotlib.animation as animation
music_fn='zaifeixing.wav'
times=4
class Scope:
def __init__(self,ax,times,fr,frames):
self.ax=ax
self.times=times
self.fr=fr
self.frames=frames
self.i=0
def paint(self,j):
self.ax.cla()
n=self.fr//self.times
freq_spectra=scipy.fft.fft(self.frames[self.i*n:(self.i+1)*n])
abs_freq=np.abs(freq_spectra)
x=np.arange(n//2)*self.fr*2/n
x[0]*=2
self.ax.plot(x,abs_freq[:n//2])
self.i+=1
def visualize_freq_spectra(times,fr,frames):
fig,ax=plt.subplots()
scope=Scope(ax,times,fr,frames)
ani=animation.FuncAnimation(fig,scope.paint,interval=1000//times)
plt.show()
def play_music(music_fn):
song=AudioSegment.from_wav(music_fn)
play(song-15)
wav=wave.open(music_fn,'rb')
frames=wav.readframes(wav.getnframes())
frames=np.frombuffer(frames,dtype=np.short).reshape((-1,2)).T[0]
fr=wav.getframerate()
t=multiprocessing.Process(target=visualize_freq_spectra,args=(times,fr,frames))
t.daemon=True # 非阻塞
t.start()
play_music(music_fn)
北桥苏写的代码,根据系统的混响声音(扬声器加麦克风?)进行律动,首先,在系统设置-系统-声音-所有声音设备-立体声混音-属性里设置允许应用和Windows将此设备用于音频,且在更多声音设置里面将立体声混音设为默认设备,在立体声混音的属性-高级里取消勾选允许程序独占控制此设备,然后运行下述代码,但是pyaudio还是无法采集到系统声音,因此此段代码无法实现预期的功能。
import pyaudio
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import wave
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 4096
# CHUNK = 1024
WAVE_OUTPUT_FILENAME = 'audio_output.wav'
# 获取内录设备序号,在windows操作系统上测试通过,hostAPI = 0 表明是MME设备
def findInternalRecordingDevice(p):
# 要找查的设备名称中的关键字
target = '立体声混音'
# 逐一查找声音设备
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
print(devInfo)
if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
# print('已找到内录设备,序号是 ',i)
return i
print('无法找到内录设备!')
return -1
# Initialize PyAudio
audio = pyaudio.PyAudio()
# 这里input_device_index的2就是系统内录设备索引
stream = audio.open(input_device_index=findInternalRecordingDevice(audio),
format=FORMAT,
channels=1,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
plt.ion()
fig, ax = plt.subplots()
x = np.arange(0, CHUNK)
line, = ax.plot(x, np.zeros(CHUNK))
ax.set_xlim(0, CHUNK)
ax.set_ylim(-32768, 32767)
wave_output_file = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wave_output_file.setnchannels(CHANNELS)
wave_output_file.setsampwidth(audio.get_sample_size(FORMAT))
wave_output_file.setframerate(RATE)
def update_plot(data):
print(data)
line.set_ydata(data)
fig.canvas.draw()
fig.canvas.flush_events()
def display_audio_waveform():
while True:
try:
audio_data = np.frombuffer(stream.read(CHUNK), dtype=np.int16)
# update_plot(audio_data*500)
update_plot(audio_data)
wave_output_file.writeframes(audio_data)
except KeyboardInterrupt:
break
display_audio_waveform()
stream.stop_stream()
stream.close()
audio.terminate()
wave_output_file.close()
print('Audio saved to', WAVE_OUTPUT_FILENAME)
参考链接:
如何用 Python 实现一个 “系统声音” 的实时律动挂件
创建于2407111417,修改于2407111417