女儿情:对于一段音乐进行频率频谱分析

Posted 卓晴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了女儿情:对于一段音乐进行频率频谱分析相关的知识,希望对你有一定的参考价值。

简 介: 对于一段有筷子、饭盒、橡皮筋组成的乐器演奏的音乐进行分析。对于其音节的准确性讨论。可以看出,该乐器在高音所对应的频率节点还是比较准确,但低音中的(6,7,1)相对偏差比较大。令人惊奇的是,居然伴音7,4频率点恰到好处,这究竟是什么魔法?

关键词 频谱分析音节

音乐频谱 目 录
Contents
音乐来源 读取和显示声音波形 波形时频联合分布 动态显示波形和频谱 峰值频率 数据频率峰值频率 频率直方图 所有音节频率 总 结

 

§01乐频谱


1.1 音乐来源

  今天在微信中友人给我发送了一段有趣的视频。这段视频演示了清新优雅的弹拨乐来自于饭盒上的九条橡皮筋,令人不禁感**:慨飞花摘叶皆可伤人,草木竹石均可为剑,诚不我欺也.**

▲ 图1.1.1 浪漫的音乐

▲ 图1.1.2 西游记主题曲:女儿情

  剩下的问题就是对这段浪漫的音乐进行分析。

  在 如何从MP4视频文件中抽取MP3音频? 利用 格式工程ffmpeg 软件从朋友圈下载的MP4视频中提取了相应的音频。由于原来的视频中音量比较小,使用 Audacity 软件对音频进行了初步处理,提升了音频数据音量。

1.2 读取和显示声音波形

1.2.1 读取波形代码

  利用下面代码读取波形文件,并进行显示。

import sys,os,math,time
import matplotlib.pyplot as plt
from numpy import *
from scipy.io import wavfile

wavefile = '/home/aistudio/work/wave.wav'
sample_rate,sig = wavfile.read(wavefile)

print("sig.shape: ".format(sig.shape), "sample_rate: ".format(sample_rate))

plt.clf()
plt.figure(figsize=(10,6))
plt.plot(sig[:,0])
plt.xlabel("n")
plt.ylabel("wave")
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()

1.2.2 波形文件参数

  可以看到波形文件的采样率以及双声道数据长度。

sig.shape: (1012608, 2)
sample_rate: 44100

1.3 波形时频联合分布

1.3.1 处理代码

from scipy import signal

f,t,Sxx = signal.spectrogram(sig[:, 0],
                             fs=sample_rate,
                             nperseg=8192,
                             noverlap=8000,
                             nfft=8192)

thread = 150000
Sxx[where(Sxx >thread)] = thread
startf = 25
endf = 200

plt.clf()
plt.figure(figsize=(15,7))
plt.pcolormesh(t, f[startf:endf], Sxx[startf:endf,:])
plt.xlabel('Time(s)')
plt.ylabel('Frequency(Hz)')
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()

1.3.2 显示处理结果

▲ 图1.3.1 音乐的是时频联合分布

thread = 50000
Sxx[where(Sxx >thread)] = thread
startf = 0
endf = 350

▲ 图1.3.2 音乐的是时频联合分布

▲ 图1.3.3 音频中的基频和各次谐波

▲ 声音前5秒钟的时频联合分布

▲ 图1.3.5 前两秒中的频谱

(1)完整的显示程序

from headm import *                 # =
from scipy.io import wavfile

wavefile = '/home/aistudio/work/wave.wav'
sample_rate,sig = wavfile.read(wavefile)

printt(sig.shape:, sample_rate:)

plt.clf()
plt.figure(figsize=(10,6))
plt.plot(sig[:,0])
plt.xlabel("n")
plt.ylabel("wave")
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()

from scipy import signal

f,t,Sxx = signal.spectrogram(sig[:sample_rate*5, 0],
                             fs=sample_rate,
                             nperseg=8192,
                             noverlap=8000,
                             nfft=8192)

thread = 50000
Sxx[where(Sxx >thread)] = thread
startf = 0
endf = 350

plt.clf()
plt.figure(figsize=(15,10))
plt.pcolormesh(t, f[startf:endf], Sxx[startf:endf,:])
plt.xlabel('Time(s)')
plt.ylabel('Frequency(Hz)')
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()

1.4 动态显示波形和频谱

1.4.1 音乐数据波形

  下面是音乐的数据波形。可以看到背景的噪声的幅值还是比较大的。

▲ 图1.4.1 音乐数据波形

step_length = sample_rate//10
page_number = 300
overlap_length = step_length // 10

gifpath = '/home/aistudio/GIF'
if not os.path.isdir(gifpath):
    os.makedirs(gifpath)
gifdim = os.listdir(gifpath)
for f in gifdim:
    fn = os.path.join(gifpath, f)
    if os.path.isfile(fn):
        os.remove(fn)

from tqdm import tqdm
for id,i in tqdm(enumerate(range(page_number))):
    startid = i * overlap_length
    endid = startid + step_length

    musicdata = sig[startid:endid,0]

    plt.clf()
    plt.figure(figsize=(10,6))
    plt.plot(musicdata, label='Start:%d'%startid)
    plt.xlabel("Samples")
    plt.ylabel("Value")
    plt.axis([0,step_length, -15000, 15000])
    plt.grid(True)
    plt.legend(loc='upper right')
    plt.tight_layout()
    savefile = os.path.join(gifpath, '%03d.jpg'%id)
    plt.savefig(savefile)
    plt.close()

1.4.2 音乐频谱变化

  下面显示了音乐数据的频谱变化情况。

短时FFT参数:
显示频率:10~2000Hz
时间:100ms
补零长度:400ms

▲ 图1.4.2 音频的频谱变化数据

startf = 10
endf = 2000
startfid = int(step_length * startf / sample_rate*5)
endfid = int(step_length * endf / sample_rate*5)

from tqdm import tqdm
for id,i in tqdm(enumerate(range(page_number))):
    startid = i * overlap_length
    endid = startid + step_length

    musicdata = list(sig[startid:endid,0])
    zerodata = [0]*(step_length*4)
    musicdata = musicdata + zerodata

    mdfft = abs(fft.fft(musicdata))/step_length
    fdim = linspace(startf, endf, endfid-startfid)

    plt.clf()
    plt.figure(figsize=(10,6))
    plt.plot(fdim, mdfft[startfid:endfid], linewidth=3, label='Start:%d'%startid)
    plt.xlabel("Frequency(Hz)")
    plt.ylabel("Spectrum")
    plt.axis([startf,endf, 0, 2000])
    plt.grid(True)
    plt.legend(loc='upper right')
    plt.tight_layout()
    savefile = os.path.join(gifpath, '%03d.jpg'%id)
    plt.savefig(savefile)
    plt.close()

 

§02 值频率


2.1 数据频率峰值频率

  求出数据中频谱峰值频率的变化。

2.1.1 绘制所有频谱峰值

step_length = sample_rate//10
page_number = 500
overlap_length = step_length//5

startf = 10
endf = 2000
startfid = int(step_length * startf / sample_rate*5)
endfid = int(step_length * endf / sample_rate*5)

maxfdim = []
maxadim = []
maxtdim = []

for id,i in tqdm(enumerate(range(page_number))):
    startid = i * overlap_length
    endid &

以上是关于女儿情:对于一段音乐进行频率频谱分析的主要内容,如果未能解决你的问题,请参考以下文章

如何使用频谱分析仪

如何用 FFT 进行频谱分析? [关闭]

饭盒里的女儿情

Win7桌面显示音乐波动 - 音频频谱分析仪

基频测试原理

声音信号基音提取算法基频和谐波处理分析